Search in sources :

Example 26 with Type

use of com.sun.tools.javac.code.Type in project error-prone by google.

the class AbstractArgumentParameterChecker method findReplacements.

private Description findReplacements(List<? extends ExpressionTree> args, com.sun.tools.javac.util.List<VarSymbol> params, boolean isVarArgs, VisitorState state, Tree tree) {
    if (args.isEmpty()) {
        return Description.NO_MATCH;
    }
    ImmutableSet<PotentialReplacement> potentialReplacements = potentialReplacementsFunction.apply(state.withPath(new TreePath(state.getPath(), args.get(0))));
    SuggestedFix.Builder fix = SuggestedFix.builder();
    // Don't suggest for the varargs parameter.
    // TODO(eaftan): Reconsider this, especially if the argument is of array type or is itself
    // a varargs parameter.
    int maxArg = isVarArgs ? params.size() - 1 : params.size();
    for (int i = 0; i < maxArg; i++) {
        ExpressionTree arg = args.get(i);
        VarSymbol param = params.get(i);
        if (!validKinds.contains(arg.getKind()) || !parameterPredicate.test(param)) {
            continue;
        }
        String extractedArgumentName = extractArgumentName(arg);
        if (extractedArgumentName == null) {
            continue;
        }
        double currSimilarity = similarityMetric.applyAsDouble(extractedArgumentName, param.getSimpleName().toString());
        if (1.0 - currSimilarity < beta) {
            // No way for any replacement to be at least BETA better than the current argument
            continue;
        }
        ReplacementWithSimilarity bestReplacement = potentialReplacements.stream().filter(replacement -> !replacement.sym().equals(ASTHelpers.getSymbol(arg))).filter(replacement -> isSubtypeHandleCompletionFailures(replacement.sym(), param, state)).map(replacement -> ReplacementWithSimilarity.create(replacement, similarityMetric.applyAsDouble(replacement.argumentName(), param.getSimpleName().toString()))).max(Comparator.comparingDouble(ReplacementWithSimilarity::similarity)).orElse(null);
        if ((bestReplacement != null) && (bestReplacement.similarity() - currSimilarity >= beta)) {
            fix.replace(arg, bestReplacement.replacement().replacementString());
        }
    }
    if (fix.isEmpty()) {
        return Description.NO_MATCH;
    } else {
        return describeMatch(tree, fix.build());
    }
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Function(java.util.function.Function) NewClassTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.NewClassTreeMatcher) VisitorState(com.google.errorprone.VisitorState) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Kind(com.sun.source.tree.Tree.Kind) NewClassTree(com.sun.source.tree.NewClassTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) Nullable(javax.annotation.Nullable) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) MethodInvocationTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher) TreePath(com.sun.source.util.TreePath) ImmutableSet(com.google.common.collect.ImmutableSet) ExpressionTree(com.sun.source.tree.ExpressionTree) Predicate(java.util.function.Predicate) Symbol(com.sun.tools.javac.code.Symbol) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ToDoubleBiFunction(java.util.function.ToDoubleBiFunction) List(java.util.List) CompletionFailure(com.sun.tools.javac.code.Symbol.CompletionFailure) Description(com.google.errorprone.matchers.Description) AutoValue(com.google.auto.value.AutoValue) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Comparator(java.util.Comparator) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) TreePath(com.sun.source.util.TreePath) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ExpressionTree(com.sun.source.tree.ExpressionTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol)

Example 27 with Type

use of com.sun.tools.javac.code.Type 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 28 with Type

use of com.sun.tools.javac.code.Type in project error-prone by google.

the class ArrayHashCode method rewriteArrayArgument.

/**
   * Given an {@link ExpressionTree} that represents an argument of array type, rewrites it to wrap
   * it in a call to either {@link java.util.Arrays#hashCode} if it is single dimensional, or
   * {@link java.util.Arrays#deepHashCode} if it is multidimensional.
   */
private static String rewriteArrayArgument(ExpressionTree arg, Types types) {
    Type argType = ASTHelpers.getType(arg);
    Preconditions.checkState(types.isArray(argType), "arg must be of array type");
    if (types.isArray(types.elemtype(argType))) {
        return "Arrays.deepHashCode(" + arg + ")";
    } else {
        return "Arrays.hashCode(" + arg + ")";
    }
}
Also used : MatchType(com.google.errorprone.matchers.ChildMultiMatcher.MatchType) Type(com.sun.tools.javac.code.Type)

Example 29 with Type

use of com.sun.tools.javac.code.Type in project error-prone by google.

the class BadAnnotationImplementation method matchClass.

