Search in sources :

Example 1 with TryTree

use of com.sun.source.tree.TryTree in project error-prone by google.

the class TryFailThrowable method tryTreeMatches.

private static MatchResult tryTreeMatches(TryTree tryTree, VisitorState state) {
    BlockTree tryBlock = tryTree.getBlock();
    List<? extends StatementTree> statements = tryBlock.getStatements();
    if (statements.isEmpty()) {
        return doesNotMatch();
    }
    // Check if any of the statements is a fail or assert* method (i.e. any
    // method that can throw an AssertionFailedError)
    StatementTree failStatement = null;
    for (StatementTree statement : statements) {
        if (!(statement instanceof ExpressionStatementTree)) {
            continue;
        }
        if (failOrAssert.matches(((ExpressionStatementTree) statement).getExpression(), state)) {
            failStatement = statement;
            break;
        }
    }
    if (failStatement == null) {
        return doesNotMatch();
    }
    // Verify that the only catch clause catches Throwable
    List<? extends CatchTree> catches = tryTree.getCatches();
    if (catches.size() != 1) {
        // to be checked - it would either be Throwable or Error.
        return doesNotMatch();
    }
    CatchTree catchTree = catches.get(0);
    VariableTree catchType = catchTree.getParameter();
    boolean catchesThrowable = javaLangThrowable.matches(catchType, state);
    boolean catchesError = javaLangError.matches(catchType, state);
    boolean catchesOtherError = someAssertionFailure.matches(catchType, state);
    if (!catchesThrowable && !catchesError && !catchesOtherError) {
        return doesNotMatch();
    }
    // Verify that the catch block is empty or contains only comments.
    List<? extends StatementTree> catchStatements = catchTree.getBlock().getStatements();
    for (StatementTree catchStatement : catchStatements) {
        // or a list of empty statements.
        if (!Matchers.<Tree>kindIs(EMPTY_STATEMENT).matches(catchStatement, state)) {
            return doesNotMatch();
        }
    }
    return matches(failStatement, catchesThrowable ? JAVA_LANG_THROWABLE : catchesError ? JAVA_LANG_ERROR : SOME_ASSERTION_FAILURE);
}
Also used : ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) StatementTree(com.sun.source.tree.StatementTree) CatchTree(com.sun.source.tree.CatchTree) VariableTree(com.sun.source.tree.VariableTree) BlockTree(com.sun.source.tree.BlockTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) CatchTree(com.sun.source.tree.CatchTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) TryTree(com.sun.source.tree.TryTree)

Example 2 with TryTree

use of com.sun.source.tree.TryTree in project error-prone by google.

the class AbstractMustBeClosedChecker method tryFinallyClose.

