use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class MutableMethodReturnType method matchMethod.
@Override
public Description matchMethod(MethodTree methodTree, VisitorState state) {
MethodSymbol methodSymbol = ASTHelpers.getSymbol(methodTree);
if (methodSymbol.isConstructor()) {
return Description.NO_MATCH;
}
if (isMethodCanBeOverridden(methodSymbol, state)) {
return Description.NO_MATCH;
}
if (ANNOTATED_WITH_PRODUCES_OR_PROVIDES.matches(methodTree, state)) {
return Description.NO_MATCH;
}
Type returnType = methodSymbol.getReturnType();
if (ImmutableCollections.isImmutableType(returnType)) {
return Description.NO_MATCH;
}
ImmutableSet<ClassType> returnStatementsTypes = getMethodReturnTypes(methodTree);
if (returnStatementsTypes.isEmpty()) {
return Description.NO_MATCH;
}
boolean alwaysReturnsImmutableType = returnStatementsTypes.stream().allMatch(ImmutableCollections::isImmutableType);
if (!alwaysReturnsImmutableType) {
return Description.NO_MATCH;
}
Optional<String> immutableReturnType = ImmutableCollections.mutableToImmutable(getTypeQualifiedName(returnType));
if (!immutableReturnType.isPresent()) {
immutableReturnType = getCommonImmutableTypeForAllReturnStatementsTypes(returnStatementsTypes);
}
if (!immutableReturnType.isPresent()) {
return Description.NO_MATCH;
}
Type newReturnType = state.getTypeFromString(immutableReturnType.get());
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
fixBuilder.replace(getTypeTree(methodTree.getReturnType()), SuggestedFixes.qualifyType(state, fixBuilder, newReturnType.asElement()));
SuggestedFix fix = fixBuilder.build();
return describeMatch(methodTree.getReturnType(), fix);
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class MissingSuperCall method matchAnnotation.
/**
* Prevents abstract methods from being annotated with {@code @CallSuper} et al. It doesn't make
* sense to require overriders to call a method with no implementation.
*/
@Override
public Description matchAnnotation(AnnotationTree tree, VisitorState state) {
if (!ANNOTATION_MATCHER.matches(tree, state)) {
return Description.NO_MATCH;
}
MethodTree methodTree = ASTHelpers.findEnclosingNode(state.getPath(), MethodTree.class);
if (methodTree == null) {
return Description.NO_MATCH;
}
MethodSymbol methodSym = ASTHelpers.getSymbol(methodTree);
if (methodSym == null) {
return Description.NO_MATCH;
}
if (!methodSym.getModifiers().contains(Modifier.ABSTRACT)) {
return Description.NO_MATCH;
}
// Match, find the matched annotation to use for the error message.
Symbol annotationSym = ASTHelpers.getSymbol(tree);
if (annotationSym == null) {
return Description.NO_MATCH;
}
return buildDescription(tree).setMessage(String.format("@%s cannot be applied to an abstract method", annotationSym.getSimpleName())).build();
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class LambdaFunctionalInterface method matchMethod.
/**
* Identifies methods with parameters that have a generic argument with Int, Long, or Double. If
* pre-conditions are met, it refactors them to the primitive specializations.
*
* <pre>PreConditions:
* (1): The method declaration has to be private (to do a safe refactoring)
* (2): Its parameters have to meet the following conditions:
* 2.1 Contain type java.util.function.Function
* 2.2 At least one argument type of the Function must be subtype of Number
* (3): All its invocations in the top-level enclosing class have to meet the following
* conditions as well:
* 3.1: lambda argument of Kind.LAMBDA_EXPRESSION
* 3.2: same as 2.1
* 3.3: same as 2.2
* </pre>
*
* <pre>
* Refactoring Changes for matched methods:
* (1) Add the imports
* (2) Change the method signature to use utility function instead of Function
* (3) Find and change the 'apply' calls to the corresponding applyAsT
* </pre>
*/
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
MethodSymbol methodSym = ASTHelpers.getSymbol(tree);
// precondition (1)
if (!methodSym.getModifiers().contains(Modifier.PRIVATE)) {
return Description.NO_MATCH;
}
ImmutableList<Tree> params = tree.getParameters().stream().filter(param -> hasFunctionAsArg(param, state)).filter(param -> isFunctionArgSubtypeOf(param, 0, state.getTypeFromString(JAVA_LANG_NUMBER), state) || isFunctionArgSubtypeOf(param, 1, state.getTypeFromString(JAVA_LANG_NUMBER), state)).collect(toImmutableList());
// preconditions (2) and (3)
if (params.isEmpty() || !methodCallsMeetConditions(methodSym, state)) {
return Description.NO_MATCH;
}
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
for (Tree param : params) {
getMappingForFunctionFromTree(param).ifPresent(mappedFunction -> {
fixBuilder.addImport(getImportName(mappedFunction));
fixBuilder.replace(param, getFunctionName(mappedFunction) + " " + ASTHelpers.getSymbol(param).name);
refactorInternalApplyMethods(tree, fixBuilder, param, mappedFunction);
});
}
return describeMatch(tree, fixBuilder.build());
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class ParameterName method checkArguments.
private void checkArguments(Tree tree, List<? extends ExpressionTree> arguments, VisitorState state) {
if (arguments.isEmpty()) {
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();
if (!source.contains("/*")) {
// fast path if the arguments don't contain anything that looks like a comment
return;
}
Deque<ErrorProneToken> tokens = new ArrayDeque<>(ErrorProneTokens.getTokens(source, state.context));
forEachPair(sym.getParameters().stream(), arguments.stream(), (p, a) -> {
while (!tokens.isEmpty() && ((start + tokens.peekFirst().pos()) < ((JCTree) a).getStartPosition())) {
tokens.removeFirst();
}
if (tokens.isEmpty()) {
return;
}
Range<Integer> argRange = Range.closedOpen(((JCTree) a).getStartPosition(), state.getEndPosition(a));
if (!argRange.contains(start + tokens.peekFirst().pos())) {
return;
}
checkArgument(p, a, start, tokens.removeFirst(), state);
});
}
use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.
the class AbstractExpectedExceptionChecker method buildBaseFix.
protected BaseFix buildBaseFix(VisitorState state, List<Tree> expectations, @Nullable StatementTree failure) {
String exceptionClass = "Throwable";
// additional assertions to perform on the captured exception (if any)
List<String> newAsserts = new ArrayList<>();
Builder fix = SuggestedFix.builder();
for (Tree expectation : expectations) {
MethodInvocationTree invocation = (MethodInvocationTree) ((ExpressionStatementTree) expectation).getExpression();
MethodSymbol symbol = ASTHelpers.getSymbol(invocation);
Symtab symtab = state.getSymtab();
List<? extends ExpressionTree> args = invocation.getArguments();
switch(symbol.getSimpleName().toString()) {
case "expect":
Type type = ASTHelpers.getType(getOnlyElement(invocation.getArguments()));
if (isSubtype(type, symtab.classType, state)) {
// expect(Class<?>)
exceptionClass = state.getSourceForNode(getReceiver(getOnlyElement(args)));
} else if (isSubtype(type, state.getTypeFromString("org.hamcrest.Matcher"), state)) {
Type matcherType = state.getTypes().asSuper(type, state.getSymbolFromString("org.hamcrest.Matcher"));
if (!matcherType.getTypeArguments().isEmpty()) {
Type matchType = getOnlyElement(matcherType.getTypeArguments());
if (isSubtype(matchType, symtab.throwableType, state)) {
exceptionClass = SuggestedFixes.qualifyType(state, fix, matchType);
}
}
// expect(Matcher)
fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
newAsserts.add(String.format("assertThat(thrown, %s);", state.getSourceForNode(getOnlyElement(args))));
}
break;
case "expectCause":
ExpressionTree matcher = getOnlyElement(invocation.getArguments());
if (IS_A.matches(matcher, state)) {
fix.addStaticImport("com.google.common.truth.Truth.assertThat");
newAsserts.add(String.format("assertThat(thrown).hasCauseThat().isInstanceOf(%s);", state.getSourceForNode(getOnlyElement(((MethodInvocationTree) matcher).getArguments()))));
} else {
fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
newAsserts.add(String.format("assertThat(thrown.getCause(), %s);", state.getSourceForNode(getOnlyElement(args))));
}
break;
case "expectMessage":
if (isSubtype(getOnlyElement(symbol.getParameters()).asType(), symtab.stringType, state)) {
// expectedMessage(String)
fix.addStaticImport("com.google.common.truth.Truth.assertThat");
newAsserts.add(String.format("assertThat(thrown).hasMessageThat().contains(%s);", state.getSourceForNode(getOnlyElement(args))));
} else {
// expectedMessage(Matcher)
fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
newAsserts.add(String.format("assertThat(thrown.getMessage(), %s);", state.getSourceForNode(getOnlyElement(args))));
}
break;
default:
throw new AssertionError("unknown expect method: " + symbol.getSimpleName());
}
}
// remove all interactions with the ExpectedException rule
fix.replace(((JCTree) expectations.get(0)).getStartPosition(), state.getEndPosition(getLast(expectations)), "");
if (failure != null) {
fix.delete(failure);
}
return new BaseFix(fix.build(), exceptionClass, newAsserts);
}
Aggregations