@Override
public Description matchClass(ClassTree classTree, final VisitorState state) {
    if (!CLASS_TREE_MATCHER.matches(classTree, state)) {
        return Description.NO_MATCH;
    }
    // If this is an enum that is trying to implement Annotation, give a special error message.
    if (classTree.getKind() == Kind.ENUM) {
        return buildDescription(classTree).setMessage("Enums cannot correctly implement Annotation because their equals and hashCode " + "methods are final. Consider using AutoAnnotation instead of implementing " + "Annotation by hand.").build();
    }
    // Otherwise walk up type hierarchy looking for equals and hashcode methods
    MethodSymbol equals = null;
    MethodSymbol hashCode = null;
    final Types types = state.getTypes();
    Name equalsName = state.getName("equals");
    Predicate<MethodSymbol> equalsPredicate = new Predicate<MethodSymbol>() {

        @Override
        public boolean apply(MethodSymbol methodSymbol) {
            return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().size() == 1 && types.isSameType(methodSymbol.getParameters().get(0).type, state.getSymtab().objectType);
        }
    };
    Name hashCodeName = state.getName("hashCode");
    Predicate<MethodSymbol> hashCodePredicate = new Predicate<MethodSymbol>() {

        @Override
        public boolean apply(MethodSymbol methodSymbol) {
            return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().isEmpty();
        }
    };
    for (Type sup : types.closure(ASTHelpers.getSymbol(classTree).type)) {
        if (equals == null) {
            equals = getMatchingMethod(sup, equalsName, equalsPredicate);
        }
        if (hashCode == null) {
            hashCode = getMatchingMethod(sup, hashCodeName, hashCodePredicate);
        }
    }
    Verify.verifyNotNull(equals);
    Verify.verifyNotNull(hashCode);
    Symbol objectSymbol = state.getSymtab().objectType.tsym;
    if (equals.owner.equals(objectSymbol) || hashCode.owner.equals(objectSymbol)) {
        return describeMatch(classTree);
    }
    return Description.NO_MATCH;
}
Also used : Types(com.sun.tools.javac.code.Types) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Symbol(com.sun.tools.javac.code.Symbol) Name(com.sun.tools.javac.util.Name) Predicate(com.google.common.base.Predicate)

Example 30 with Type

use of com.sun.tools.javac.code.Type in project error-prone by google.

the class BadComparable method matches.

/**
   * Matches if this is a narrowing integral cast between signed types where the expression is a
   * subtract.
   */
private boolean matches(TypeCastTree tree, VisitorState state) {
    Type treeType = ASTHelpers.getType(tree.getType());
    // If the cast isn't narrowing to an int then don't implicate it in the bug pattern.
    if (treeType.getTag() != TypeTag.INT) {
        return false;
    }
    // The expression should be a subtract but remove parentheses.
    ExpressionTree expression = TreeInfo.skipParens((JCExpression) tree.getExpression());
    if (expression.getKind() != Kind.MINUS) {
        return false;
    }
    // Ensure the expression type is wider and signed (ie a long) than the cast type ignoring
    // boxing.
    Type expressionType = getTypeOfSubtract((BinaryTree) expression);
    TypeTag expressionTypeTag = state.getTypes().unboxedTypeOrType(expressionType).getTag();
    return (expressionTypeTag == TypeTag.LONG);
}
Also used : Type(com.sun.tools.javac.code.Type) ExpressionTree(com.sun.source.tree.ExpressionTree) TypeTag(com.sun.tools.javac.code.TypeTag)

Aggregations

Type (com.sun.tools.javac.code.Type)253 Symbol (com.sun.tools.javac.code.Symbol)64 ClassType (com.sun.tools.javac.code.Type.ClassType)55 ArrayType (com.sun.tools.javac.code.Type.ArrayType)47 MethodType (com.sun.tools.javac.code.Type.MethodType)42 WildcardType (com.sun.tools.javac.code.Type.WildcardType)42 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)36 UnionClassType (com.sun.tools.javac.code.Type.UnionClassType)33 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)32 JCTree (com.sun.tools.javac.tree.JCTree)27 TypeSymbol (com.sun.tools.javac.code.Symbol.TypeSymbol)24 VarSymbol (com.sun.tools.javac.code.Symbol.VarSymbol)23 Types (com.sun.tools.javac.code.Types)22 ExpressionTree (com.sun.source.tree.ExpressionTree)21 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)17 ArrayList (java.util.ArrayList)17 PackageSymbol (com.sun.tools.javac.code.Symbol.PackageSymbol)16 Tree (com.sun.source.tree.Tree)14 Name (com.sun.tools.javac.util.Name)14 DynamicMethodSymbol (com.sun.tools.javac.code.Symbol.DynamicMethodSymbol)13