private boolean tryFinallyClose(VarSymbol var, TreePath path, VisitorState state) {
    if ((var.flags() & (Flags.FINAL | Flags.EFFECTIVELY_FINAL)) == 0) {
        return false;
    }
    Tree parent = path.getParentPath().getLeaf();
    if (parent.getKind() != Tree.Kind.BLOCK) {
        return false;
    }
    BlockTree block = (BlockTree) parent;
    int idx = block.getStatements().indexOf(path.getLeaf());
    if (idx == -1 || idx == block.getStatements().size() - 1) {
        return false;
    }
    StatementTree next = block.getStatements().get(idx + 1);
    if (!(next instanceof TryTree)) {
        return false;
    }
    TryTree tryTree = (TryTree) next;
    if (tryTree.getFinallyBlock() == null) {
        return false;
    }
    boolean[] closed = { false };
    tryTree.getFinallyBlock().accept(new TreeScanner<Void, Void>() {

        @Override
        public Void visitMethodInvocation(MethodInvocationTree tree, Void unused) {
            if (CLOSE_METHOD.matches(tree, state) && Objects.equals(getSymbol(getReceiver(tree)), var)) {
                closed[0] = true;
            }
            return null;
        }
    }, null);
    return closed[0];
}
Also used : StatementTree(com.sun.source.tree.StatementTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) MethodTree(com.sun.source.tree.MethodTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Tree(com.sun.source.tree.Tree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) TryTree(com.sun.source.tree.TryTree) BlockTree(com.sun.source.tree.BlockTree) TryTree(com.sun.source.tree.TryTree)

Example 3 with TryTree

use of com.sun.source.tree.TryTree in project groovy-cps by cloudbees.

the class Translator method translateMethod.

/**
 * @param e
 *      Method in {@code fqcn} to translate.
 */
private void translateMethod(final CompilationUnitTree cut, ExecutableElement e, JDefinedClass $output, String fqcn, String overloadResolved) {
    String methodName = n(e);
    boolean isPublic = e.getModifiers().contains(Modifier.PUBLIC);
    JMethod delegating = $output.method(isPublic ? JMod.PUBLIC | JMod.STATIC : JMod.STATIC, (JType) null, methodName);
    JMethod m = $output.method(JMod.PRIVATE | JMod.STATIC, (JType) null, overloadResolved);
    Map<String, JTypeVar> typeVars = new HashMap<>();
    e.getTypeParameters().forEach(p -> {
        String name = n(p);
        JTypeVar typeVar = delegating.generify(name);
        JTypeVar typeVar2 = m.generify(name);
        p.getBounds().forEach(b -> {
            JClass binding = (JClass) t(b, typeVars);
            typeVar.bound(binding);
            typeVar2.bound(binding);
        });
        typeVars.put(name, typeVar);
    });
    JType type = t(e.getReturnType(), typeVars);
    delegating.type(type);
    m.type(type);
    List<JVar> delegatingParams = new ArrayList<>();
    List<JVar> params = new ArrayList<>();
    e.getParameters().forEach(p -> {
        JType paramType = t(p.asType(), typeVars);
        delegatingParams.add(e.isVarArgs() && p == e.getParameters().get(e.getParameters().size() - 1) ? delegating.varParam(paramType.elementType(), n(p)) : delegating.param(paramType, n(p)));
        params.add(m.param(paramType, n(p)));
    });
    e.getThrownTypes().forEach(ex -> {
        delegating._throws((JClass) t(ex));
        m._throws((JClass) t(ex));
    });
    boolean returnsVoid = e.getReturnType().getKind() == TypeKind.VOID;
    if (isPublic) {
        // preamble
        /*
                If the call to this method happen outside CPS code, execute normally via DefaultGroovyMethods
             */
        delegating.body()._if(JOp.cand(JOp.not($Caller.staticInvoke("isAsynchronous").tap(inv -> {
            inv.arg(delegatingParams.get(0));
            inv.arg(methodName);
            for (int i = 1; i < delegatingParams.size(); i++) inv.arg(delegatingParams.get(i));
        })), JOp.not($Caller.staticInvoke("isAsynchronous").arg($output.dotclass()).arg(methodName).args(params))))._then().tap(blk -> {
            JClass $WhateverGroovyMethods = codeModel.ref(fqcn);
            JInvocation forward = $WhateverGroovyMethods.staticInvoke(methodName).args(delegatingParams);
            if (returnsVoid) {
                blk.add(forward);
                blk._return();
            } else {
                blk._return(forward);
            }
        });
    }
    JInvocation delegateCall = $output.staticInvoke(overloadResolved);
    if (returnsVoid) {
        delegating.body().add(delegateCall);
    } else {
        delegating.body()._return(delegateCall);
    }
    delegatingParams.forEach(p -> delegateCall.arg(p));
    JVar $b = m.body().decl($Builder, "b", JExpr._new($Builder).arg(JExpr.invoke("loc").arg(methodName)).invoke("contextualize").arg(codeModel.ref("com.cloudbees.groovy.cps.sandbox.Trusted").staticRef("INSTANCE")));
    JInvocation f = JExpr._new($CpsFunction);
    // parameter names
    f.arg(codeModel.ref(Arrays.class).staticInvoke("asList").tap(inv -> {
        e.getParameters().forEach(p -> inv.arg(n(p)));
    }));
    // translate the method body into an expression that invokes Builder
    f.arg(trees.getTree(e).getBody().accept(new SimpleTreeVisitor<JExpression, Void>() {

        private JExpression visit(Tree t) {
            if (t == null)
                return JExpr._null();
            return visit(t, null);
        }

        /**
         * Maps a symbol to its source location.
         */
        private JExpression loc(Tree t) {
            long pos = trees.getSourcePositions().getStartPosition(cut, t);
            return JExpr.lit((int) cut.getLineMap().getLineNumber(pos));
        }

        @Override
        public JExpression visitWhileLoop(WhileLoopTree wt, Void __) {
            return $b.invoke("while_").arg(// TODO: label
            JExpr._null()).arg(visit(wt.getCondition())).arg(visit(wt.getStatement()));
        }

        @Override
        public JExpression visitMethodInvocation(MethodInvocationTree mt, Void __) {
            ExpressionTree ms = mt.getMethodSelect();
            JInvocation inv;
            if (ms instanceof MemberSelectTree) {
                MemberSelectTree mst = (MemberSelectTree) ms;
                // of the other known translated classes.
                if (mst.getExpression() instanceof JCIdent && !((JCIdent) mst.getExpression()).sym.toString().equals(fqcn) && otherTranslated.containsKey(((JCIdent) mst.getExpression()).sym.toString())) {
                    inv = $b.invoke("functionCall").arg(loc(mt)).arg($b.invoke("constant").arg(otherTranslated.get(((JCIdent) mst.getExpression()).sym.toString()).dotclass())).arg(n(mst.getIdentifier()));
                } else {
                    inv = $b.invoke("functionCall").arg(loc(mt)).arg(visit(mst.getExpression())).arg(n(mst.getIdentifier()));
                }
            } else if (ms instanceof JCIdent) {
                // invocation without object selection, like  foo(bar,zot)
                JCIdent it = (JCIdent) ms;
                if (!it.sym.owner.toString().equals(fqcn)) {
                    if (otherTranslated.containsKey(it.sym.owner.toString())) {
                        // static import from transformed class
                        inv = $b.invoke("functionCall").arg(loc(mt)).arg($b.invoke("constant").arg(otherTranslated.get(it.sym.owner.toString()).dotclass())).arg(n(it));
                    } else {
                        // static import from non-transformed class
                        inv = $b.invoke("functionCall").arg(loc(mt)).arg($b.invoke("constant").arg(t(it.sym.owner.type).dotclass())).arg(n(it));
                    }
                } else {
                    // invocation on this class
                    String overloadResolved = mangledName((Symbol.MethodSymbol) it.sym);
                    Optional<? extends Element> callSite = elements.getTypeElement(fqcn).getEnclosedElements().stream().filter(e -> e.getKind() == ElementKind.METHOD && mangledName((ExecutableElement) e).equals(overloadResolved)).findAny();
                    if (callSite.isPresent()) {
                        ExecutableElement e = (ExecutableElement) callSite.get();
                        if (e.getModifiers().contains(Modifier.PUBLIC) && !e.isVarArgs() && !e.getParameters().stream().anyMatch(p -> types.isAssignable(p.asType(), closureType))) {
                            // Delegate to the standard version.
                            inv = $b.invoke("staticCall").arg(loc(mt)).arg(t(it.sym.owner.type).dotclass()).arg(n(e));
                        } else if (overloadsResolved.containsKey(overloadResolved)) {
                            // Private, so delegate to our mangled version.
                            // TODO add a String parameter to each internal helper method for the expected methodName to pass to CpsCallableInvocation.<init>
                            // (It could be improved to take a parameter for the name under which we expect methodCall to be invoking it.
                            // Usually just `each`, but might be `$each__java_util_Iterable__groovy_lang_Closure` for the case that one DGM method is delegating to another.
                            // See comment in ContinuationGroup, where we are unable to enforce continuation name mismatches in this case.)
                            inv = $b.invoke("staticCall").arg(loc(mt)).arg($output.dotclass()).arg(overloadResolved);
                        } else {
                            throw new IllegalStateException("Not yet translating a " + e.getModifiers() + " method; translatable.txt might need to include: " + fqcn + "." + e);
                        }
                    } else {
                        throw new IllegalStateException("Could not find self-call site " + overloadResolved + " for " + mt);
                    }
                }
            } else {
                // TODO: figure out what can come here
                throw new UnsupportedOperationException(ms.toString());
            }
            mt.getArguments().forEach(a -> inv.arg(visit(a)));
            return inv;
        }

        @Override
        public JExpression visitVariable(VariableTree vt, Void __) {
            return $b.invoke("declareVariable").arg(loc(vt)).arg(cpsTypeTranslation(erasure(vt))).arg(n(vt)).arg(visit(vt.getInitializer()));
        }

        @Override
        public JExpression visitIdentifier(IdentifierTree it, Void __) {
            JCIdent idt = (JCIdent) it;
            return idt.sym.accept(new DefaultSymbolVisitor<JExpression, Void>() {

                @Override
                public JExpression visitClassSymbol(ClassSymbol cs, Void __) {
                    return $b.invoke("constant").arg(t(cs.asType()).dotclass());
                }

                @Override
                public JExpression visitVarSymbol(VarSymbol s, Void __) {
                    return $b.invoke("localVariable").arg(n(s.name));
                }

                @Override
                public JExpression visitSymbol(Symbol s, Void __) {
                    throw new UnsupportedOperationException(s.toString());
                }
            }, __);
        }

        @Override
        public JExpression visitBlock(BlockTree bt, Void __) {
            JInvocation inv = $b.invoke("block");
            bt.getStatements().forEach(s -> inv.arg(visit(s)));
            return inv;
        }

        @Override
        public JExpression visitReturn(ReturnTree rt, Void __) {
            return $b.invoke("return_").arg(visit(rt.getExpression()));
        }

        /**
         * When used outside {@link MethodInvocationTree}, this is property access.
         */
        @Override
        public JExpression visitMemberSelect(MemberSelectTree mt, Void __) {
            return $b.invoke("property").arg(loc(mt)).arg(visit(mt.getExpression())).arg(n(mt.getIdentifier()));
        }

        @Override
        public JExpression visitTypeCast(TypeCastTree tt, Void __) {
            return $b.invoke("cast").arg(loc(tt)).arg(visit(tt.getExpression())).arg(erasure(tt.getType()).dotclass()).arg(JExpr.lit(false));
        }

        @Override
        public JExpression visitIf(IfTree it, Void __) {
            JInvocation inv = $b.invoke("if_").arg(visit(it.getCondition())).arg(visit(it.getThenStatement()));
            if (it.getElseStatement() != null)
                inv.arg(visit(it.getElseStatement()));
            return inv;
        }

        @Override
        public JExpression visitNewClass(NewClassTree nt, Void __) {
            // TODO: outer class
            if (nt.getEnclosingExpression() != null)
                throw new UnsupportedOperationException();
            return $b.invoke("new_").tap(inv -> {
                inv.arg(loc(nt));
                inv.arg(cpsTypeTranslation(t(((JCTree) nt).type)));
                nt.getArguments().forEach(et -> inv.arg(visit(et)));
            });
        }

        @Override
        public JExpression visitExpressionStatement(ExpressionStatementTree et, Void __) {
            return visit(et.getExpression());
        }

        @Override
        public JExpression visitLiteral(LiteralTree lt, Void __) {
            return $b.invoke("constant").arg(JExpr.literal(lt.getValue()));
        }

        @Override
        public JExpression visitParenthesized(ParenthesizedTree pt, Void __) {
            return visit(pt.getExpression());
        }

        @Override
        public JExpression visitBinary(BinaryTree bt, Void __) {
            return $b.invoke(opName(bt.getKind())).arg(loc(bt)).arg(visit(bt.getLeftOperand())).arg(visit(bt.getRightOperand()));
        }

        @Override
        public JExpression visitUnary(UnaryTree ut, Void __) {
            return $b.invoke(opName(ut.getKind())).arg(loc(ut)).arg(visit(ut.getExpression()));
        }

        @Override
        public JExpression visitCompoundAssignment(CompoundAssignmentTree ct, Void __) {
            return $b.invoke(opName(ct.getKind())).arg(loc(ct)).arg(visit(ct.getVariable())).arg(visit(ct.getExpression()));
        }

        private String opName(Kind kind) {
            switch(kind) {
                case EQUAL_TO:
                    return "compareEqual";
                case NOT_EQUAL_TO:
                    return "compareNotEqual";
                case LESS_THAN_EQUAL:
                    return "lessThanEqual";
                case LESS_THAN:
                    return "lessThan";
                case GREATER_THAN_EQUAL:
                    return "greaterThanEqual";
                case GREATER_THAN:
                    return "greaterThan";
                case PREFIX_INCREMENT:
                    return "prefixInc";
                case POSTFIX_INCREMENT:
                    return "postfixInc";
                case POSTFIX_DECREMENT:
                    return "postfixDec";
                case LOGICAL_COMPLEMENT:
                    return "not";
                case CONDITIONAL_OR:
                    return "logicalOr";
                case CONDITIONAL_AND:
                    return "logicalAnd";
                case PLUS:
                    return "plus";
                case PLUS_ASSIGNMENT:
                    return "plusEqual";
                case MINUS:
                    return "minus";
                case MINUS_ASSIGNMENT:
                    return "minusEqual";
            }
            throw new UnsupportedOperationException(kind.toString());
        }

        @Override
        public JExpression visitAssignment(AssignmentTree at, Void __) {
            return $b.invoke("assign").arg(loc(at)).arg(visit(at.getVariable())).arg(visit(at.getExpression()));
        }

        /**
         * This is needed to handle cases like {@code Object[].class}.
         */
        @Override
        public JExpression visitArrayType(ArrayTypeTree at, Void __) {
            if (at.getType() instanceof IdentifierTree) {
                return visitIdentifier((IdentifierTree) at.getType(), __);
            } else {
                return defaultAction(at, __);
            }
        }

        @Override
        public JExpression visitNewArray(NewArrayTree nt, Void __) {
            if (nt.getInitializers() != null) {
                return $b.invoke("newArrayFromInitializers").tap(inv -> {
                    nt.getInitializers().forEach(d -> inv.arg(visit(d)));
                });
            } else {
                return $b.invoke("newArray").tap(inv -> {
                    inv.arg(loc(nt));
                    inv.arg(t(nt.getType()).dotclass());
                    nt.getDimensions().forEach(d -> inv.arg(visit(d)));
                });
            }
        }

        @Override
        public JExpression visitForLoop(ForLoopTree ft, Void __) {
            return $b.invoke("forLoop").arg(JExpr._null()).arg($b.invoke("sequence").tap(inv -> ft.getInitializer().forEach(i -> inv.arg(visit(i))))).arg(visit(ft.getCondition())).arg($b.invoke("sequence").tap(inv -> ft.getUpdate().forEach(i -> inv.arg(visit(i))))).arg(visit(ft.getStatement()));
        }

        @Override
        public JExpression visitEnhancedForLoop(EnhancedForLoopTree et, Void __) {
            return $b.invoke("forInLoop").arg(loc(et)).arg(JExpr._null()).arg(erasure(et.getVariable()).dotclass()).arg(n(et.getVariable())).arg(visit(et.getExpression())).arg(visit(et.getStatement()));
        }

        @Override
        public JExpression visitArrayAccess(ArrayAccessTree at, Void __) {
            return $b.invoke("array").arg(loc(at)).arg(visit(at.getExpression())).arg(visit(at.getIndex()));
        }

        @Override
        public JExpression visitBreak(BreakTree node, Void __) {
            if (node.getLabel() != null)
                throw new UnsupportedOperationException();
            return $b.invoke("break_").arg(JExpr._null());
        }

        @Override
        public JExpression visitContinue(ContinueTree node, Void aVoid) {
            if (node.getLabel() != null)
                throw new UnsupportedOperationException();
            return $b.invoke("continue_").arg(JExpr._null());
        }

        @Override
        public JExpression visitInstanceOf(InstanceOfTree it, Void __) {
            return $b.invoke("instanceOf").arg(loc(it)).arg(visit(it.getExpression())).arg($b.invoke("constant").arg(t(it.getType()).dotclass()));
        }

        @Override
        public JExpression visitThrow(ThrowTree tt, Void __) {
            return $b.invoke("throw_").arg(loc(tt)).arg(visit(tt.getExpression()));
        }

        @Override
        public JExpression visitDoWhileLoop(DoWhileLoopTree dt, Void __) {
            return $b.invoke("doWhile").arg(JExpr._null()).arg(visit(dt.getStatement())).arg(visit(dt.getCondition()));
        }

        @Override
        public JExpression visitConditionalExpression(ConditionalExpressionTree ct, Void __) {
            return $b.invoke("ternaryOp").arg(visit(ct.getCondition())).arg(visit(ct.getTrueExpression())).arg(visit(ct.getFalseExpression()));
        }

        @Override
        public JExpression visitTry(TryTree tt, Void __) {
            return $b.invoke("tryCatch").arg(visit(tt.getBlock())).arg(visit(tt.getFinallyBlock())).tap(inv -> tt.getCatches().forEach(ct -> JExpr._new($CatchExpression).arg(t(ct.getParameter()).dotclass()).arg(n(ct.getParameter())).arg(visit(ct.getBlock()))));
        }

        @Override
        protected JExpression defaultAction(Tree node, Void aVoid) {
            throw new UnsupportedOperationException(node.toString());
        }
    }, null));
    JVar $f = m.body().decl($CpsFunction, "f", f);
    m.body()._throw(JExpr._new($CpsCallableInvocation).arg(JExpr.lit(methodName)).arg($f).arg(JExpr._null()).args(params));
}
Also used : CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) Arrays(java.util.Arrays) LiteralTree(com.sun.source.tree.LiteralTree) JCodeModel(com.sun.codemodel.JCodeModel) Modifier(javax.lang.model.element.Modifier) Closure(groovy.lang.Closure) TypeElement(javax.lang.model.element.TypeElement) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Elements(javax.lang.model.util.Elements) JExpr(com.sun.codemodel.JExpr) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) Map(java.util.Map) ForLoopTree(com.sun.source.tree.ForLoopTree) Trees(com.sun.source.util.Trees) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ParenthesizedTree(com.sun.source.tree.ParenthesizedTree) ArrayType(javax.lang.model.type.ArrayType) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) DefaultSymbolVisitor(com.sun.tools.javac.code.Types.DefaultSymbolVisitor) Symbol(com.sun.tools.javac.code.Symbol) Set(java.util.Set) Element(javax.lang.model.element.Element) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) StandardCharsets(java.nio.charset.StandardCharsets) ThrowTree(com.sun.source.tree.ThrowTree) BlockTree(com.sun.source.tree.BlockTree) JCIdent(com.sun.tools.javac.tree.JCTree.JCIdent) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) UnaryTree(com.sun.source.tree.UnaryTree) JInvocation(com.sun.codemodel.JInvocation) VariableTree(com.sun.source.tree.VariableTree) ArrayList(java.util.ArrayList) Kind(com.sun.source.tree.Tree.Kind) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) DeclaredType(javax.lang.model.type.DeclaredType) BreakTree(com.sun.source.tree.BreakTree) Tree(com.sun.source.tree.Tree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) JClassAlreadyExistsException(com.sun.codemodel.JClassAlreadyExistsException) Resources(com.google.common.io.Resources) JDefinedClass(com.sun.codemodel.JDefinedClass) ExpressionTree(com.sun.source.tree.ExpressionTree) IOException(java.io.IOException) TreeMap(java.util.TreeMap) WildcardTree(com.sun.source.tree.WildcardTree) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) JVar(com.sun.codemodel.JVar) SimpleTypeVisitor6(javax.lang.model.util.SimpleTypeVisitor6) Date(java.util.Date) JMethod(com.sun.codemodel.JMethod) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) JExpression(com.sun.codemodel.JExpression) Generated(javax.annotation.Generated) CompilationTask(javax.tools.JavaCompiler.CompilationTask) IdentifierTree(com.sun.source.tree.IdentifierTree) NewArrayTree(com.sun.source.tree.NewArrayTree) WildcardType(javax.lang.model.type.WildcardType) JMod(com.sun.codemodel.JMod) JOp(com.sun.codemodel.JOp) JavacTask(com.sun.source.util.JavacTask) ContinueTree(com.sun.source.tree.ContinueTree) SimpleTreeVisitor(com.sun.source.util.SimpleTreeVisitor) Types(javax.lang.model.util.Types) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) TypeKind(javax.lang.model.type.TypeKind) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) List(java.util.List) ElementScanner7(javax.lang.model.util.ElementScanner7) JType(com.sun.codemodel.JType) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) TypeVariable(javax.lang.model.type.TypeVariable) Optional(java.util.Optional) WhileLoopTree(com.sun.source.tree.WhileLoopTree) BinaryTree(com.sun.source.tree.BinaryTree) HashMap(java.util.HashMap) JTypeVar(com.sun.codemodel.JTypeVar) HashSet(java.util.HashSet) CodeWriter(com.sun.codemodel.CodeWriter) ClassTree(com.sun.source.tree.ClassTree) Name(javax.lang.model.element.Name) IfTree(com.sun.source.tree.IfTree) ElementKind(javax.lang.model.element.ElementKind) NoType(javax.lang.model.type.NoType) ExecutableElement(javax.lang.model.element.ExecutableElement) JCTree(com.sun.tools.javac.tree.JCTree) TypeMirror(javax.lang.model.type.TypeMirror) DoWhileLoopTree(com.sun.source.tree.DoWhileLoopTree) TryTree(com.sun.source.tree.TryTree) PrimitiveType(javax.lang.model.type.PrimitiveType) JClass(com.sun.codemodel.JClass) Collections(java.util.Collections) TypeCastTree(com.sun.source.tree.TypeCastTree) HashMap(java.util.HashMap) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ArrayList(java.util.ArrayList) BinaryTree(com.sun.source.tree.BinaryTree) IdentifierTree(com.sun.source.tree.IdentifierTree) ReturnTree(com.sun.source.tree.ReturnTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) JTypeVar(com.sun.codemodel.JTypeVar) Kind(com.sun.source.tree.Tree.Kind) TypeKind(javax.lang.model.type.TypeKind) ElementKind(javax.lang.model.element.ElementKind) ThrowTree(com.sun.source.tree.ThrowTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) LiteralTree(com.sun.source.tree.LiteralTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) ForLoopTree(com.sun.source.tree.ForLoopTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ParenthesizedTree(com.sun.source.tree.ParenthesizedTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) ThrowTree(com.sun.source.tree.ThrowTree) BlockTree(com.sun.source.tree.BlockTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) BreakTree(com.sun.source.tree.BreakTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) WildcardTree(com.sun.source.tree.WildcardTree) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) IdentifierTree(com.sun.source.tree.IdentifierTree) NewArrayTree(com.sun.source.tree.NewArrayTree) ContinueTree(com.sun.source.tree.ContinueTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) WhileLoopTree(com.sun.source.tree.WhileLoopTree) BinaryTree(com.sun.source.tree.BinaryTree) ClassTree(com.sun.source.tree.ClassTree) IfTree(com.sun.source.tree.IfTree) JCTree(com.sun.tools.javac.tree.JCTree) DoWhileLoopTree(com.sun.source.tree.DoWhileLoopTree) TryTree(com.sun.source.tree.TryTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) AssignmentTree(com.sun.source.tree.AssignmentTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) JType(com.sun.codemodel.JType) DoWhileLoopTree(com.sun.source.tree.DoWhileLoopTree) JCIdent(com.sun.tools.javac.tree.JCTree.JCIdent) Optional(java.util.Optional) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) IfTree(com.sun.source.tree.IfTree) Arrays(java.util.Arrays) TryTree(com.sun.source.tree.TryTree) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Symbol(com.sun.tools.javac.code.Symbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) TypeVariableSymbol(com.sun.tools.javac.code.Symbol.TypeVariableSymbol) TypeElement(javax.lang.model.element.TypeElement) Element(javax.lang.model.element.Element) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) VariableTree(com.sun.source.tree.VariableTree) ParenthesizedTree(com.sun.source.tree.ParenthesizedTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) NewClassTree(com.sun.source.tree.NewClassTree) BreakTree(com.sun.source.tree.BreakTree) LiteralTree(com.sun.source.tree.LiteralTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) BlockTree(com.sun.source.tree.BlockTree) ContinueTree(com.sun.source.tree.ContinueTree) UnaryTree(com.sun.source.tree.UnaryTree) JVar(com.sun.codemodel.JVar) SimpleTreeVisitor(com.sun.source.util.SimpleTreeVisitor) JClass(com.sun.codemodel.JClass) ForLoopTree(com.sun.source.tree.ForLoopTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) JInvocation(com.sun.codemodel.JInvocation) JExpression(com.sun.codemodel.JExpression) NewArrayTree(com.sun.source.tree.NewArrayTree) WhileLoopTree(com.sun.source.tree.WhileLoopTree) DoWhileLoopTree(com.sun.source.tree.DoWhileLoopTree) JMethod(com.sun.codemodel.JMethod)

