Search in sources :

Example 1 with JCSwitch

use of com.sun.tools.javac.tree.JCTree.JCSwitch in project ceylon-compiler by ceylon.

the class AbstractTransformer method makeLazyIterable.

/**
     * Makes a lazy iterable literal, for a sequenced argument to a named invocation 
     * (<code>f{foo=""; expr1, expr2, *expr3}</code>) or
     * for an iterable instantiation (<code>{expr1, expr2, *expr3}</code>)
     */
JCExpression makeLazyIterable(Tree.SequencedArgument sequencedArgument, Type seqElemType, Type absentType, int flags) {
    java.util.List<PositionalArgument> list = sequencedArgument.getPositionalArguments();
    int i = 0;
    ListBuffer<JCStatement> returns = new ListBuffer<JCStatement>();
    boolean spread = false;
    boolean old = expressionGen().withinSyntheticClassBody(true);
    try {
        for (Tree.PositionalArgument arg : list) {
            at(arg);
            JCExpression jcExpression;
            // last expression can be an Iterable<seqElemType>
            if (arg instanceof Tree.SpreadArgument || arg instanceof Tree.Comprehension) {
                // make sure we only have spread/comprehension as last
                if (i != list.size() - 1) {
                    jcExpression = makeErroneous(arg, "compiler bug: spread or comprehension argument is not last in sequence literal");
                } else {
                    Type type = typeFact().getIterableType(seqElemType);
                    spread = true;
                    if (arg instanceof Tree.SpreadArgument) {
                        Tree.Expression expr = ((Tree.SpreadArgument) arg).getExpression();
                        // always boxed since it is a sequence
                        jcExpression = expressionGen().transformExpression(expr, BoxingStrategy.BOXED, type);
                    } else {
                        jcExpression = expressionGen().transformComprehension((Comprehension) arg, type);
                    }
                }
            } else if (arg instanceof Tree.ListedArgument) {
                Tree.Expression expr = ((Tree.ListedArgument) arg).getExpression();
                // always boxed since we stuff them into a sequence
                jcExpression = expressionGen().transformExpression(expr, BoxingStrategy.BOXED, seqElemType);
            } else {
                jcExpression = makeErroneous(arg, "compiler bug: " + arg.getNodeType() + " is not a supported sequenced argument");
            }
            at(arg);
            // the last iterable goes first if spread
            returns.add(make().Return(jcExpression));
            i++;
        }
        at(sequencedArgument);
        if (Strategy.preferLazySwitchingIterable(sequencedArgument.getPositionalArguments())) {
            // use a LazySwitchingIterable
            MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$evaluate$.toString());
            mdb.isOverride(true);
            mdb.modifiers(PROTECTED | FINAL);
            mdb.resultType(null, make().Type(syms().objectType));
            mdb.parameter(ParameterDefinitionBuilder.systemParameter(this, Unfix.$index$.toString()).type(make().Type(syms().intType), null));
            JCSwitch swtch;
            try (SavedPosition sp = noPosition()) {
                ListBuffer<JCCase> cases = ListBuffer.<JCCase>lb();
                i = 0;
                for (JCStatement e : returns) {
                    cases.add(make().Case(make().Literal(i++), List.<JCStatement>of(e)));
                }
                cases.add(make().Case(null, List.<JCStatement>of(make().Return(makeNull()))));
                swtch = make().Switch(naming.makeUnquotedIdent(Unfix.$index$), cases.toList());
            }
            mdb.body(swtch);
            return make().NewClass(null, //of(makeJavaType(seqElemType), makeJavaType(absentType)),
            List.<JCExpression>nil(), make().TypeApply(make().QualIdent(syms.ceylonLazyIterableType.tsym), List.<JCExpression>of(makeJavaType(seqElemType, JT_TYPE_ARGUMENT), makeJavaType(absentType, JT_TYPE_ARGUMENT))), // td, 
            List.of(// td, 
            makeReifiedTypeArgument(seqElemType), //td
            makeReifiedTypeArgument(absentType), // numMethods
            make().Literal(list.size()), // spread), 
            make().Literal(spread)), make().AnonymousClassDef(make().Modifiers(FINAL), List.<JCTree>of(mdb.build())));
        } else {
            // use a LazyInvokingIterable
            ListBuffer<JCTree> methods = new ListBuffer<JCTree>();
            MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$lookup$.toString());
            mdb.isOverride(true);
            mdb.modifiers(PROTECTED | FINAL);
            mdb.resultType(null, naming.makeQualIdent(make().Type(syms().methodHandlesType), "Lookup"));
            mdb.body(make().Return(make().Apply(List.<JCExpression>nil(), naming.makeQualIdent(make().Type(syms().methodHandlesType), "lookup"), List.<JCExpression>nil())));
            methods.add(mdb.build());
            mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$invoke$.toString());
            mdb.isOverride(true);
            mdb.modifiers(PROTECTED | FINAL);
            mdb.resultType(null, make().Type(syms().objectType));
            mdb.parameter(ParameterDefinitionBuilder.systemParameter(this, "handle").type(make().Type(syms().methodHandleType), null));
            mdb.body(make().Return(make().Apply(List.<JCExpression>nil(), naming.makeQualIdent(naming.makeUnquotedIdent("handle"), "invokeExact"), List.<JCExpression>of(naming.makeThis()))));
            methods.add(mdb.build());
            i = 0;
            for (JCStatement expr : returns) {
                mdb = MethodDefinitionBuilder.systemMethod(this, "$" + i);
                i++;
                mdb.modifiers(PRIVATE | FINAL);
                mdb.resultType(null, make().Type(syms().objectType));
                mdb.body(expr);
                methods.add(mdb.build());
            }
            return make().NewClass(null, //of(makeJavaType(seqElemType), makeJavaType(absentType)),
            List.<JCExpression>nil(), make().TypeApply(make().QualIdent(syms.ceylonLazyInvokingIterableType.tsym), List.<JCExpression>of(makeJavaType(seqElemType, JT_TYPE_ARGUMENT), makeJavaType(absentType, JT_TYPE_ARGUMENT))), // td, 
            List.of(// td, 
            makeReifiedTypeArgument(seqElemType), //td
            makeReifiedTypeArgument(absentType), // numMethods
            make().Literal(list.size()), // spread), 
            make().Literal(spread)), make().AnonymousClassDef(make().Modifiers(FINAL), methods.toList()));
        }
    } finally {
        expressionGen().withinSyntheticClassBody(old);
    }
}
Also used : ListBuffer(com.sun.tools.javac.util.ListBuffer) PositionalArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCCase(com.sun.tools.javac.tree.JCTree.JCCase) JCTree(com.sun.tools.javac.tree.JCTree) Comprehension(com.redhat.ceylon.compiler.typechecker.tree.Tree.Comprehension) Type(com.redhat.ceylon.model.typechecker.model.Type) ModelUtil.appliedType(com.redhat.ceylon.model.typechecker.model.ModelUtil.appliedType) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) Comprehension(com.redhat.ceylon.compiler.typechecker.tree.Tree.Comprehension) PositionalArgument(com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument)

