Search in sources :

Example 1 with TreeScanner

use of com.sun.source.util.TreeScanner in project lombok by rzwitserloot.

the class HandleHelper method handle.

@Override
public void handle(AnnotationValues<Helper> annotation, JCAnnotation ast, JavacNode annotationNode) {
    handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.HELPER_FLAG_USAGE, "@Helper");
    deleteAnnotationIfNeccessary(annotationNode, Helper.class);
    JavacNode annotatedType = annotationNode.up();
    JavacNode containingBlock = annotatedType == null ? null : annotatedType.directUp();
    List<JCStatement> origStatements = getStatementsFromJcNode(containingBlock == null ? null : containingBlock.get());
    if (annotatedType == null || annotatedType.getKind() != Kind.TYPE || origStatements == null) {
        annotationNode.addError("@Helper is legal only on method-local classes.");
        return;
    }
    JCClassDecl annotatedType_ = (JCClassDecl) annotatedType.get();
    Iterator<JCStatement> it = origStatements.iterator();
    while (it.hasNext()) {
        if (it.next() == annotatedType_) {
            break;
        }
    }
    java.util.List<String> knownMethodNames = new ArrayList<String>();
    for (JavacNode ch : annotatedType.down()) {
        if (ch.getKind() != Kind.METHOD)
            continue;
        String n = ch.getName();
        if (n == null || n.isEmpty() || n.charAt(0) == '<')
            continue;
        knownMethodNames.add(n);
    }
    Collections.sort(knownMethodNames);
    final String[] knownMethodNames_ = knownMethodNames.toArray(new String[knownMethodNames.size()]);
    final Name helperName = annotationNode.toName("$" + annotatedType_.name);
    final boolean[] helperUsed = new boolean[1];
    final JavacTreeMaker maker = annotationNode.getTreeMaker();
    TreeVisitor<Void, Void> visitor = new TreeScanner<Void, Void>() {

        @Override
        public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
            JCMethodInvocation jcmi = (JCMethodInvocation) node;
            apply(jcmi);
            return super.visitMethodInvocation(node, p);
        }

        private void apply(JCMethodInvocation jcmi) {
            if (!(jcmi.meth instanceof JCIdent))
                return;
            JCIdent jci = (JCIdent) jcmi.meth;
            if (Arrays.binarySearch(knownMethodNames_, jci.name.toString()) < 0)
                return;
            jcmi.meth = maker.Select(maker.Ident(helperName), jci.name);
            helperUsed[0] = true;
        }
    };
    while (it.hasNext()) {
        JCStatement stat = it.next();
        stat.accept(visitor, null);
    }
    if (!helperUsed[0]) {
        annotationNode.addWarning("No methods of this helper class are ever used.");
        return;
    }
    ListBuffer<JCStatement> newStatements = new ListBuffer<JCStatement>();
    boolean mark = false;
    for (JCStatement stat : origStatements) {
        newStatements.append(stat);
        if (mark || stat != annotatedType_)
            continue;
        mark = true;
        JCExpression init = maker.NewClass(null, List.<JCExpression>nil(), maker.Ident(annotatedType_.name), List.<JCExpression>nil(), null);
        JCExpression varType = maker.Ident(annotatedType_.name);
        JCVariableDecl decl = maker.VarDef(maker.Modifiers(Flags.FINAL), helperName, varType, init);
        newStatements.append(decl);
    }
    setStatementsOfJcNode(containingBlock.get(), newStatements.toList());
}
Also used : JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) JCIdent(com.sun.tools.javac.tree.JCTree.JCIdent) JavacTreeMaker(lombok.javac.JavacTreeMaker) ListBuffer(com.sun.tools.javac.util.ListBuffer) ArrayList(java.util.ArrayList) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JavacNode(lombok.javac.JavacNode) TreeScanner(com.sun.source.util.TreeScanner) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree)

Example 2 with TreeScanner

