Search in sources :

Example 11 with JCFieldAccess

use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project error-prone by google.

the class ArrayEquals method matchMethodInvocation.

/**
   * Suggests replacing with Arrays.equals(a, b). Also adds the necessary import statement for
   * java.util.Arrays.
   */
@Override
public Description matchMethodInvocation(MethodInvocationTree t, VisitorState state) {
    String arg1;
    String arg2;
    if (instanceEqualsMatcher.matches(t, state)) {
        arg1 = ((JCFieldAccess) t.getMethodSelect()).getExpression().toString();
        arg2 = t.getArguments().get(0).toString();
    } else if (staticEqualsMatcher.matches(t, state)) {
        arg1 = t.getArguments().get(0).toString();
        arg2 = t.getArguments().get(1).toString();
    } else {
        return NO_MATCH;
    }
    Fix fix = SuggestedFix.builder().replace(t, "Arrays.equals(" + arg1 + ", " + arg2 + ")").addImport("java.util.Arrays").build();
    return describeMatch(t, fix);
}
Also used : SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Fix(com.google.errorprone.fixes.Fix) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess)

Example 12 with JCFieldAccess

use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project error-prone by google.

the class ArrayHashCode method matchMethodInvocation.

/**
   * Wraps identity hashcode computations in calls to {@link java.util.Arrays#hashCode} if the
   * array is single dimensional or {@link java.util.Arrays#deepHashCode} if the array is
   * multidimensional.
   *
   * <p>If there is only one argument to the hashcode method or the instance hashcode method is
   * used, replaces the whole method invocation.  If there are multiple arguments, wraps any that
   * are of array type with the appropriate {@link java.util.Arrays} hashcode method.
   */
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
    SuggestedFix.Builder fix = null;
    Types types = state.getTypes();
    if (jdk7HashCodeMethodMatcher.matches(tree, state)) {
        // java.util.Objects#hashCode takes a single argument, so rewrite the whole method call
        // to use Arrays.hashCode/deepHashCode instead.
        fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(tree.getArguments().get(0), types));
    } else if (instanceHashCodeMethodMatcher.matches(tree, state)) {
        // Rewrite call to instance hashCode method to use Arrays.hashCode/deepHashCode instead.
        fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(((JCFieldAccess) tree.getMethodSelect()).getExpression(), types));
    } else if (varargsHashCodeMethodMatcher.matches(tree, state)) {
        // com.google.common.base.Objects#hashCode
        if (tree.getArguments().size() == 1) {
            // If only one argument, type must be either primitive array or multidimensional array.
            // Types like Object[], String[], etc. are not an error because they don't get boxed
            // in this single-argument varargs call.
            ExpressionTree arg = tree.getArguments().get(0);
            Type elemType = types.elemtype(ASTHelpers.getType(arg));
            if (elemType.isPrimitive() || types.isArray(elemType)) {
                fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(arg, types));
            }
        } else {
            // If more than one argument, wrap each argument in a call to Arrays#hashCode/deepHashCode.
            fix = SuggestedFix.builder();
            for (ExpressionTree arg : tree.getArguments()) {
                if (types.isArray(ASTHelpers.getType(arg))) {
                    fix.replace(arg, rewriteArrayArgument(arg, types));
                }
            }
        }
    }
    if (fix != null) {
        fix.addImport("java.util.Arrays");
        return describeMatch(tree, fix.build());
    }
    return Description.NO_MATCH;
}
Also used : Types(com.sun.tools.javac.code.Types) MatchType(com.google.errorprone.matchers.ChildMultiMatcher.MatchType) Type(com.sun.tools.javac.code.Type) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 13 with JCFieldAccess

use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project error-prone by google.

the class Matchers method selectedIsInstance.

/**
   * Returns true if the expression is a member access on an instance, rather than a static type.
   * Supports member method invocations and field accesses.
   */
public static Matcher<ExpressionTree> selectedIsInstance() {
    return new Matcher<ExpressionTree>() {

        @Override
        public boolean matches(ExpressionTree expr, VisitorState state) {
            if (!(expr instanceof JCFieldAccess)) {
                // TODO(cushon): throw IllegalArgumentException?
                return false;
            }
            JCExpression selected = ((JCFieldAccess) expr).getExpression();
            if (selected instanceof JCNewClass) {
                return true;
            }
            Symbol sym = ASTHelpers.getSymbol(selected);
            return sym instanceof VarSymbol;
        }
    };
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) InstanceMethodMatcher(com.google.errorprone.matchers.method.MethodMatchers.InstanceMethodMatcher) AnyMethodMatcher(com.google.errorprone.matchers.method.MethodMatchers.AnyMethodMatcher) StaticMethodMatcher(com.google.errorprone.matchers.method.MethodMatchers.StaticMethodMatcher) ConstructorMatcher(com.google.errorprone.matchers.method.MethodMatchers.ConstructorMatcher) VisitorState(com.google.errorprone.VisitorState) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Symbol(com.sun.tools.javac.code.Symbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) ExpressionTree(com.sun.source.tree.ExpressionTree) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol)