Example 4 with TryTree

use of com.sun.source.tree.TryTree in project j2objc by google.

the class TreeConverter method convertTry.

private TreeNode convertTry(TryTree node, TreePath parent) {
    TreePath path = getTreePath(parent, node);
    TryStatement newNode = new TryStatement();
    for (Tree obj : node.getResources()) {
        if (obj.getKind() == Kind.VARIABLE) {
            newNode.addResource(convertVariableExpression((VariableTree) obj, path));
        } else {
            newNode.addResource(convertInner(obj, path));
        }
    }
    for (CatchTree obj : node.getCatches()) {
        newNode.addCatchClause((CatchClause) convert(obj, path));
    }
    return newNode.setBody((Block) convert(node.getBlock(), path)).setFinally((Block) convert(node.getFinallyBlock(), path));
}
Also used : TreePath(com.sun.source.util.TreePath) TryStatement(com.google.devtools.j2objc.ast.TryStatement) CatchTree(com.sun.source.tree.CatchTree) VariableTree(com.sun.source.tree.VariableTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) LiteralTree(com.sun.source.tree.LiteralTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) TypeCastTree(com.sun.source.tree.TypeCastTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) ForLoopTree(com.sun.source.tree.ForLoopTree) InstanceOfTree(com.sun.source.tree.InstanceOfTree) ParenthesizedTree(com.sun.source.tree.ParenthesizedTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) ThrowTree(com.sun.source.tree.ThrowTree) BlockTree(com.sun.source.tree.BlockTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) ReturnTree(com.sun.source.tree.ReturnTree) ArrayTypeTree(com.sun.source.tree.ArrayTypeTree) LabeledStatementTree(com.sun.source.tree.LabeledStatementTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) ParameterizedTypeTree(com.sun.source.tree.ParameterizedTypeTree) BreakTree(com.sun.source.tree.BreakTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) NewArrayTree(com.sun.source.tree.NewArrayTree) ContinueTree(com.sun.source.tree.ContinueTree) CaseTree(com.sun.source.tree.CaseTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) SwitchTree(com.sun.source.tree.SwitchTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) SynchronizedTree(com.sun.source.tree.SynchronizedTree) AssertTree(com.sun.source.tree.AssertTree) StatementTree(com.sun.source.tree.StatementTree) ModifiersTree(com.sun.source.tree.ModifiersTree) WhileLoopTree(com.sun.source.tree.WhileLoopTree) AnnotationTree(com.sun.source.tree.AnnotationTree) MethodTree(com.sun.source.tree.MethodTree) BinaryTree(com.sun.source.tree.BinaryTree) ClassTree(com.sun.source.tree.ClassTree) IfTree(com.sun.source.tree.IfTree) MemberReferenceTree(com.sun.source.tree.MemberReferenceTree) JCTree(com.sun.tools.javac.tree.JCTree) DoWhileLoopTree(com.sun.source.tree.DoWhileLoopTree) TryTree(com.sun.source.tree.TryTree) Block(com.google.devtools.j2objc.ast.Block)