Example 2 with JCSwitch

use of com.sun.tools.javac.tree.JCTree.JCSwitch in project error-prone by google.

the class UnnecessaryDefaultInEnumSwitch method matchSwitch.

@Override
public Description matchSwitch(SwitchTree tree, VisitorState state) {
    TypeSymbol switchType = ((JCSwitch) tree).getExpression().type.tsym;
    if (switchType.getKind() != ElementKind.ENUM) {
        return NO_MATCH;
    }
    Optional<? extends CaseTree> maybeDefaultCase = tree.getCases().stream().filter(c -> c.getExpression() == null).findFirst();
    if (!maybeDefaultCase.isPresent()) {
        return NO_MATCH;
    }
    CaseTree defaultCase = maybeDefaultCase.get();
    Set<String> handledCases = tree.getCases().stream().map(CaseTree::getExpression).filter(IdentifierTree.class::isInstance).map(p -> ((IdentifierTree) p).getName().toString()).collect(toImmutableSet());
    if (!ASTHelpers.enumValues(switchType).equals(handledCases)) {
        return NO_MATCH;
    }
    Fix fix;
    List<? extends StatementTree> defaultStatements = defaultCase.getStatements();
    if (trivialDefault(defaultStatements)) {
        // deleting `default:` or `default: break;` is a no-op
        fix = SuggestedFix.delete(defaultCase);
    } else if (!canCompleteNormally(tree)) {
        // if the switch statement cannot complete normally, then deleting the default
        // and moving its statements to after the switch statement is a no-op
        String defaultSource = state.getSourceCode().subSequence(((JCTree) defaultStatements.get(0)).getStartPosition(), state.getEndPosition(getLast(defaultStatements))).toString();
        fix = SuggestedFix.builder().delete(defaultCase).postfixWith(tree, defaultSource).build();
    } else {
        return NO_MATCH;
    }
    return describeMatch(defaultCase, fix);
}
Also used : SwitchTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.SwitchTreeMatcher) VisitorState(com.google.errorprone.VisitorState) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) IdentifierTree(com.sun.source.tree.IdentifierTree) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) Fix(com.google.errorprone.fixes.Fix) Tree(com.sun.source.tree.Tree) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) ElementKind(javax.lang.model.element.ElementKind) Set(java.util.Set) Iterables.getLast(com.google.common.collect.Iterables.getLast) Iterables.getOnlyElement(com.google.common.collect.Iterables.getOnlyElement) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) CaseTree(com.sun.source.tree.CaseTree) JCTree(com.sun.tools.javac.tree.JCTree) SwitchTree(com.sun.source.tree.SwitchTree) List(java.util.List) Description(com.google.errorprone.matchers.Description) StatementTree(com.sun.source.tree.StatementTree) Optional(java.util.Optional) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Reachability.canCompleteNormally(com.google.errorprone.util.Reachability.canCompleteNormally) ASTHelpers(com.google.errorprone.util.ASTHelpers) CaseTree(com.sun.source.tree.CaseTree) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) Fix(com.google.errorprone.fixes.Fix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) IdentifierTree(com.sun.source.tree.IdentifierTree) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol)

