private static ImmutableList<VarSymbol> getFormalParametersWithoutVarArgs( MethodSymbol invokedMethodSymbol) { List<VarSymbol> formalParameters = invokedMethodSymbol.getParameters(); /* javac can get argument names from debugging symbols if they are not available from other sources. When it does this for an inner class sometimes it returns the implicit this pointer for the outer class as the first name (but not the first type). If we see this, then just abort */ if (!formalParameters.isEmpty() && formalParameters.get(0).getSimpleName().toString().matches("this\\$[0-9]+")) { return ImmutableList.of(); } /* If we have a varargs method then just ignore the final parameter and trailing actual parameters */ int size = invokedMethodSymbol.isVarArgs() ? formalParameters.size() - 1 : formalParameters.size(); return ImmutableList.copyOf(formalParameters.subList(0, size)); } }
/** * Pretty-prints a method signature for use in diagnostics. * * <p>Uses simple names for declared types, and omitting formal type parameters and the return * type since they do not affect overload resolution. */ public static String prettyMethodSignature(ClassSymbol origin, MethodSymbol m) { StringBuilder sb = new StringBuilder(); if (!m.owner.equals(origin)) { sb.append(m.owner.getSimpleName()).append('.'); } sb.append(m.isConstructor() ? origin.getSimpleName() : m.getSimpleName()).append('('); sb.append( m.getParameters().stream() .map(v -> v.type.accept(PRETTY_TYPE_VISITOR, null)) .collect(joining(", "))); sb.append(')'); return sb.toString(); }
/** * Returns true if the method has synthetic parameter names, indicating the real names are not * available. */ public static boolean containsSyntheticParameterName(MethodSymbol sym) { return sym.getParameters().stream() .anyMatch(p -> SYNTHETIC_PARAMETER_NAME.matcher(p.getSimpleName()).matches()); }
return NO_MATCH; if (tree.getArguments().size() != sym.getParameters().size()) { String qualified = SuggestedFixes.qualifyType( state, fix, types.elemtype(getLast(sym.getParameters()).asType())); Tree toFix = !trueIsArray ? cond.getTrueExpression() : cond.getFalseExpression(); fix.prefixWith(toFix, String.format("new %s[] {", qualified)).postfixWith(toFix, "}");
private String getMethodSignature(Symbol.MethodSymbol method) { // Generate method signature String methodSign = method.enclClass().getQualifiedName().toString() + ":" + (method.isStaticOrInstanceInit() ? "" : getSimpleTypeName(method.getReturnType()) + " ") + method.getSimpleName() + "("; if (!method.getParameters().isEmpty()) { for (Symbol.VarSymbol var : method.getParameters()) { methodSign += getSimpleTypeName(var.type) + ", "; } methodSign = methodSign.substring(0, methodSign.lastIndexOf(',')); } methodSign += ")"; LOG(DEBUG, "DEBUG", "@ method sign: " + methodSign); return methodSign; }
/** * Works for method parameters defined either in source or in class files * * @param symbol the method symbol * @param paramInd index of the parameter * @return all declaration and type-use annotations for the parameter */ public static Stream<? extends AnnotationMirror> getAllAnnotationsForParameter( Symbol.MethodSymbol symbol, int paramInd) { Symbol.VarSymbol varSymbol = symbol.getParameters().get(paramInd); return Stream.concat( varSymbol.getAnnotationMirrors().stream(), symbol .getRawTypeAttributes() .stream() .filter( t -> t.position.type.equals(TargetType.METHOD_FORMAL_PARAMETER) && t.position.parameter_index == paramInd)); }
private Description matchNewClassOrMethodInvocation( MethodSymbol symbol, ImmutableList<Commented<ExpressionTree>> arguments, Tree tree) { if (symbol.getParameters().isEmpty()) { return NO_MATCH; } SuggestedFix.Builder fix = SuggestedFix.builder(); forEachPair( arguments.stream(), Stream.concat( symbol.getParameters().stream(), Stream.iterate(getLast(symbol.getParameters()), x -> x)), (commented, param) -> { ImmutableList<Comment> comments = commented.afterComments().isEmpty() ? commented.beforeComments() : commented.afterComments(); boolean matchStandardForm = !commented.afterComments().isEmpty(); comments.stream() .filter(c -> matchingParamComment(c, param, matchStandardForm)) .findFirst() .ifPresent(c -> fixParamComment(fix, commented, param, c)); }); return fix.isEmpty() ? NO_MATCH : describeMatch(tree, fix.build()); }
@Override public Description matchMethod(MethodTree node, VisitorState state) { Symbol.MethodSymbol method = ASTHelpers.getSymbol(node); if (method == null) { return Description.NO_MATCH; } List<Integer> compileTimeConstantAnnotationIndexes = new ArrayList<>(); for (int i = 0; i < method.getParameters().size(); i++) { if (hasCompileTimeConstantAnnotation(state, method.getParameters().get(i))) { compileTimeConstantAnnotationIndexes.add(i); } } if (compileTimeConstantAnnotationIndexes.isEmpty()) { return Description.NO_MATCH; } for (Symbol.MethodSymbol superMethod : ASTHelpers.findSuperMethods(method, state.getTypes())) { for (Integer index : compileTimeConstantAnnotationIndexes) { if (!hasCompileTimeConstantAnnotation(state, superMethod.getParameters().get(index))) { return buildDescription(node) .setMessage( "Method with @CompileTimeConstant parameter can't override method without it.") .build(); } } } return Description.NO_MATCH; }
private void handleArguments( Tree tree, List<? extends ExpressionTree> arguments, VisitorState state) { if (arguments.size() < 2 && areSingleArgumentsSelfDocumenting(tree)) { // single-argument methods are often self-documenting return; } if (arguments.stream().noneMatch(BooleanParameter::isBooleanLiteral)) { return; } MethodSymbol sym = (MethodSymbol) ASTHelpers.getSymbol(tree); if (NamedParameterComment.containsSyntheticParameterName(sym)) { return; } int start = ((JCTree) tree).getStartPosition(); int end = state.getEndPosition(getLast(arguments)); String source = state.getSourceCode().subSequence(start, end).toString(); Deque<ErrorProneToken> tokens = new ArrayDeque<>(ErrorProneTokens.getTokens(source, state.context)); forEachPair( sym.getParameters().stream(), arguments.stream(), (p, c) -> checkParameter(p, c, start, tokens, state)); }
@Override public ImmutableSet<Integer> onUnannotatedInvocationGetNonNullPositions( NullAway analysis, VisitorState state, Symbol.MethodSymbol methodSymbol, List<? extends ExpressionTree> actualParams, ImmutableSet<Integer> nonNullPositions) { HashSet<Integer> positions = new HashSet<Integer>(); positions.addAll(nonNullPositions); for (int i = 0; i < methodSymbol.getParameters().size(); ++i) { if (Nullness.paramHasNonNullAnnotation(methodSymbol, i)) { positions.add(i); } } return ImmutableSet.copyOf(positions); }
@Override public Description matchMemberReference(MemberReferenceTree tree, VisitorState state) { Symbol.MethodSymbol sym = ASTHelpers.getSymbol(tree); if (sym == null) { return Description.NO_MATCH; } for (Symbol.VarSymbol formalParam : sym.getParameters()) { if (hasCompileTimeConstantAnnotation(state, formalParam)) { // We couldn't check how the reference will be used. Simply disallow all references. return buildDescription(tree) .setMessage( "References to methods with @CompileTimeConstant parameters are not supported.") .build(); } } return Description.NO_MATCH; }
@Override public ImmutableSet<Integer> onUnannotatedInvocationGetExplicitlyNullablePositions( Context context, Symbol.MethodSymbol methodSymbol, ImmutableSet<Integer> explicitlyNullablePositions) { HashSet<Integer> positions = new HashSet<Integer>(); positions.addAll(explicitlyNullablePositions); for (int i = 0; i < methodSymbol.getParameters().size(); ++i) { if (Nullness.paramHasNullableAnnotation(methodSymbol, i)) { positions.add(i); } } return ImmutableSet.copyOf(positions); }
private static boolean canBeUsedByGetChecked(MethodSymbol constructor, VisitorState state) { Type stringType = state.getSymtab().stringType; Type throwableType = state.getSymtab().throwableType; // TODO(cpovirk): Check visibility of enclosing types (assuming that it matters to getChecked). if (!constructor.getModifiers().contains(PUBLIC)) { return false; } for (VarSymbol param : constructor.getParameters()) { if (!isSameType(param.asType(), stringType, state) && !isSameType(param.asType(), throwableType, state)) { return false; } } return true; }
private boolean thriftIsSetCall(Symbol.MethodSymbol symbol, Types types) { Preconditions.checkNotNull(tbaseType); // noinspection ConstantConditions return tbaseType.isPresent() && symbol.getSimpleName().toString().startsWith("isSet") // weeds out the isSet() method in TBase itself && symbol.getParameters().length() == 0 && types.isSubtype(symbol.owner.type, tbaseType.get()); } }
/** * A string representation of a method descriptor, where all parameters whose type is a functional * interface are "erased" to the interface's function type. For example, `foo(Supplier<String>)` * is represented as `foo(()->Ljava/lang/String;)`. */ private static String functionalInterfaceSignature(VisitorState state, MethodSymbol msym) { return String.format( "%s(%s)", msym.getSimpleName(), msym.getParameters().stream() .map(p -> functionalInterfaceSignature(state, p.type)) .collect(joining(","))); }
@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); } };
private static boolean hasInitialStringParameter(MethodSymbol sym, VisitorState state) { Types types = state.getTypes(); List<VarSymbol> parameters = sym.getParameters(); return !parameters.isEmpty() && types.isSameType(parameters.get(0).type, state.getSymtab().stringType); }
@Override public boolean apply(MethodSymbol methodSymbol) { return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().isEmpty(); } };
@Override public boolean matches(MethodInvocationTree tree, VisitorState state) { List<VarSymbol> parameters = ASTHelpers.getSymbol(tree).getParameters(); if (parameters.size() != 3) { return false; } return ASTHelpers.isSameType( parameters.get(0).asType(), state.getTypeFromString("java.lang.String"), state) && ASTHelpers.isSameType( parameters.get(1).asType(), parameters.get(2).asType(), state); } };
@Override public boolean matches(MethodInvocationTree tree, VisitorState state) { List<VarSymbol> parameters = ASTHelpers.getSymbol(tree).getParameters(); if (parameters.size() != 2) { return false; } return ASTHelpers.isSameType( parameters.get(0).asType(), parameters.get(1).asType(), state); } };