use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class StrictFormatStringValidation method isFormatStringParameter.
/**
* Returns whether an input {@link Symbol} is a format string in a {@link FormatMethod}. This is
* true if the {@link Symbol} is a {@link String} parameter in a {@link FormatMethod} and is
* either:
*
* <ol>
* <li>Annotated with {@link FormatString}
* <li>The first {@link String} parameter in the method with no other parameters annotated {@link
* FormatString}.
* </ol>
*/
private static boolean isFormatStringParameter(Symbol formatString, VisitorState state) {
Type stringType = state.getSymtab().stringType;
// The input symbol must be a String and a parameter of a @FormatMethod to be a @FormatString.
if (!ASTHelpers.isSameType(formatString.type, stringType, state) || !(formatString.owner instanceof MethodSymbol) || !ASTHelpers.hasAnnotation(formatString.owner, FormatMethod.class, state)) {
return false;
}
// If the format string is annotated @FormatString in a @FormatMethod, it is a format string.
if (ASTHelpers.hasAnnotation(formatString, FormatString.class, state)) {
return true;
}
// Check if format string is the first string with no @FormatString params in the @FormatMethod.
MethodSymbol owner = (MethodSymbol) formatString.owner;
boolean formatStringFound = false;
for (Symbol param : owner.getParameters()) {
if (param == formatString) {
formatStringFound = true;
}
if (ASTHelpers.isSameType(param.type, stringType, state)) {
// format string since it wasn't annotated @FormatString.
if (!formatStringFound) {
return false;
} else if (ASTHelpers.hasAnnotation(param, FormatString.class, state)) {
return false;
}
}
}
return true;
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class StrictFormatStringValidation method validateFormatStringParamter.
/** Helps {@code validate()} validate a format string that is declared as a method parameter. */
private static ValidationResult validateFormatStringParamter(ExpressionTree formatStringTree, Symbol formatStringSymbol, List<? extends ExpressionTree> args, VisitorState state) {
if (!isFormatStringParameter(formatStringSymbol, state)) {
return ValidationResult.create(null, String.format("Format strings must be compile time constant or parameters annotated " + "@FormatString: %s", formatStringTree));
}
List<VarSymbol> ownerParams = ((MethodSymbol) formatStringSymbol.owner).getParameters();
int ownerFormatStringIndex = ownerParams.indexOf(formatStringSymbol);
ImmutableList.Builder<Type> ownerFormatArgTypesBuilder = ImmutableList.builder();
for (VarSymbol paramSymbol : ownerParams.subList(ownerFormatStringIndex + 1, ownerParams.size())) {
ownerFormatArgTypesBuilder.add(paramSymbol.type);
}
ImmutableList<Type> ownerFormatArgTypes = ownerFormatArgTypesBuilder.build();
Types types = state.getTypes();
ImmutableList.Builder<Type> calleeFormatArgTypesBuilder = ImmutableList.builder();
for (ExpressionTree formatArgExpression : args) {
calleeFormatArgTypesBuilder.add(types.erasure(((JCExpression) formatArgExpression).type));
}
ImmutableList<Type> calleeFormatArgTypes = calleeFormatArgTypesBuilder.build();
if (ownerFormatArgTypes.size() != calleeFormatArgTypes.size()) {
return ValidationResult.create(null, String.format("The number of format arguments passed " + "with an @FormatString must match the number of format arguments in the " + "@FormatMethod header where the format string was declared.\n\t" + "Format args passed: %d\n\tFormat args expected: %d", calleeFormatArgTypes.size(), ownerFormatArgTypes.size()));
} else {
for (int i = 0; i < calleeFormatArgTypes.size(); i++) {
if (!ASTHelpers.isSameType(ownerFormatArgTypes.get(i), calleeFormatArgTypes.get(i), state)) {
return ValidationResult.create(null, String.format("The format argument types passed " + "with an @FormatString must match the types of the format arguments in " + "the @FormatMethod header where the format string was declared.\n\t" + "Format arg types passed: %s\n\tFormat arg types expected: %s", calleeFormatArgTypes.toArray(), ownerFormatArgTypes.toArray()));
}
}
}
// Format string usage was valid.
return null;
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class StaticQualifiedUsingExpression method matchMemberSelect.
@Override
public Description matchMemberSelect(MemberSelectTree tree, VisitorState state) {
if (!staticAccessedFromInstanceMatcher.matches(tree, state)) {
return Description.NO_MATCH;
}
// Is the static member being accessed a method or a variable?
Symbol staticMemberSym = ASTHelpers.getSymbol(tree);
if (staticMemberSym == null) {
return Description.NO_MATCH;
}
boolean isMethod = staticMemberSym instanceof MethodSymbol;
// Is the static member defined in this class?
Symbol ownerSym = staticMemberSym.owner;
Symbol whereAccessedSym = ASTHelpers.getSymbol(ASTHelpers.findEnclosingNode(state.getPath().getParentPath(), ClassTree.class));
if (!(ownerSym instanceof ClassSymbol && whereAccessedSym instanceof ClassSymbol)) {
return Description.NO_MATCH;
}
boolean staticMemberDefinedHere = whereAccessedSym.equals(ownerSym);
SuggestedFix.Builder fix = SuggestedFix.builder();
String replacement;
if (staticMemberDefinedHere && isMethod) {
// If the static member is defined in the enclosing class and the member is a method, then
// just use the bare method name. Don't do this for fields, because they may share a simple
// name with a local in the same scope.
// TODO(eaftan): If we had access to name resolution info, we could do this in all applicable
// cases. Investigate Scope.Entry for this.
replacement = tree.getIdentifier().toString();
} else {
// Replace the operand of the field access expression with the simple name of the class.
replacement = ownerSym.getSimpleName() + "." + tree.getIdentifier();
// Don't import implicitly imported packages (java.lang.* and current package).
// TODO(cushon): move this logic into addImport?
Symbol packageSym = ownerSym.packge();
if (!packageSym.toString().equals("java.lang") && !packageSym.equals(whereAccessedSym.packge())) {
fix.addImport(ownerSym.toString());
}
}
fix.replace(tree, replacement);
// Compute strings to interpolate into diagnostic message.
String memberName = staticMemberSym.getSimpleName().toString();
String methodOrVariable = isMethod ? "method" : "variable";
String customDiagnosticMessage = String.format(MESSAGE_TEMPLATE, methodOrVariable, memberName, replacement);
return buildDescription(tree).setMessage(customDiagnosticMessage).addFix(fix.build()).build();
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class TryFailThrowable method getMessageSnippet.
private static String getMessageSnippet(StatementTree failStatement, VisitorState state, HasOtherParameters hasOtherParameters) {
ExpressionTree expression = ((ExpressionStatementTree) failStatement).getExpression();
MethodSymbol sym = (MethodSymbol) getSymbol(expression);
String tail = hasOtherParameters == HasOtherParameters.TRUE ? ", " : "";
// The above casts were checked earlier by failOrAssert.
return hasInitialStringParameter(sym, state) ? state.getSourceForNode(((MethodInvocationTree) expression).getArguments().get(0)) + tail : "";
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class WrongParameterPackage method matchMethod.
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
MethodSymbol method = ASTHelpers.getSymbol(tree);
if (method == null) {
return Description.NO_MATCH;
}
ClassSymbol classSym = method.enclClass();
if (classSym == null) {
return Description.NO_MATCH;
}
TypeSymbol superClass = classSym.getSuperclass().tsym;
if (superClass == null) {
return Description.NO_MATCH;
}
for (Symbol s : superClass.members().getSymbols()) {
if (s.name.contentEquals(method.name) && s.getKind() == ElementKind.METHOD) {
MethodSymbol supermethod = (MethodSymbol) s;
// if this method actually overrides the supermethod, then it's correct and not a match.
if (method.overrides(supermethod, superClass, state.getTypes(), true)) {
return Description.NO_MATCH;
}
// if this doesn't have the right number of parameters, look at other ones.
if (supermethod.params().size() != method.params().size()) {
continue;
}
for (int x = 0; x < method.params().size(); x++) {
Type methodParamType = method.params().get(x).type;
Type supermethodParamType = supermethod.params().get(x).type;
if (methodParamType.tsym.name.contentEquals(supermethodParamType.tsym.name) && !state.getTypes().isSameType(methodParamType, supermethodParamType)) {
this.supermethod = supermethod;
return describe(tree, state);
}
}
}
}
return Description.NO_MATCH;
}
Aggregations