Example 14 with JCFieldAccess

use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project ceylon-compiler by ceylon.

the class Attr method visitApply.

/** Visitor method for method invocations.
     *  NOTE: The method part of an application will have in its type field
     *        the return type of the method, not the method's type itself!
     */
public void visitApply(JCMethodInvocation tree) {
    // The local environment of a method application is
    // a new environment nested in the current one.
    Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
    // The types of the actual method arguments.
    List<Type> argtypes;
    // The types of the actual method type arguments.
    List<Type> typeargtypes = null;
    Name methName = TreeInfo.name(tree.meth);
    boolean isConstructorCall = methName == names._this || methName == names._super;
    if (isConstructorCall) {
        // Check that this is the first statement in a constructor.
        if (checkFirstConstructorStat(tree, env)) {
            // Record the fact
            // that this is a constructor call (using isSelfCall).
            localEnv.info.isSelfCall = true;
            // Attribute arguments, yielding list of argument types.
            argtypes = attribArgs(tree.args, localEnv);
            typeargtypes = attribTypes(tree.typeargs, localEnv);
            // Variable `site' points to the class in which the called
            // constructor is defined.
            Type site = env.enclClass.sym.type;
            if (methName == names._super) {
                if (site == syms.objectType) {
                    log.error(tree.meth.pos(), "no.superclass", site);
                    site = types.createErrorType(syms.objectType);
                } else {
                    site = types.supertype(site);
                }
            }
            if (site.tag == CLASS) {
                Type encl = site.getEnclosingType();
                while (encl != null && encl.tag == TYPEVAR) encl = encl.getUpperBound();
                if (encl.tag == CLASS) {
                    if (tree.meth.getTag() == JCTree.SELECT) {
                        JCTree qualifier = ((JCFieldAccess) tree.meth).selected;
                        // We are seeing a prefixed call, of the form
                        //     <expr>.super(...).
                        // Check that the prefix expression conforms
                        // to the outer instance type of the class.
                        chk.checkRefType(qualifier.pos(), attribExpr(qualifier, localEnv, encl));
                    } else if (methName == names._super) {
                        // qualifier omitted; check for existence
                        // of an appropriate implicit qualifier.
                        rs.resolveImplicitThis(tree.meth.pos(), localEnv, site, true);
                    }
                } else if (tree.meth.getTag() == JCTree.SELECT) {
                    log.error(tree.meth.pos(), "illegal.qual.not.icls", site.tsym);
                }
                // prefix the implicit String and int parameters
                if (site.tsym == syms.enumSym && allowEnums)
                    argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType);
                // Resolve the called constructor under the assumption
                // that we are referring to a superclass instance of the
                // current instance (JLS ???).
                boolean selectSuperPrev = localEnv.info.selectSuper;
                localEnv.info.selectSuper = true;
                localEnv.info.varArgs = false;
                Symbol sym = rs.resolveConstructor(tree.meth.pos(), localEnv, site, argtypes, typeargtypes);
                localEnv.info.selectSuper = selectSuperPrev;
                // Set method symbol to resolved constructor...
                TreeInfo.setSymbol(tree.meth, sym);
                // ...and check that it is legal in the current context.
                // (this will also set the tree's type)
                Type mpt = newMethTemplate(argtypes, typeargtypes);
                checkId(tree.meth, site, sym, localEnv, MTH, mpt, tree.varargsElement != null);
            }
        // Otherwise, `site' is an error type and we do nothing
        }
        result = tree.type = syms.voidType;
    } else {
        // Otherwise, we are seeing a regular method call.
        // Attribute the arguments, yielding list of argument types, ...
        argtypes = attribArgs(tree.args, localEnv);
        typeargtypes = attribAnyTypes(tree.typeargs, localEnv);
        // ... and attribute the method using as a prototype a methodtype
        // whose formal argument types is exactly the list of actual
        // arguments (this will also set the method symbol).
        Type mpt = newMethTemplate(argtypes, typeargtypes);
        localEnv.info.varArgs = false;
        Type mtype = attribExpr(tree.meth, localEnv, mpt);
        if (localEnv.info.varArgs)
            Assert.check(mtype.isErroneous() || tree.varargsElement != null);
        // Compute the result type.
        Type restype = mtype.getReturnType();
        if (restype.tag == WILDCARD)
            throw new AssertionError(mtype);
        // the same as static type of the array being cloned
        if (tree.meth.getTag() == JCTree.SELECT && allowCovariantReturns && methName == names.clone && types.isArray(((JCFieldAccess) tree.meth).selected.type))
            restype = ((JCFieldAccess) tree.meth).selected.type;
        // as a special case, x.getClass() has type Class<? extends |X|>
        if (allowGenerics && methName == names.getClass && tree.args.isEmpty()) {
            Type qualifier = (tree.meth.getTag() == JCTree.SELECT) ? ((JCFieldAccess) tree.meth).selected.type : env.enclClass.sym.type;
            restype = new ClassType(restype.getEnclosingType(), List.<Type>of(new WildcardType(types.erasure(qualifier), BoundKind.EXTENDS, syms.boundClass)), restype.tsym);
        }
        chk.checkRefTypes(tree.typeargs, typeargtypes);
        // Check that value of resulting type is admissible in the
        // current context.  Also, capture the return type
        result = check(tree, capture(restype), VAL, pkind, pt);
    }
    chk.validate(tree.typeargs, localEnv);
}
Also used : ClassType(com.sun.tools.javac.code.Type.ClassType) MethodType(com.sun.tools.javac.code.Type.MethodType) WildcardType(com.sun.tools.javac.code.Type.WildcardType) Type(com.sun.tools.javac.code.Type) ArrayType(com.sun.tools.javac.code.Type.ArrayType) UnionClassType(com.sun.tools.javac.code.Type.UnionClassType) WildcardType(com.sun.tools.javac.code.Type.WildcardType) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) DynamicMethodSymbol(com.sun.tools.javac.code.Symbol.DynamicMethodSymbol) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) OperatorSymbol(com.sun.tools.javac.code.Symbol.OperatorSymbol) JCTree(com.sun.tools.javac.tree.JCTree) ClassType(com.sun.tools.javac.code.Type.ClassType) UnionClassType(com.sun.tools.javac.code.Type.UnionClassType) Kinds.kindName(com.sun.tools.javac.code.Kinds.kindName) Name(com.sun.tools.javac.util.Name)

