@Override public Boolean visitIdentifier(IdentifierTree node, Void v) { return idMatcher.matches(node, ancestorState.withPath(getCurrentPath())); }
@Override public boolean matches(U unused, VisitorState state) { TreePath pathToEnclosing = state.findPathToEnclosing(clazz); // No match if there is no enclosing element to match against if (pathToEnclosing == null) { return false; } T enclosing = clazz.cast(pathToEnclosing.getLeaf()); return matcher.matches(enclosing, state.withPath(pathToEnclosing)); } }
@Override public Void visitIdentifier(IdentifierTree identifierTree, Void unused) { if (!Objects.equals(getSymbol(identifierTree), symbol)) { return null; } if (matcher.matches(identifierTree, state.withPath(getCurrentPath()))) { isUsed = true; return null; } usageSites.add(getCurrentPath()); return null; }
private static VisitorState getCheckState(VisitorState state) { // Gets the VisitorState to start from when checking how to qualify the name. This won't work // correctly in all cases 1) it assumes there is only 1 top level type; 2) it doesn't look for // all of the locations where the symbol-to-be-replaced is used in the compilation unit. // Really, we should gather all of the usages first, and check them all. // It is assumed that this will work sufficiently until proven otherwise. CompilationUnitTree compilationUnit = state.getPath().getCompilationUnit(); if (compilationUnit.getTypeDecls().isEmpty()) { return state; } return state.withPath(TreePath.getPath(compilationUnit, compilationUnit.getTypeDecls().get(0))); }
@Override public void apply(TreePath tree, Context context, DescriptionListener listener) { scanner().scan(tree, createVisitorState(context, listener).withPath(tree)); }
@Override public MultiMatchResult<N> multiMatchResult(T tree, VisitorState state) { ImmutableList.Builder<Matchable<N>> result = ImmutableList.builder(); for (N subnode : getChildNodes(tree, state)) { TreePath newPath = new TreePath(state.getPath(), subnode); result.add(Matchable.create(subnode, state.withPath(newPath))); } MatchResult<N> matchResult = listMatcher.matches(result.build(), nodeMatcher); return MultiMatchResult.create(matchResult.matches(), matchResult.matchingNodes()); }
@Override public boolean matches(T unused, VisitorState state) { TreePath pathToEnclosing = state.findPathToEnclosing(CaseTree.class, BlockTree.class); if (pathToEnclosing == null) { return false; } Tree enclosing = pathToEnclosing.getLeaf(); state = state.withPath(pathToEnclosing); if (enclosing instanceof BlockTree) { return blockTreeMatcher.matches((BlockTree) enclosing, state); } else if (enclosing instanceof CaseTree) { return caseTreeMatcher.matches((CaseTree) enclosing, state); } else { // findEnclosing given two types must return something of one of those types throw new IllegalStateException("enclosing tree not a BlockTree or CaseTree"); } } }
static VisitorState makeVisitorState(Tree target, Unifier unifier) { Context context = unifier.getContext(); TreePath path = TreePath.getPath(context.get(JCCompilationUnit.class), target); return new VisitorState(context).withPath(path); } }
@Override public Description matchLambdaExpression(LambdaExpressionTree tree, VisitorState state) { analyze(state.withPath(new TreePath(state.getPath(), tree.getBody()))); return NO_MATCH; }
@Override public Void visitMethodInvocation(MethodInvocationTree node, Void unused) { Description description = matchMethodInvocation(node, state.withPath(getCurrentPath())); if (description != Description.NO_MATCH) { state.reportMatch(description); } return super.visitMethodInvocation(node, null); }
@Override public Void visitClass(ClassTree node, Void unused) { if (immutableChecker.matchClass(node, createVisitorState().withPath(getCurrentPath())) != Description.NO_MATCH) { ok[0] = false; } return super.visitClass(node, null); }
@Override public Void visitNewClass(NewClassTree node, Void unused) { if (immutableChecker.matchNewClass(node, createVisitorState().withPath(getCurrentPath())) != Description.NO_MATCH) { ok[0] = false; } return super.visitNewClass(node, null); }
@SuppressWarnings("unchecked") // TODO(cushon): this should take a Class<T> @Override public boolean matches(Tree t, VisitorState state) { TreePath path = state.getPath().getParentPath(); while (path != null) { Tree node = path.getLeaf(); state = state.withPath(path); if (matcher.matches((T) node, state)) { return true; } path = path.getParentPath(); } return false; } };
@Override public boolean matches(Tree tree, VisitorState state) { Tree parent = state.getPath().getParentPath().getLeaf(); try { return treeMatcher.matches(parent, state.withPath(state.getPath().getParentPath())); } catch (ClassCastException e) { return false; } } }
@Override public Void visitMethodInvocation(MethodInvocationTree node, Void unused) { VisitorState subState = state.withPath(getCurrentPath()); ExpressionTree argument; ProblemUsage problemType; if (CHECK_NOT_NULL.matches(node, subState)) { argument = node.getArguments().get(0); problemType = ProblemUsage.CHECK_NOT_NULL; } else if (matchTestAssertions && ASSERT_NOT_NULL.matches(node, subState)) { argument = getLast(node.getArguments()); problemType = ProblemUsage.JUNIT; } else if (matchTestAssertions && TRUTH_NOT_NULL.matches(node, subState)) { argument = getOnlyElement(((MethodInvocationTree) getReceiver(node)).getArguments()); problemType = ProblemUsage.TRUTH; } else { return super.visitMethodInvocation(node, null); } getFixer(argument, subState) .map(f -> describeMatch(node, problemType.fix(f, node, subState))) .ifPresent(state::reportMatch); return super.visitMethodInvocation(node, null); }
@Override public Void visitBinary(BinaryTree binary, Void unused) { if (!COMPARISON_OPERATORS.contains(binary.getKind())) { return super.visitBinary(binary, null); } VisitorState subState = state.withPath(getCurrentPath()); Optional<Fixer> fixer = Optional.empty(); if (isNull(binary.getLeftOperand())) { fixer = getFixer(binary.getRightOperand(), subState); } if (isNull(binary.getRightOperand())) { fixer = getFixer(binary.getLeftOperand(), subState); } fixer .map(f -> describeMatch(binary, ProblemUsage.COMPARISON.fix(f, binary, subState))) .ifPresent(state::reportMatch); return super.visitBinary(binary, null); }
@Override public Void visitMethodInvocation(MethodInvocationTree tree, VisitorState state) { VisitorState nowState = state.withPath(TreePath.getPath(state.getPath(), tree)); if (!inShadowClass) { for (MethodInvocationMatcher matcher : matchers) { if (matcher.matcher().matches(tree, state)) { matcher.replace(tree, nowState, fixBuilder, possibleFixes); return null; } } } return super.visitMethodInvocation(tree, nowState); } }.scan(tree, state);
@Override public Void visitClass(ClassTree node, InitializationContext init) { VisitorState state = new VisitorState(context).withPath(getCurrentPath()); if (isSuppressed(node)) { return null; } for (String annotation : IMPLICIT_VAR_CLASS_ANNOTATIONS) { if (ASTHelpers.hasAnnotation(getSymbol(node), annotation, state)) { return null; } } // reset the initialization context when entering a new declaration return super.visitClass(node, InitializationContext.NONE); }
@Override public Void visitMethodInvocation(MethodInvocationTree tree, VisitorState state) { VisitorState nowState = state.withPath(TreePath.getPath(state.getPath(), tree)); if (!inShadowClass && shadowStaticMatcher.matches(tree, nowState)) { // Replace ShadowXxx.method() with Xxx.method() where possible... JCFieldAccess methodSelect = (JCFieldAccess) tree.getMethodSelect(); ClassSymbol owner = (ClassSymbol) methodSelect.sym.owner; ClassType shadowedClass = determineShadowedClassName(owner, nowState); String shadowedTypeName = SuggestedFixes.prettyType(state, possibleFixes.fixBuilder, shadowedClass); possibleFixes.fixByReplacing(methodSelect.selected, shadowedTypeName); } if (!inShadowClass && shadowOfMatcher.matches(tree, nowState)) { matchedShadowOf(tree, nowState); } return super.visitMethodInvocation(tree, nowState); } }
private static boolean collectionUsed(VisitorState state) { TreePath path = state.getPath(); return !(path.getParentPath().getLeaf() instanceof MemberSelectTree) || !(path.getParentPath().getParentPath().getLeaf() instanceof MethodInvocationTree) || !COLLECTION_SETTER.matches( (MethodInvocationTree) path.getParentPath().getParentPath().getLeaf(), state) || ASTHelpers.targetType(state.withPath(path.getParentPath().getParentPath())) != null; }