/** * Fixes the error by assigning the result of the call to the receiver reference, or deleting the * method call. */ public Description describe(MethodInvocationTree methodInvocationTree, VisitorState state) { // Find the root of the field access chain, i.e. a.intern().trim() ==> a. ExpressionTree identifierExpr = ASTHelpers.getRootAssignable(methodInvocationTree); String identifierStr = null; Type identifierType = null; if (identifierExpr != null) { identifierStr = identifierExpr.toString(); if (identifierExpr instanceof JCIdent) { identifierType = ((JCIdent) identifierExpr).sym.type; } else if (identifierExpr instanceof JCFieldAccess) { identifierType = ((JCFieldAccess) identifierExpr).sym.type; } else { throw new IllegalStateException("Expected a JCIdent or a JCFieldAccess"); } } Type returnType = ASTHelpers.getReturnType(((JCMethodInvocation) methodInvocationTree).getMethodSelect()); Fix fix; if (identifierStr != null && !"this".equals(identifierStr) && returnType != null && state.getTypes().isAssignable(returnType, identifierType)) { // Fix by assigning the assigning the result of the call to the root receiver reference. fix = SuggestedFix.prefixWith(methodInvocationTree, identifierStr + " = "); } else { // Unclear what the programmer intended. Delete since we don't know what else to do. Tree parent = state.getPath().getParentPath().getLeaf(); fix = SuggestedFix.delete(parent); } return describeMatch(methodInvocationTree, fix); }
@Override public Description matchMethod(MethodTree methodTree, VisitorState state) { // if method is itself annotated with @Inject or it has no ancestor methods, return NO_MATCH; if (hasInjectAnnotation().matches(methodTree, state)) { return Description.NO_MATCH; } boolean foundJavaxInject = false; for (MethodSymbol superMethod : ASTHelpers.findSuperMethods(ASTHelpers.getSymbol(methodTree), state.getTypes())) { // With a Guice annotation, Guice will still inject the subclass-overridden method. if (ASTHelpers.hasAnnotation(superMethod, GUICE_INJECT_ANNOTATION, state)) { return Description.NO_MATCH; } // is not necessarily a match even if we find javax Inject on an ancestor // since a higher up ancestor may have @com.google.inject.Inject foundJavaxInject |= ASTHelpers.hasAnnotation(superMethod, JAVAX_INJECT_ANNOTATION, state); } if (foundJavaxInject) { return describeMatch( methodTree, SuggestedFix.builder() .addImport(JAVAX_INJECT_ANNOTATION) .prefixWith(methodTree, "@Inject\n") .build()); } return Description.NO_MATCH; }
@Override public Description matchMethodInvocation( MethodInvocationTree methodInvocationTree, VisitorState state) { if (methodInvocationTree.getArguments().isEmpty()) { return Description.NO_MATCH; } if (!TRUTH_SUBJECT_CALL.matches(methodInvocationTree, state)) { return Description.NO_MATCH; } ExpressionTree rec = ASTHelpers.getReceiver(methodInvocationTree); if (rec == null) { return Description.NO_MATCH; } if (!ASSERT_THAT.matches(rec, state)) { return Description.NO_MATCH; } ExpressionTree expr = getOnlyElement(((MethodInvocationTree) rec).getArguments()); if (expr == null) { return Description.NO_MATCH; } // check that argument of assertThat is a constant if (ASTHelpers.constValue(expr) == null) { return Description.NO_MATCH; } // check that expectation isn't a constant ExpressionTree expectation = getOnlyElement(methodInvocationTree.getArguments()); if (ASTHelpers.constValue(expectation) != null) { return Description.NO_MATCH; } SuggestedFix fix = SuggestedFix.swap(expr, expectation); return buildDescription(methodInvocationTree).addFix(fix).build(); }
@Override public Description matchTry(TryTree tree, VisitorState state) { if (tryTreeMatches(tree, state)) { List<? extends StatementTree> tryStatements = tree.getBlock().getStatements(); StatementTree lastTryStatement = tryStatements.get(tryStatements.size() - 1); String failCall = String.format("%nfail(\"Expected %s\");", exceptionToString(tree)); SuggestedFix.Builder fixBuilder = SuggestedFix.builder().postfixWith(lastTryStatement, failCall); // Make sure that when the fail import is added it doesn't conflict with existing ones. fixBuilder.removeStaticImport("junit.framework.Assert.fail"); fixBuilder.removeStaticImport("junit.framework.TestCase.fail"); fixBuilder.addStaticImport("org.junit.Assert.fail"); return describeMatch(lastTryStatement, fixBuilder.build()); } else { return Description.NO_MATCH; } }
/** * 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); }