Example 5 with TryTree

use of com.sun.source.tree.TryTree in project error-prone by google.

the class ClassNewInstance method fixExceptions.

// if the match occurrs inside the body of a try statement with existing catch clauses
// update or add a catch block to handle the new exceptions
private boolean fixExceptions(final VisitorState state, SuggestedFix.Builder fix) {
    TryTree tryTree = null;
    OUTER: for (TreePath path = state.getPath(); path != null; path = path.getParentPath()) {
        if (path.getLeaf() instanceof CatchTree) {
            // don't add more catch blocks if newInstance() was called in a catch block
            return false;
        } else if (path.getLeaf() instanceof TryTree && !((TryTree) path.getLeaf()).getCatches().isEmpty()) {
            tryTree = (TryTree) path.getLeaf();
            break;
        }
    }
    if (tryTree == null) {
        return false;
    }
    ImmutableMap.Builder<Type, CatchTree> catches = ImmutableMap.builder();
    for (CatchTree c : tryTree.getCatches()) {
        catches.put(ASTHelpers.getType(c.getParameter().getType()), c);
    }
    UnhandledResult<CatchTree> result = unhandled(catches.build(), state);
    if (result.unhandled.isEmpty()) {
        // no fix needed
        return true;
    }
    {
        // if there's an existing multi-catch at the end that handles reflective exceptions,
        // replace all of them with ROE and leave any non-reflective exceptions.
        // earlier catch blocks are left unchanged.
        CatchTree last = Iterables.getLast(tryTree.getCatches());
        Tree lastType = last.getParameter().getType();
        if (lastType.getKind() == Tree.Kind.UNION_TYPE) {
            Type roe = state.getTypeFromString(ReflectiveOperationException.class.getName());
            Set<String> exceptions = new LinkedHashSet<>();
            boolean foundReflective = false;
            for (Tree alternate : ((UnionTypeTree) lastType).getTypeAlternatives()) {
                if (ASTHelpers.isSubtype(ASTHelpers.getType(alternate), roe, state)) {
                    foundReflective = true;
                    exceptions.add("ReflectiveOperationException");
                } else {
                    exceptions.add(state.getSourceForNode(alternate));
                }
            }
            if (foundReflective) {
                fix.replace(lastType, Joiner.on(" | ").join(exceptions));
                return true;
            }
        }
    }
    // check for duplicated catch blocks that handle reflective exceptions exactly the same way,
    // and merge them into a single block that catches ROE
    Set<String> uniq = new HashSet<>();
    for (CatchTree ct : result.handles.values()) {
        uniq.add(state.getSourceForNode(ct.getBlock()));
    }
    // the catch blocks are all unique, append a new fresh one
    if (uniq.size() != 1) {
        CatchTree last = Iterables.getLast(tryTree.getCatches());
        // borrow the variable name of the previous catch variable, in case the naive 'e' conflicts
        // with something in the current scope
        String name = last.getParameter().getName().toString();
        fix.postfixWith(last, String.format("catch (ReflectiveOperationException %s) {" + " throw new LinkageError(%s.getMessage(), %s); }", name, name, name));
        return true;
    }
    // if the catch blocks contain calls to newInstance, don't delete any of them to avoid
    // overlapping fixes
    final AtomicBoolean newInstanceInCatch = new AtomicBoolean(false);
    ((JCTree) result.handles.values().iterator().next()).accept(new TreeScanner() {

        @Override
        public void visitApply(JCTree.JCMethodInvocation tree) {
            if (NEW_INSTANCE.matches(tree, state)) {
                newInstanceInCatch.set(true);
            }
        }
    });
    if (newInstanceInCatch.get()) {
        fix.replace(Iterables.getLast(result.handles.values()).getParameter().getType(), "ReflectiveOperationException");
        return true;
    }
    // otherwise, merge the duplicated catch blocks into a single block that
    // handles ROE
    boolean first = true;
    for (CatchTree ct : result.handles.values()) {
        if (first) {
            fix.replace(ct.getParameter().getType(), "ReflectiveOperationException");
            first = false;
        } else {
            fix.delete(ct);
        }
    }
    return true;
}
Also used : HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) CatchTree(com.sun.source.tree.CatchTree) JCTree(com.sun.tools.javac.tree.JCTree) ImmutableMap(com.google.common.collect.ImmutableMap) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Type(com.sun.tools.javac.code.Type) TreePath(com.sun.source.util.TreePath) TreeScanner(com.sun.tools.javac.tree.TreeScanner) MethodTree(com.sun.source.tree.MethodTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) CatchTree(com.sun.source.tree.CatchTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) JCTree(com.sun.tools.javac.tree.JCTree) TryTree(com.sun.source.tree.TryTree) UnionTypeTree(com.sun.source.tree.UnionTypeTree) TryTree(com.sun.source.tree.TryTree) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Aggregations

Tree (com.sun.source.tree.Tree)12 TryTree (com.sun.source.tree.TryTree)12 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)11 CatchTree (com.sun.source.tree.CatchTree)9 BlockTree (com.sun.source.tree.BlockTree)8 ExpressionTree (com.sun.source.tree.ExpressionTree)8 StatementTree (com.sun.source.tree.StatementTree)8 ExpressionStatementTree (com.sun.source.tree.ExpressionStatementTree)6 MemberSelectTree (com.sun.source.tree.MemberSelectTree)6 MethodTree (com.sun.source.tree.MethodTree)6 VariableTree (com.sun.source.tree.VariableTree)6 ClassTree (com.sun.source.tree.ClassTree)5 IdentifierTree (com.sun.source.tree.IdentifierTree)5 AssignmentTree (com.sun.source.tree.AssignmentTree)4 CompilationUnitTree (com.sun.source.tree.CompilationUnitTree)4 EnhancedForLoopTree (com.sun.source.tree.EnhancedForLoopTree)4 ForLoopTree (com.sun.source.tree.ForLoopTree)4 IfTree (com.sun.source.tree.IfTree)4 NewClassTree (com.sun.source.tree.NewClassTree)4 WhileLoopTree (com.sun.source.tree.WhileLoopTree)4