Example 3 with JCSwitch

use of com.sun.tools.javac.tree.JCTree.JCSwitch in project ceylon-compiler by ceylon.

the class JavaPositionsRetriever method getJavaSourceCodeWithCeylonPositions.

public String getJavaSourceCodeWithCeylonPositions() {
    final CharArrayWriter writer = new CharArrayWriter();
    Pretty printer = new Pretty(writer, true) {

        int previousCeylonPosition = -1;

        int previousPositionInString = 0;

        private void outputCeylonPosition(JCTree tree) {
            try {
                int currentCeylonPosition = tree.getPreferredPosition();
                int currentPositionInString = writer.size();
                if (previousCeylonPosition != currentCeylonPosition || previousPositionInString != currentPositionInString) {
                    if (currentCeylonPosition != -1 && currentCeylonPosition != 0) {
                        writer.write("/* " + formatCeylonPosition(currentCeylonPosition) + " */");
                    }
                    previousCeylonPosition = currentCeylonPosition;
                    previousPositionInString = writer.size();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void visitTopLevel(JCCompilationUnit tree) {
            outputCeylonPosition(tree);
            super.visitTopLevel(tree);
        }

        @Override
        public void visitImport(JCImport tree) {
            outputCeylonPosition(tree);
            super.visitImport(tree);
        }

        @Override
        public void visitClassDef(JCClassDecl tree) {
            outputCeylonPosition(tree);
            super.visitClassDef(tree);
        }

        @Override
        public void visitMethodDef(JCMethodDecl tree) {
            outputCeylonPosition(tree);
            super.visitMethodDef(tree);
        }

        @Override
        public void visitVarDef(JCVariableDecl tree) {
            outputCeylonPosition(tree);
            super.visitVarDef(tree);
        }

        @Override
        public void visitSkip(JCSkip tree) {
            outputCeylonPosition(tree);
            super.visitSkip(tree);
        }

        @Override
        public void visitBlock(JCBlock tree) {
            outputCeylonPosition(tree);
            super.visitBlock(tree);
            tree.endpos = currentPosition - 1;
        }

        @Override
        public void visitDoLoop(JCDoWhileLoop tree) {
            outputCeylonPosition(tree);
            super.visitDoLoop(tree);
        }

        @Override
        public void visitWhileLoop(JCWhileLoop tree) {
            outputCeylonPosition(tree);
            super.visitWhileLoop(tree);
        }

        @Override
        public void visitForLoop(JCForLoop tree) {
            outputCeylonPosition(tree);
            super.visitForLoop(tree);
        }

        @Override
        public void visitForeachLoop(JCEnhancedForLoop tree) {
            outputCeylonPosition(tree);
            super.visitForeachLoop(tree);
        }

        @Override
        public void visitLabelled(JCLabeledStatement tree) {
            outputCeylonPosition(tree);
            super.visitLabelled(tree);
        }

        @Override
        public void visitSwitch(JCSwitch tree) {
            outputCeylonPosition(tree);
            super.visitSwitch(tree);
        }

        @Override
        public void visitCase(JCCase tree) {
            outputCeylonPosition(tree);
            super.visitCase(tree);
        }

        @Override
        public void visitSynchronized(JCSynchronized tree) {
            outputCeylonPosition(tree);
            super.visitSynchronized(tree);
        }

        @Override
        public void visitTry(JCTry tree) {
            outputCeylonPosition(tree);
            super.visitTry(tree);
        }

        @Override
        public void visitCatch(JCCatch tree) {
            outputCeylonPosition(tree);
            super.visitCatch(tree);
        }

        @Override
        public void visitConditional(JCConditional tree) {
            outputCeylonPosition(tree);
            super.visitConditional(tree);
        }

        @Override
        public void visitIf(JCIf tree) {
            outputCeylonPosition(tree);
            super.visitIf(tree);
        }

        @Override
        public void visitExec(JCExpressionStatement tree) {
            outputCeylonPosition(tree);
            super.visitExec(tree);
        }

        @Override
        public void visitBreak(JCBreak tree) {
            outputCeylonPosition(tree);
            super.visitBreak(tree);
        }

        @Override
        public void visitContinue(JCContinue tree) {
            outputCeylonPosition(tree);
            super.visitContinue(tree);
        }

        @Override
        public void visitReturn(JCReturn tree) {
            outputCeylonPosition(tree);
            super.visitReturn(tree);
        }

        @Override
        public void visitThrow(JCThrow tree) {
            outputCeylonPosition(tree);
            super.visitThrow(tree);
        }

        @Override
        public void visitAssert(JCAssert tree) {
            outputCeylonPosition(tree);
            super.visitAssert(tree);
        }

        @Override
        public void visitApply(JCMethodInvocation tree) {
            outputCeylonPosition(tree);
            super.visitApply(tree);
        }

        @Override
        public void visitNewClass(JCNewClass tree) {
            outputCeylonPosition(tree);
            super.visitNewClass(tree);
        }

        @Override
        public void visitNewArray(JCNewArray tree) {
            outputCeylonPosition(tree);
            super.visitNewArray(tree);
        }

        @Override
        public void visitParens(JCParens tree) {
            outputCeylonPosition(tree);
            super.visitParens(tree);
        }

        @Override
        public void visitAssign(JCAssign tree) {
            outputCeylonPosition(tree);
            super.visitAssign(tree);
        }

        @Override
        public void visitAssignop(JCAssignOp tree) {
            outputCeylonPosition(tree);
            super.visitAssignop(tree);
        }

        @Override
        public void visitUnary(JCUnary tree) {
            outputCeylonPosition(tree);
            super.visitUnary(tree);
        }

        @Override
        public void visitBinary(JCBinary tree) {
            outputCeylonPosition(tree);
            super.visitBinary(tree);
        }

        @Override
        public void visitTypeCast(JCTypeCast tree) {
            outputCeylonPosition(tree);
            super.visitTypeCast(tree);
        }

        @Override
        public void visitTypeTest(JCInstanceOf tree) {
            outputCeylonPosition(tree);
            super.visitTypeTest(tree);
        }

        @Override
        public void visitIndexed(JCArrayAccess tree) {
            outputCeylonPosition(tree);
            super.visitIndexed(tree);
        }

        @Override
        public void visitSelect(JCFieldAccess tree) {
            outputCeylonPosition(tree);
            super.visitSelect(tree);
        }

        @Override
        public void visitIdent(JCIdent tree) {
            outputCeylonPosition(tree);
            super.visitIdent(tree);
        }

        @Override
        public void visitLiteral(JCLiteral tree) {
            outputCeylonPosition(tree);
            super.visitLiteral(tree);
        }

        @Override
        public void visitTypeIdent(JCPrimitiveTypeTree tree) {
            outputCeylonPosition(tree);
            super.visitTypeIdent(tree);
        }

        @Override
        public void visitTypeArray(JCArrayTypeTree tree) {
            outputCeylonPosition(tree);
            super.visitTypeArray(tree);
        }

        @Override
        public void visitTypeApply(JCTypeApply tree) {
            outputCeylonPosition(tree);
            super.visitTypeApply(tree);
        }

        @Override
        public void visitTypeParameter(JCTypeParameter tree) {
            outputCeylonPosition(tree);
            super.visitTypeParameter(tree);
        }

        @Override
        public void visitWildcard(JCWildcard tree) {
            outputCeylonPosition(tree);
            super.visitWildcard(tree);
        }

        @Override
        public void visitTypeBoundKind(TypeBoundKind tree) {
            outputCeylonPosition(tree);
            super.visitTypeBoundKind(tree);
        }

        @Override
        public void visitErroneous(JCErroneous tree) {
            outputCeylonPosition(tree);
            super.visitErroneous(tree);
        }

        @Override
        public void visitLetExpr(LetExpr tree) {
            outputCeylonPosition(tree);
            super.visitLetExpr(tree);
        }

        @Override
        public void visitModifiers(JCModifiers mods) {
            outputCeylonPosition(mods);
            super.visitModifiers(mods);
        }

        @Override
        public void visitAnnotation(JCAnnotation tree) {
            outputCeylonPosition(tree);
            super.visitAnnotation(tree);
        }

        @Override
        public void visitTree(JCTree tree) {
            outputCeylonPosition(tree);
            super.visitTree(tree);
        }
    };
    printer.visitTopLevel(unit);
    return writer.toString();
}
Also used : JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) JCTypeApply(com.sun.tools.javac.tree.JCTree.JCTypeApply) JCAssert(com.sun.tools.javac.tree.JCTree.JCAssert) JCPrimitiveTypeTree(com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCIf(com.sun.tools.javac.tree.JCTree.JCIf) JCEnhancedForLoop(com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) JCNewArray(com.sun.tools.javac.tree.JCTree.JCNewArray) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation) JCCase(com.sun.tools.javac.tree.JCTree.JCCase) JCThrow(com.sun.tools.javac.tree.JCTree.JCThrow) JCImport(com.sun.tools.javac.tree.JCTree.JCImport) JCWildcard(com.sun.tools.javac.tree.JCTree.JCWildcard) JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) JCIdent(com.sun.tools.javac.tree.JCTree.JCIdent) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) LetExpr(com.sun.tools.javac.tree.JCTree.LetExpr) JCErroneous(com.sun.tools.javac.tree.JCTree.JCErroneous) JCSynchronized(com.sun.tools.javac.tree.JCTree.JCSynchronized) JCParens(com.sun.tools.javac.tree.JCTree.JCParens) JCDoWhileLoop(com.sun.tools.javac.tree.JCTree.JCDoWhileLoop) JCContinue(com.sun.tools.javac.tree.JCTree.JCContinue) JCInstanceOf(com.sun.tools.javac.tree.JCTree.JCInstanceOf) TypeBoundKind(com.sun.tools.javac.tree.JCTree.TypeBoundKind) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCUnary(com.sun.tools.javac.tree.JCTree.JCUnary) JCModifiers(com.sun.tools.javac.tree.JCTree.JCModifiers) JCCatch(com.sun.tools.javac.tree.JCTree.JCCatch) JCCompilationUnit(com.sun.tools.javac.tree.JCTree.JCCompilationUnit) JCWhileLoop(com.sun.tools.javac.tree.JCTree.JCWhileLoop) JCReturn(com.sun.tools.javac.tree.JCTree.JCReturn) JCLabeledStatement(com.sun.tools.javac.tree.JCTree.JCLabeledStatement) JCAssign(com.sun.tools.javac.tree.JCTree.JCAssign) JCSkip(com.sun.tools.javac.tree.JCTree.JCSkip) JCConditional(com.sun.tools.javac.tree.JCTree.JCConditional) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement) CharArrayWriter(java.io.CharArrayWriter) JCTypeCast(com.sun.tools.javac.tree.JCTree.JCTypeCast) JCArrayTypeTree(com.sun.tools.javac.tree.JCTree.JCArrayTypeTree) JCBlock(com.sun.tools.javac.tree.JCTree.JCBlock) JCTree(com.sun.tools.javac.tree.JCTree) JCBinary(com.sun.tools.javac.tree.JCTree.JCBinary) JCArrayAccess(com.sun.tools.javac.tree.JCTree.JCArrayAccess) IOException(java.io.IOException) JCForLoop(com.sun.tools.javac.tree.JCTree.JCForLoop) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Pretty(com.sun.tools.javac.tree.Pretty) JCTry(com.sun.tools.javac.tree.JCTree.JCTry) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) JCLiteral(com.sun.tools.javac.tree.JCTree.JCLiteral) JCAssignOp(com.sun.tools.javac.tree.JCTree.JCAssignOp) JCBreak(com.sun.tools.javac.tree.JCTree.JCBreak)