use of com.sun.source.util.TreeScanner in project error-prone by google.

the class UFreeIdent method defaultAction.

@Override
protected Choice<Unifier> defaultAction(Tree target, final Unifier unifier) {
    if (target instanceof JCExpression) {
        JCExpression expression = (JCExpression) target;
        JCExpression currentBinding = unifier.getBinding(key());
        // Check that the expression does not reference any template-local variables.
        boolean isGood = trueOrNull(new TreeScanner<Boolean, Void>() {

            @Override
            public Boolean reduce(@Nullable Boolean left, @Nullable Boolean right) {
                return trueOrNull(left) && trueOrNull(right);
            }

            @Override
            public Boolean visitIdentifier(IdentifierTree ident, Void v) {
                Symbol identSym = ASTHelpers.getSymbol(ident);
                for (ULocalVarIdent.Key key : Iterables.filter(unifier.getBindings().keySet(), ULocalVarIdent.Key.class)) {
                    if (identSym == unifier.getBinding(key).getSymbol()) {
                        return false;
                    }
                }
                return true;
            }
        }.scan(expression, null));
        if (!isGood) {
            return Choice.none();
        } else if (currentBinding == null) {
            unifier.putBinding(key(), expression);
            return Choice.of(unifier);
        } else if (currentBinding.toString().equals(expression.toString())) {
            // If it's the same code, treat it as the same expression.
            return Choice.of(unifier);
        }
    }
    return Choice.none();
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) TreeScanner(com.sun.source.util.TreeScanner) Symbol(com.sun.tools.javac.code.Symbol) IdentifierTree(com.sun.source.tree.IdentifierTree) Nullable(javax.annotation.Nullable)

Example 3 with TreeScanner

use of com.sun.source.util.TreeScanner in project ceylon by eclipse.

the class TestPos method main.

public static void main(String... args) throws IOException {
    final boolean[] sawError = { false };
    final StringBuilder log = new StringBuilder();
    class MyFileObject extends SimpleJavaFileObject {

        MyFileObject() {
            super(URI.create("myfo:///Test.java"), SOURCE);
        }

        @Override
        public String getCharContent(boolean ignoreEncodingErrors) {
            // 0123456789012345678901234567890123456789012345678901234
            return "class Test { { Object[] o = new <T,e,s,t>Object[0]; } }";
        }
    }
    class Scanner extends TreeScanner<Void, Trees> {

        CompilationUnitTree toplevel = null;

        @Override
        public Void visitCompilationUnit(CompilationUnitTree node, Trees trees) {
            toplevel = node;
            return super.visitCompilationUnit(node, trees);
        }

        @Override
        public Void visitErroneous(ErroneousTree node, Trees trees) {
            sawError[0] = true;
            long startPos = trees.getSourcePositions().getStartPosition(toplevel, node);
            long endPos = trees.getSourcePositions().getEndPosition(toplevel, node);
            log.append(String.format("begin=%s, end=%s : %s%n", startPos, endPos, node.getErrorTrees()));
            if (startPos != 28)
                error("Start pos for %s is incorrect (%s)!", node, startPos);
            if (endPos != 50)
                error("End pos for %s is incorrect (%s)!", node, endPos);
            return null;
        }
    }
    JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
    List<JavaFileObject> compilationUnits = Collections.<JavaFileObject>singletonList(new MyFileObject());
    DiagnosticListener<JavaFileObject> dl = new DiagnosticListener<JavaFileObject>() {

        public void report(Diagnostic<? extends JavaFileObject> diag) {
            log.append(String.format("%s @ %s%n", diag.getCode(), diag.getPosition()));
            if (!diag.getCode().equals(errCode))
                error("unexpected error");
            if (diag.getPosition() != 33)
                error("Error pos for %s is incorrect (%s)!", diag.getCode(), diag.getPosition());
            sawError[0] = true;
        }
    };
    JavacTask task = (JavacTask) javac.getTask(null, null, dl, null, null, compilationUnits);
    Trees trees = Trees.instance(task);
    Iterable<? extends Tree> toplevels = task.parse();
    if (!sawError[0])
        error("No parse error detected");
    sawError[0] = false;
    new Scanner().scan(toplevels, trees);
    if (!sawError[0])
        error("No error tree detected");
    if (!log.toString().equals(expected))
        error("Unexpected log message: %n%s%n", log);
    System.out.print(log);
    System.out.flush();
}
Also used : SimpleJavaFileObject(javax.tools.SimpleJavaFileObject) Trees(com.sun.source.util.Trees) TreeScanner(com.sun.source.util.TreeScanner) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) JavaCompiler(javax.tools.JavaCompiler) Diagnostic(javax.tools.Diagnostic) DiagnosticListener(javax.tools.DiagnosticListener) SimpleJavaFileObject(javax.tools.SimpleJavaFileObject) JavaFileObject(javax.tools.JavaFileObject) TreeScanner(com.sun.source.util.TreeScanner) ErroneousTree(com.sun.source.tree.ErroneousTree) JavacTask(com.sun.source.util.JavacTask)

