@Override public boolean matches(ClassTree t, VisitorState state) { for (Tree member : t.getMembers()) { if (member instanceof MethodTree) { if (methodMatcher.matches((MethodTree) member, state)) { return true; } } } return false; } };
private static MethodTree getMethod( Matcher<MethodTree> methodMatcher, ClassTree classTree, VisitorState state) { for (Tree member : classTree.getMembers()) { if (member instanceof MethodTree) { MethodTree memberTree = (MethodTree) member; if (methodMatcher.matches(memberTree, state)) { return memberTree; } } } return null; }
@Override public Description matchClass(ClassTree tree, VisitorState state) { return checkDeclarations(tree.getMembers(), state); }
/** * Returns a list of {@link MethodTree} declared in the given {@code classTree}. * * <p>Only method trees that belong to the {@code classTree} are returned, so methods declared in * nested classes are not going to be considered. */ private ImmutableList<MethodTree> getClassTreeMethods(ClassTree classTree) { List<? extends Tree> members = classTree.getMembers(); return members.stream() .filter(MethodTree.class::isInstance) .map(MethodTree.class::cast) .filter(m -> !isSuppressed(m)) .collect(toImmutableList()); }
@Override protected Iterable<? extends MethodTree> getChildNodes(ClassTree classTree, VisitorState state) { ImmutableList.Builder<MethodTree> result = ImmutableList.builder(); // Iterate over members of class (methods and fields). for (Tree member : classTree.getMembers()) { // If this member is a constructor... if (member instanceof MethodTree && ASTHelpers.getSymbol(member).isConstructor()) { result.add((MethodTree) member); } } return result.build(); } }
/** Returns the list of all constructors defined in the class (including generated ones). */ public static List<MethodTree> getConstructors(ClassTree classTree) { List<MethodTree> constructors = new ArrayList<>(); for (Tree member : classTree.getMembers()) { if (member instanceof MethodTree) { MethodTree methodTree = (MethodTree) member; if (getSymbol(methodTree).isConstructor()) { constructors.add(methodTree); } } } return constructors; }
private void handleMapAnonClass( MaplikeMethodRecord methodRecord, MethodInvocationTree observableDotMap, ClassTree annonClassBody, VisitorState state) { for (Tree t : annonClassBody.getMembers()) { if (t instanceof MethodTree && ((MethodTree) t).getName().toString().equals(methodRecord.getInnerMethodName())) { observableCallToInnerMethodOrLambda.put(observableDotMap, (MethodTree) t); } } }
@Override public UClassDecl visitClass(ClassTree tree, Void v) { ImmutableList.Builder<UMethodDecl> decls = ImmutableList.builder(); for (MethodTree decl : Iterables.filter(tree.getMembers(), MethodTree.class)) { if (decl.getReturnType() != null) { decls.add(visitMethod(decl, null)); } } return UClassDecl.create(decls.build()); }
private void handleFilterAnonClass( StreamTypeRecord streamType, MethodInvocationTree observableDotFilter, ClassTree annonClassBody, VisitorState state) { for (Tree t : annonClassBody.getMembers()) { if (t instanceof MethodTree && ((MethodTree) t).getName().toString().equals("test")) { filterMethodOrLambdaSet.add(t); observableCallToInnerMethodOrLambda.put(observableDotFilter, (MethodTree) t); handleChainFromFilter(streamType, observableDotFilter, t, state); } } }
@Override public boolean matches(Tree tree, VisitorState visitorState) { if (!(tree instanceof NewClassTree)) { return false; } NewClassTree newClassTree = (NewClassTree) tree; if (newClassTree.getClassBody() == null) { return false; } return newClassTree.getClassBody().getMembers().stream() .filter(mem -> mem instanceof VariableTree) .anyMatch(mem -> !isFinal(mem)); }
@Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { if (CALLS_TO_SYSTEM_EXIT_OUTSIDE_MAIN.matches(tree, state)) { Optional<? extends Tree> mainMethodInThisClass = ASTHelpers.findEnclosingNode(state.getPath(), ClassTree.class).getMembers().stream() .filter(t -> t instanceof MethodTree) .filter(t -> MAIN_METHOD.matches((MethodTree) t, state)) .findAny(); return mainMethodInThisClass.isPresent() ? Description.NO_MATCH : describeMatch(tree); } return Description.NO_MATCH; } }
@Override public Description matchClass(ClassTree classTree, VisitorState state) { if (!ASTHelpers.isSubtype( ASTHelpers.getType(classTree), state.getSymtab().throwableType, state)) { return Description.NO_MATCH; } ImmutableList<MethodTree> methods = classTree.getMembers().stream() .filter(m -> m instanceof MethodTree) .map(m -> (MethodTree) m) .collect(toImmutableList()); if (methods.stream().anyMatch(m -> m.getName().contentEquals("getMessage"))) { return Description.NO_MATCH; } return methods.stream() .filter(m -> Matchers.toStringMethodDeclaration().matches(m, state)) .findFirst() .map(m -> describeMatch(classTree, SuggestedFixes.renameMethod(m, "getMessage", state))) .orElse(Description.NO_MATCH); } }
@Override public Description matchClass(ClassTree classTree, VisitorState state) { // collect all member methods and their indices in the list of members, grouped by name LinkedHashMultimap<OverloadKey, MemberWithIndex> methods = LinkedHashMultimap.create(); for (int i = 0; i < classTree.getMembers().size(); ++i) { Tree member = classTree.getMembers().get(i); if (member instanceof MethodTree) { MethodTree methodTree = (MethodTree) member; methods.put(OverloadKey.create(methodTree), MemberWithIndex.create(i, methodTree)); } } ImmutableList<Description> descriptions = methods.asMap().entrySet().stream() .flatMap( e -> checkOverloads( state, classTree.getMembers(), ImmutableList.copyOf(e.getValue()))) .collect(toImmutableList()); if (batchFindings && !descriptions.isEmpty()) { SuggestedFix.Builder fix = SuggestedFix.builder(); descriptions.forEach(d -> fix.merge((SuggestedFix) getOnlyElement(d.fixes))); return buildDescription(descriptions.get(0).position).addFix(fix.build()).build(); } descriptions.forEach(state::reportMatch); return NO_MATCH; }
@Override public Description matchClass(ClassTree tree, VisitorState state) { if (ASTHelpers.hasAnnotation(tree, "com.google.auto.value.AutoValue", state)) { for (Tree memberTree : tree.getMembers()) { if (memberTree instanceof MethodTree && !isSuppressed(memberTree)) { MethodTree methodTree = (MethodTree) memberTree; if (ABSTRACT_MATCHER.matches(methodTree, state)) { for (Map.Entry<String, Matcher<MethodTree>> entry : REPLACEMENT_TO_MATCHERS.entries()) { if (entry.getValue().matches(methodTree, state)) { state.reportMatch( buildDescription(methodTree) .setMessage(String.format(MESSAGE, entry.getKey())) .build()); } } } } } } return NO_MATCH; } }
private static SuggestedFix fixClass(ClassTree classTree, VisitorState state) { int startPos = ((JCTree) classTree).getStartPosition(); int endPos = ((JCTree) classTree.getMembers().get(0)).getStartPosition(); ImmutableList<ErrorProneToken> tokens = ErrorProneTokens.getTokens( state.getSourceCode().subSequence(startPos, endPos).toString(), state.context); String modifiers = getSymbol(classTree).owner.enclClass() == null ? "final class" : "static final class"; SuggestedFix.Builder fix = SuggestedFix.builder(); for (ErrorProneToken token : tokens) { if (token.kind() == TokenKind.INTERFACE) { fix.replace(startPos + token.pos(), startPos + token.endPos(), modifiers); } } return fix.build(); } }
@Override public Choice<Unifier> visitClass(ClassTree node, Unifier unifier) { Choice<UnifierWithRemainingMembers> path = Choice.of(UnifierWithRemainingMembers.create(unifier, getMembers())); for (Tree targetMember : node.getMembers()) { if (!(targetMember instanceof MethodTree) || ((MethodTree) targetMember).getReturnType() != null) { // skip synthetic constructors path = path.thenChoose(match(targetMember)); } } return path.condition(s -> s.remainingMembers().isEmpty()) .transform(UnifierWithRemainingMembers::unifier); }
public static Collection<? extends CodeTransformer> extractRules( ClassTree tree, Context context) { ClassSymbol sym = ASTHelpers.getSymbol(tree); RefasterRuleBuilderScanner scanner = new RefasterRuleBuilderScanner(context); // visit abstract methods first List<MethodTree> methods = new Ordering<MethodTree>() { @Override public int compare(MethodTree l, MethodTree r) { return Boolean.compare( l.getModifiers().getFlags().contains(Modifier.ABSTRACT), r.getModifiers().getFlags().contains(Modifier.ABSTRACT)); } }.reverse().immutableSortedCopy(Iterables.filter(tree.getMembers(), MethodTree.class)); scanner.visit(methods, null); UTemplater templater = new UTemplater(context); List<UType> types = templater.templateTypes(sym.type.getTypeArguments()); return scanner.createMatchers( Iterables.filter(types, UTypeVar.class), sym.getQualifiedName().toString(), UTemplater.annotationMap(sym)); }
private static SuggestedFix.Builder addPrivateConstructor(ClassTree classTree) { SuggestedFix.Builder fix = SuggestedFix.builder(); String indent = " "; for (Tree member : classTree.getMembers()) { if (member.getKind().equals(METHOD) && !isGeneratedConstructor((MethodTree) member)) { fix.prefixWith( member, indent + "private " + classTree.getSimpleName() + "() {} // no instances\n" + indent); break; } if (!member.getKind().equals(METHOD)) { indent = ""; } } return fix; } }
@Override public Void visitClass(ClassTree node, Context context) { Symbol sym = ASTHelpers.getSymbol(node); if (sym == null || !sym.getQualifiedName().contentEquals(rule().qualifiedTemplateClass())) { ListBuffer<JCStatement> statements = new ListBuffer<>(); for (Tree tree : node.getMembers()) { if (tree instanceof JCStatement) { statements.append((JCStatement) tree); } else { tree.accept(this, context); } } scan(TreeMaker.instance(context).Block(0, statements.toList()), context); } return null; }
/** * Find the node which (approximately) follows this one in the tree. This works by walking upwards * to find enclosing block (or class) and then looking for the node after the subtree we walked. * If our subtree is the last of the block then we return the node for the block instead, if we * can't find a suitable block we return the parent node. */ private static Tree getNextNodeOrParent(Tree current, VisitorState state) { Tree predecessorNode = current; TreePath enclosingPath = state.getPath(); while (enclosingPath != null && !(enclosingPath.getLeaf() instanceof BlockTree) && !(enclosingPath.getLeaf() instanceof ClassTree)) { predecessorNode = enclosingPath.getLeaf(); enclosingPath = enclosingPath.getParentPath(); } if (enclosingPath == null) { return state.getPath().getParentPath().getLeaf(); } Tree parent = enclosingPath.getLeaf(); if (parent instanceof BlockTree) { return after(predecessorNode, ((BlockTree) parent).getStatements(), parent); } else if (parent instanceof ClassTree) { return after(predecessorNode, ((ClassTree) parent).getMembers(), parent); } return parent; }