Example 4 with JCSwitch

use of com.sun.tools.javac.tree.JCTree.JCSwitch in project ceylon-compiler by ceylon.

the class ClassTransformer method serializationGet.

private void serializationGet(Class model, ClassDefinitionBuilder classBuilder) {
    MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$get$.toString());
    mdb.isOverride(true);
    mdb.ignoreModelAnnotations();
    mdb.modifiers(PUBLIC);
    ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(this, Unfix.reference.toString());
    pdb.modifiers(FINAL);
    pdb.type(make().Type(syms().ceylonReachableReferenceType), null);
    mdb.parameter(pdb);
    mdb.resultType(null, make().Type(syms().objectType));
    /*
         * public void $set$(Object reference, Object instance) {
         *     switch((String)reference) {
         *     case ("attr1")
         *           return ...;
         *     // ... other fields of this class
         *     case ("lateAttr1")
         *           if (!$init$lateAttr1) {
         *               return ceylon.language.serialization.uninitializedLateValue.get_();
         *           }
         *           return ...;
         *     case (null):
         *           return Outer.this;
         *     default:
         *           return super.get(reference);
         */
    ListBuffer<JCCase> cases = ListBuffer.<JCCase>lb();
    boolean[] needsLookup = new boolean[] { false };
    for (Declaration member : model.getMembers()) {
        if (hasField(member)) {
            if (member instanceof Function)
                // TODO: This class is not serializable
                continue;
            ListBuffer<JCStatement> caseStmts = ListBuffer.<JCStatement>lb();
            if (member instanceof Value && ((Value) member).isLate()) {
                // TODO this should be encapsulated so the ADB and this
                // code can just call something common
                JCExpression test;
                if (CodegenUtil.needsLateInitField((Value) member, typeFact())) {
                    test = make().Unary(JCTree.NOT, naming.makeUnquotedIdent(Naming.getInitializationFieldName(member.getName())));
                } else {
                    test = make().Binary(JCTree.EQ, naming.makeQualifiedName(naming.makeThis(), (Value) member, Naming.NA_IDENT), makeNull());
                }
                caseStmts.add(make().If(test, make().Return(makeLanguageSerializationValue("uninitializedLateValue")), null));
            }
            caseStmts.add(make().Return(makeSerializationGetter((Value) member)));
            cases.add(make().Case(make().Literal(member.getQualifiedNameString()), caseStmts.toList()));
        }
    }
    SyntheticName reference = naming.synthetic(Unfix.reference);
    ListBuffer<JCStatement> defaultCase = ListBuffer.lb();
    if (extendsSerializable(model)) {
        // super.get(reference);
        defaultCase.add(make().Return(make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$get$.toString()), List.<JCExpression>of(reference.makeIdent()))));
    } else {
        // throw (or pass to something else to throw, based on policy)
        defaultCase.add(make().Throw(make().NewClass(null, null, naming.makeQuotedFQIdent("java.lang.RuntimeException"), List.<JCExpression>of(make().Literal("unknown attribute")), null)));
    }
    cases.add(make().Case(null, defaultCase.toList()));
    ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
    if (needsLookup[0]) {
        // if we needed to use a lookup object to reset final fields, 
        // prepend that variable
        stmts.add(makeVar(FINAL, "lookup", naming.makeQualIdent(make().Type(syms().methodHandlesType), "Lookup"), make().Apply(null, naming.makeQuotedFQIdent("java.lang.invoke.MethodHandles.lookup"), List.<JCExpression>nil())));
    }
    JCSwitch swtch = make().Switch(make().Apply(null, naming.makeSelect(make().Apply(null, naming.makeSelect(make().TypeCast(make().Type(syms().ceylonMemberType), reference.makeIdent()), "getAttribute"), List.<JCExpression>nil()), "getQualifiedName"), List.<JCExpression>nil()), cases.toList());
    if (model.isMember() && !model.getExtendedType().getDeclaration().isMember()) {
        stmts.add(make().If(make().TypeTest(reference.makeIdent(), make().Type(syms().ceylonOuterType)), make().Return(expressionGen().makeOuterExpr(((TypeDeclaration) model.getContainer()).getType())), swtch));
    } else {
        stmts.add(swtch);
    }
    mdb.body(stmts.toList());
    classBuilder.method(mdb);
}
Also used : SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Function(com.redhat.ceylon.model.typechecker.model.Function) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(com.redhat.ceylon.model.loader.model.JavaBeanValue) Value(com.redhat.ceylon.model.typechecker.model.Value) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) JCCase(com.sun.tools.javac.tree.JCTree.JCCase)