Example 4 with TreeScanner

use of com.sun.source.util.TreeScanner in project error-prone by google.

the class FindIdentifiers method createFindIdentifiersScanner.

/**
 * Finds all identifiers in a tree. Takes an optional stop point as its argument: the depth-first
 * walk will stop if this node is encountered.
 */
private static final TreeScanner<Void, Void> createFindIdentifiersScanner(ImmutableSet.Builder<Symbol> builder, @Nullable Tree stoppingPoint) {
    return new TreeScanner<Void, Void>() {

        @Override
        public Void scan(Tree tree, Void unused) {
            return Objects.equals(stoppingPoint, tree) ? null : super.scan(tree, unused);
        }

        @Override
        public Void scan(Iterable<? extends Tree> iterable, Void unused) {
            if (stoppingPoint != null && iterable != null) {
                ImmutableList.Builder<Tree> builder = ImmutableList.builder();
                for (Tree t : iterable) {
                    if (stoppingPoint.equals(t)) {
                        break;
                    }
                    builder.add(t);
                }
                iterable = builder.build();
            }
            return super.scan(iterable, unused);
        }

        @Override
        public Void visitIdentifier(IdentifierTree identifierTree, Void unused) {
            Symbol symbol = ASTHelpers.getSymbol(identifierTree);
            if (symbol != null) {
                builder.add(symbol);
            }
            return null;
        }
    };
}
Also used : TreeScanner(com.sun.source.util.TreeScanner) ImmutableList(com.google.common.collect.ImmutableList) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) ForLoopTree(com.sun.source.tree.ForLoopTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) TryTree(com.sun.source.tree.TryTree) IdentifierTree(com.sun.source.tree.IdentifierTree)

Example 5 with TreeScanner

use of com.sun.source.util.TreeScanner in project error-prone by google.