Example 15 with JCFieldAccess

use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project ceylon-compiler by ceylon.

the class ClassDocImpl method importedPackages.

/**
     * Get the list of packages declared as imported.
     * These are called "type-import-on-demand declarations" in the JLS.
     * This method is deprecated in the ClassDoc interface.
     *
     * @return an array of PackageDocImpl representing the imported packages.
     *
     * ###NOTE: the syntax supports importing all inner classes from a class as well.
     * @deprecated  Import declarations are implementation details that
     *          should not be exposed here.  In addition, this method's
     *          return type does not allow for all type-import-on-demand
     *          declarations to be returned.
     */
@Deprecated
public PackageDoc[] importedPackages() {
    // information is not available for binary classfiles
    if (tsym.sourcefile == null)
        return new PackageDoc[0];
    ListBuffer<PackageDocImpl> importedPackages = new ListBuffer<PackageDocImpl>();
    //### Add the implicit "import java.lang.*" to the result
    Names names = tsym.name.table.names;
    importedPackages.append(env.getPackageDoc(env.reader.enterPackage(names.java_lang)));
    Env<AttrContext> compenv = env.enter.getEnv(tsym);
    if (compenv == null)
        return new PackageDocImpl[0];
    for (JCTree t : compenv.toplevel.defs) {
        if (t.getTag() == JCTree.IMPORT) {
            JCTree imp = ((JCImport) t).qualid;
            if (TreeInfo.name(imp) == names.asterisk) {
                JCFieldAccess sel = (JCFieldAccess) imp;
                Symbol s = sel.selected.type.tsym;
                PackageDocImpl pdoc = env.getPackageDoc(s.packge());
                if (!importedPackages.contains(pdoc))
                    importedPackages.append(pdoc);
            }
        }
    }
    return importedPackages.toArray(new PackageDocImpl[importedPackages.length()]);
}
Also used : Names(com.sun.tools.javac.util.Names) JCImport(com.sun.tools.javac.tree.JCTree.JCImport) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) Symbol(com.sun.tools.javac.code.Symbol) ListBuffer(com.sun.tools.javac.util.ListBuffer) JCTree(com.sun.tools.javac.tree.JCTree) AttrContext(com.sun.tools.javac.comp.AttrContext)

Aggregations

JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)35 JCTree (com.sun.tools.javac.tree.JCTree)13 ExpressionTree (com.sun.source.tree.ExpressionTree)12 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)11 JCIdent (com.sun.tools.javac.tree.JCTree.JCIdent)11 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)8 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)7 Type (com.sun.tools.javac.code.Type)6 ListBuffer (com.sun.tools.javac.util.ListBuffer)6 JCClassDecl (com.sun.tools.javac.tree.JCTree.JCClassDecl)5 JCImport (com.sun.tools.javac.tree.JCTree.JCImport)5 JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)5 Name (com.sun.tools.javac.util.Name)5 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)4 Symbol (com.sun.tools.javac.code.Symbol)4 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)4 JCTypeApply (com.sun.tools.javac.tree.JCTree.JCTypeApply)4 JavacTreeMaker (lombok.javac.JavacTreeMaker)4 Fix (com.google.errorprone.fixes.Fix)3 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)3