Example 5 with JCSwitch

use of com.sun.tools.javac.tree.JCTree.JCSwitch in project ceylon-compiler by ceylon.

the class ClassTransformer method serializationSet.

private void serializationSet(Class model, ClassDefinitionBuilder classBuilder) {
    MethodDefinitionBuilder mdb = MethodDefinitionBuilder.systemMethod(this, Unfix.$set$.toString());
    mdb.isOverride(true);
    mdb.ignoreModelAnnotations();
    mdb.modifiers(PUBLIC);
    ParameterDefinitionBuilder pdb = ParameterDefinitionBuilder.systemParameter(this, Unfix.reference.toString());
    pdb.modifiers(FINAL);
    pdb.type(make().Type(syms().ceylonReachableReferenceType), null);
    mdb.parameter(pdb);
    ParameterDefinitionBuilder pdb2 = ParameterDefinitionBuilder.systemParameter(this, Unfix.instance.toString());
    pdb2.modifiers(FINAL);
    pdb2.type(make().Type(syms().objectType), null);
    mdb.parameter(pdb2);
    //mdb.resultType(null, naming.makeQuotedFQIdent("java.util.Collection"));
    /*
         * public void $set$(Object reference, Object instance) {
         *     switch((String)reference) {
         *     case ("attr1")
         *           this.field1 = ...;
         *           break;
         *     // ... other fields of this class
         *     default:
         *           super.set(reference, instance);
         */
    SyntheticName reference = naming.synthetic(Unfix.reference);
    SyntheticName instance = naming.synthetic(Unfix.instance);
    ListBuffer<JCCase> cases = ListBuffer.<JCCase>lb();
    boolean[] needsLookup = new boolean[] { false };
    for (Declaration member : model.getMembers()) {
        if (hasField(member)) {
            if (member instanceof Function)
                // TODO: This class is not serializable 
                continue;
            ListBuffer<JCStatement> caseStmts = ListBuffer.<JCStatement>lb();
            if (member instanceof Value && ((Value) member).isLate()) {
                caseStmts.add(make().If(make().TypeTest(instance.makeIdent(), make().Type(syms().ceylonUninitializedLateValueType)), make().Break(null), null));
            }
            caseStmts.add(makeDeserializationAssignment((Value) member, needsLookup));
            caseStmts.add(make().Break(null));
            cases.add(make().Case(make().Literal(member.getQualifiedNameString()), caseStmts.toList()));
        }
    }
    ListBuffer<JCStatement> defaultCase = ListBuffer.lb();
    if (extendsSerializable(model)) {
        // super.set(reference, instance);
        defaultCase.add(make().Exec(make().Apply(null, naming.makeQualIdent(naming.makeSuper(), Unfix.$set$.toString()), List.<JCExpression>of(reference.makeIdent(), instance.makeIdent()))));
    } else {
        // throw (or pass to something else to throw, based on policy)
        defaultCase.add(make().Throw(make().NewClass(null, null, naming.makeQuotedFQIdent("java.lang.RuntimeException"), List.<JCExpression>of(make().Literal("unknown attribute")), null)));
    }
    cases.add(make().Case(null, defaultCase.toList()));
    ListBuffer<JCStatement> stmts = ListBuffer.<JCStatement>lb();
    if (needsLookup[0]) {
        // if we needed to use a lookup object to reset final fields, 
        // prepend that variable
        stmts.add(makeVar(FINAL, "lookup", naming.makeQualIdent(make().Type(syms().methodHandlesType), "Lookup"), make().Apply(null, naming.makeQuotedFQIdent("java.lang.invoke.MethodHandles.lookup"), List.<JCExpression>nil())));
    }
    JCSwitch swtch = make().Switch(make().Apply(null, naming.makeSelect(make().Apply(null, naming.makeSelect(make().TypeCast(make().Type(syms().ceylonMemberType), reference.makeIdent()), "getAttribute"), List.<JCExpression>nil()), "getQualifiedName"), List.<JCExpression>nil()), cases.toList());
    stmts.add(make().If(make().TypeTest(reference.makeIdent(), make().Type(syms().ceylonMemberType)), swtch, make().Throw(make().NewClass(null, null, make().Type(syms().ceylonAssertionErrorType), List.<JCExpression>of(make().Binary(JCTree.PLUS, make().Literal("unexpected reachable reference "), reference.makeIdent())), null))));
    mdb.body(stmts.toList());
    classBuilder.method(mdb);
}
Also used : SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) Function(com.redhat.ceylon.model.typechecker.model.Function) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(com.redhat.ceylon.model.loader.model.JavaBeanValue) Value(com.redhat.ceylon.model.typechecker.model.Value) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) MethodDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration) AttributeDeclaration(com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration) JCCase(com.sun.tools.javac.tree.JCTree.JCCase)

Aggregations

JCSwitch (com.sun.tools.javac.tree.JCTree.JCSwitch)5 JCCase (com.sun.tools.javac.tree.JCTree.JCCase)4 JCTree (com.sun.tools.javac.tree.JCTree)3 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)3 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)3 SyntheticName (com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName)2 AttributeDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)2 MethodDeclaration (com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration)2 JavaBeanValue (com.redhat.ceylon.model.loader.model.JavaBeanValue)2 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)2 Function (com.redhat.ceylon.model.typechecker.model.Function)2 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)2 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)2 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)2 Value (com.redhat.ceylon.model.typechecker.model.Value)2 ImmutableSet.toImmutableSet (com.google.common.collect.ImmutableSet.toImmutableSet)1 Iterables.getLast (com.google.common.collect.Iterables.getLast)1 Iterables.getOnlyElement (com.google.common.collect.Iterables.getOnlyElement)1 BugPattern (com.google.errorprone.BugPattern)1 JDK (com.google.errorprone.BugPattern.Category.JDK)1