the class AssertionFailureIgnored method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
    if (!ASSERTION.matches(tree, state)) {
        return NO_MATCH;
    }
    JCTry tryStatement = enclosingTry(state);
    if (tryStatement == null) {
        return NO_MATCH;
    }
    Optional<JCCatch> maybeCatchTree = catchesType(tryStatement, state.getSymtab().assertionErrorType, state);
    if (!maybeCatchTree.isPresent()) {
        return NO_MATCH;
    }
    JCCatch catchTree = maybeCatchTree.get();
    VarSymbol parameter = ASTHelpers.getSymbol(catchTree.getParameter());
    boolean rethrows = firstNonNull(new TreeScanner<Boolean, Void>() {

        @Override
        public Boolean visitThrow(ThrowTree tree, Void unused) {
            if (Objects.equals(parameter, ASTHelpers.getSymbol(tree.getExpression()))) {
                return true;
            }
            if (NEW_THROWABLE.matches(tree.getExpression(), state) && ((NewClassTree) tree.getExpression()).getArguments().stream().anyMatch(arg -> Objects.equals(parameter, ASTHelpers.getSymbol(arg)))) {
                return true;
            }
            return super.visitThrow(tree, null);
        }

        @Override
        public Boolean reduce(Boolean a, Boolean b) {
            return firstNonNull(a, false) || firstNonNull(b, false);
        }
    }.scan(catchTree.getBlock(), null), false);
    if (rethrows) {
        return NO_MATCH;
    }
    Description.Builder description = buildDescription(tree);
    buildFix(tryStatement, tree, state).ifPresent(description::addFix);
    return description.build();
}
Also used : Iterables(com.google.common.collect.Iterables) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCTry(com.sun.tools.javac.tree.JCTree.JCTry) TypePredicates(com.google.errorprone.predicates.TypePredicates) VisitorState(com.google.errorprone.VisitorState) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Matchers.expressionStatement(com.google.errorprone.matchers.Matchers.expressionStatement) Kind(com.sun.source.tree.Tree.Kind) NewClassTree(com.sun.source.tree.NewClassTree) LIKELY_ERROR(com.google.errorprone.BugPattern.StandardTags.LIKELY_ERROR) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) Matcher(com.google.errorprone.matchers.Matcher) Fix(com.google.errorprone.fixes.Fix) Tree(com.sun.source.tree.Tree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) MethodInvocationTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher) UnionClassType(com.sun.tools.javac.code.Type.UnionClassType) ExpressionTree(com.sun.source.tree.ExpressionTree) Iterables.getLast(com.google.common.collect.Iterables.getLast) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) Streams(com.google.common.collect.Streams) JCCatch(com.sun.tools.javac.tree.JCTree.JCCatch) TreeScanner(com.sun.source.util.TreeScanner) Objects(java.util.Objects) ThrowTree(com.sun.source.tree.ThrowTree) MethodMatchers.staticMethod(com.google.errorprone.matchers.method.MethodMatchers.staticMethod) Stream(java.util.stream.Stream) Description(com.google.errorprone.matchers.Description) MethodMatchers(com.google.errorprone.matchers.method.MethodMatchers) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement) Optional(java.util.Optional) MoreObjects.firstNonNull(com.google.common.base.MoreObjects.firstNonNull) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ASTHelpers.isSubtype(com.google.errorprone.util.ASTHelpers.isSubtype) Pattern(java.util.regex.Pattern) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) Description(com.google.errorprone.matchers.Description) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) JCTry(com.sun.tools.javac.tree.JCTree.JCTry) TreeScanner(com.sun.source.util.TreeScanner) ThrowTree(com.sun.source.tree.ThrowTree) JCCatch(com.sun.tools.javac.tree.JCTree.JCCatch)

Aggregations

TreeScanner (com.sun.source.util.TreeScanner)9 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)5 Tree (com.sun.source.tree.Tree)5 IdentifierTree (com.sun.source.tree.IdentifierTree)4 Symbol (com.sun.tools.javac.code.Symbol)4 BugPattern (com.google.errorprone.BugPattern)3 WARNING (com.google.errorprone.BugPattern.SeverityLevel.WARNING)3 VisitorState (com.google.errorprone.VisitorState)3 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)3 Description (com.google.errorprone.matchers.Description)3 ASTHelpers (com.google.errorprone.util.ASTHelpers)3 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)3 VariableTree (com.sun.source.tree.VariableTree)3 VarSymbol (com.sun.tools.javac.code.Symbol.VarSymbol)3 ImmutableList (com.google.common.collect.ImmutableList)2 Streams (com.google.common.collect.Streams)2 JDK (com.google.errorprone.BugPattern.Category.JDK)2 MethodInvocationTreeMatcher (com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher)2 NO_MATCH (com.google.errorprone.matchers.Description.NO_MATCH)2 Matcher (com.google.errorprone.matchers.Matcher)2