Search in sources :

Example 26 with JCMethodDecl

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

the class ClassDefinitionBuilder method addAnnotationTypeMethod.

public ClassDefinitionBuilder addAnnotationTypeMethod(Type type) {
    MethodDefinitionBuilder method = MethodDefinitionBuilder.systemMethod(gen, "annotationType");
    method.modifiers(PUBLIC);
    method.resultType(List.<JCAnnotation>nil(), gen.make().TypeApply(gen.make().QualIdent(gen.syms().classType.tsym), List.<JCTree.JCExpression>of(gen.make().Wildcard(gen.make().TypeBoundKind(BoundKind.EXTENDS), gen.make().Type(gen.syms().annotationType)))));
    method.isOverride(true);
    List<JCStatement> body = List.<JCStatement>of(gen.make().Return(gen.makeClassLiteral(type, AbstractTransformer.JT_ANNOTATION)));
    method.body(body);
    JCMethodDecl build = method.build();
    defs(build);
    return this;
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement)

Example 27 with JCMethodDecl

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

the class ExpressionTransformer method transformSpreadOperator.

private JCExpression transformSpreadOperator(final Tree.QualifiedMemberOrTypeExpression expr, TermTransformer transformer) {
    at(expr);
    boolean spreadMethodReferenceOuter = !expr.equals(this.spreading) && !isWithinInvocation() && isCeylonCallableSubtype(expr.getTypeModel());
    boolean spreadMethodReferenceInner = expr.equals(this.spreading) && isWithinInvocation();
    Tree.QualifiedMemberOrTypeExpression oldSpreading = spreading;
    if (spreadMethodReferenceOuter) {
        spreading = expr;
    }
    try {
        Naming.SyntheticName varBaseName = naming.alias("spread");
        ListBuffer<JCStatement> letStmts = ListBuffer.<JCStatement>lb();
        final Naming.SyntheticName srcIterableName;
        if (spreadMethodReferenceInner) {
            // use the var we initialized in the outer
            srcIterableName = this.memberPrimary;
        } else {
            srcIterableName = varBaseName.suffixedBy(Suffix.$iterable$);
        }
        if (spreadMethodReferenceOuter) {
            // if we're in the outer, note then name of the var for use in the inner.
            this.memberPrimary = srcIterableName;
        }
        Naming.SyntheticName srcIteratorName = varBaseName.suffixedBy(Suffix.$iterator$);
        Type srcElementType = expr.getTarget().getQualifyingType();
        JCExpression srcIterableTypeExpr = makeJavaType(typeFact().getIterableType(srcElementType), JT_NO_PRIMITIVES);
        JCExpression srcIterableExpr;
        boolean isSuperOrSuperOf = false;
        if (spreadMethodReferenceInner) {
            srcIterableExpr = srcIterableName.makeIdent();
        } else {
            boolean isSuper = isSuper(expr.getPrimary());
            isSuperOrSuperOf = isSuper || isSuperOf(expr.getPrimary());
            if (isSuperOrSuperOf) {
                // so we just refer to it later
                if (isSuper) {
                    Declaration member = expr.getPrimary().getTypeModel().getDeclaration().getMember("iterator", null, false);
                    srcIterableExpr = transformSuper(expr, (TypeDeclaration) member.getContainer());
                } else
                    srcIterableExpr = transformSuperOf(expr, expr.getPrimary(), "iterator");
            } else {
                srcIterableExpr = transformExpression(expr.getPrimary(), BoxingStrategy.BOXED, typeFact().getIterableType(srcElementType));
            }
        }
        // do not capture the iterable for super invocations: see above
        if (!spreadMethodReferenceInner && !isSuperOrSuperOf) {
            JCVariableDecl srcIterable = null;
            srcIterable = makeVar(Flags.FINAL, srcIterableName, srcIterableTypeExpr, srcIterableExpr);
            letStmts.prepend(srcIterable);
        }
        Type resultElementType = expr.getTarget().getType();
        Type resultAbsentType = typeFact().getIteratedAbsentType(expr.getPrimary().getTypeModel());
        // private Iterator<srcElementType> iterator = srcIterableName.iterator();
        JCVariableDecl srcIterator = makeVar(Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
        naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
        Naming.SyntheticName iteratorResultName = varBaseName.suffixedBy(Suffix.$element$);
        /* public Object next() {
             *     Object result;
             *     if (!((result = iterator.next()) instanceof Finished)) {
             *         result = transformedMember(result);
             *     }
             *     return result;
             */
        /* Any arguments in the member of the spread would get re-evaluated on each iteration
             * so we need to shift them to the scope of the Let to ensure they're evaluated once. 
             */
        boolean aliasArguments = (transformer instanceof InvocationTermTransformer) && ((InvocationTermTransformer) transformer).invocation.getNode() instanceof Tree.InvocationExpression && ((Tree.InvocationExpression) ((InvocationTermTransformer) transformer).invocation.getNode()).getPositionalArgumentList() != null;
        if (aliasArguments) {
            ((InvocationTermTransformer) transformer).callBuilder.argumentHandling(CallBuilder.CB_ALIAS_ARGS, varBaseName);
        }
        JCNewClass iterableClass;
        boolean prevSyntheticClassBody = expressionGen().withinSyntheticClassBody(true);
        try {
            JCExpression transformedElement = applyErasureAndBoxing(iteratorResultName.makeIdent(), typeFact().getAnythingType(), CodegenUtil.hasTypeErased(expr.getPrimary()), true, BoxingStrategy.BOXED, srcElementType, 0);
            transformedElement = transformMemberExpression(expr, transformedElement, transformer);
            // be handled by the previous recursion
            if (spreadMethodReferenceOuter) {
                return make().LetExpr(letStmts.toList(), transformedElement);
            }
            transformedElement = applyErasureAndBoxing(transformedElement, resultElementType, // not necessarily of the applied member
            expr.getTarget().getDeclaration() instanceof TypedDeclaration ? CodegenUtil.hasTypeErased((TypedDeclaration) expr.getTarget().getDeclaration()) : false, !CodegenUtil.isUnBoxed(expr), BoxingStrategy.BOXED, resultElementType, 0);
            MethodDefinitionBuilder nextMdb = MethodDefinitionBuilder.systemMethod(this, "next");
            nextMdb.isOverride(true);
            nextMdb.annotationFlags(Annotations.IGNORE);
            nextMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
            nextMdb.resultType(null, make().Type(syms().objectType));
            nextMdb.body(List.of(makeVar(iteratorResultName, make().Type(syms().objectType), null), make().If(make().Unary(JCTree.NOT, make().TypeTest(make().Assign(iteratorResultName.makeIdent(), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Type(syms().ceylonFinishedType))), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(iteratorResultName.makeIdent(), transformedElement)))), null), make().Return(iteratorResultName.makeIdent())));
            JCMethodDecl nextMethod = nextMdb.build();
            // new AbstractIterator()
            JCNewClass iteratorClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIteratorType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType)), make().AnonymousClassDef(make().Modifiers(0), List.of(srcIterator, nextMethod)));
            MethodDefinitionBuilder iteratorMdb = MethodDefinitionBuilder.systemMethod(this, "iterator");
            iteratorMdb.isOverride(true);
            iteratorMdb.annotationFlags(Annotations.IGNORE);
            iteratorMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
            iteratorMdb.resultType(null, makeJavaType(typeFact().getIteratorType(resultElementType)));
            iteratorMdb.body(make().Return(iteratorClass));
            // new AbstractIterable()
            iterableClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIterableType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT), makeJavaType(resultAbsentType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType), makeReifiedTypeArgument(resultAbsentType)), make().AnonymousClassDef(make().Modifiers(0), List.<JCTree>of(iteratorMdb.build())));
        } finally {
            expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
        }
        if (aliasArguments) {
            letStmts = letStmts.appendList(((InvocationTermTransformer) transformer).callBuilder.getStatements());
        }
        JCMethodInvocation result = make().Apply(null, naming.makeQualIdent(iterableClass, "sequence"), List.<JCExpression>nil());
        JCExpression spread = letStmts.isEmpty() ? result : make().LetExpr(letStmts.toList(), result);
        // Do we *statically* know the result must be a Sequence 
        final boolean primaryIsSequence = typeFact().isNonemptyIterableType(expr.getPrimary().getTypeModel());
        Type returnElementType = expr.getTarget().getType();
        if (primaryIsSequence) {
            int flags = EXPR_DOWN_CAST;
            spread = applyErasureAndBoxing(spread, typeFact().getSequentialType(returnElementType), false, true, BoxingStrategy.BOXED, primaryIsSequence ? typeFact().getSequenceType(returnElementType) : typeFact().getSequentialType(returnElementType), flags);
        }
        return spread;
    } finally {
        spreading = oldSpreading;
    }
}
Also used : TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) Type(com.redhat.ceylon.model.typechecker.model.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) SyntheticName(com.redhat.ceylon.compiler.java.codegen.Naming.SyntheticName) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration)

Example 28 with JCMethodDecl

use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project bazel by bazelbuild.

the class InternalUtils method constructor.

/**
     * Determines the symbol for a constructor given an invocation via
     * {@code new}.
     *
     * If the tree is a declaration of an anonymous class, then method returns
     * constructor that gets invoked in the extended class, rather than the
     * anonymous constructor implicitly added by the constructor (JLS 15.9.5.1)
     *
     * @param tree the constructor invocation
     * @return the {@link ExecutableElement} corresponding to the constructor
     *         call in {@code tree}
     */
public static ExecutableElement constructor(NewClassTree tree) {
    if (!(tree instanceof JCTree.JCNewClass)) {
        ErrorReporter.errorAbort("InternalUtils.constructor: not a javac internal tree");
        // dead code
        return null;
    }
    JCNewClass newClassTree = (JCNewClass) tree;
    if (RETURN_INVOKE_CONSTRUCTOR && tree.getClassBody() != null) {
        // anonymous constructor bodies should contain exactly one statement
        // in the form:
        //    super(arg1, ...)
        // or
        //    o.super(arg1, ...)
        //
        // which is a method invocation (!) to the actual constructor
        // the method call is guaranteed to return nonnull
        JCMethodDecl anonConstructor = (JCMethodDecl) TreeInfo.declarationFor(newClassTree.constructor, newClassTree);
        assert anonConstructor != null;
        assert anonConstructor.body.stats.size() == 1;
        JCExpressionStatement stmt = (JCExpressionStatement) anonConstructor.body.stats.head;
        JCTree.JCMethodInvocation superInvok = (JCMethodInvocation) stmt.expr;
        return (ExecutableElement) TreeInfo.symbol(superInvok.meth);
    }
    Element e = newClassTree.constructor;
    assert e instanceof ExecutableElement;
    return (ExecutableElement) e;
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) ExecutableElement(javax.lang.model.element.ExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) JCTree(com.sun.tools.javac.tree.JCTree) JCExpressionStatement(com.sun.tools.javac.tree.JCTree.JCExpressionStatement) JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation)

Example 29 with JCMethodDecl

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

the class JUnit3TestNotRun method matchMethod.

/**
   * Matches if:
   * 1) Method's name begins with misspelled variation of "test".
   * 2) Method is public, returns void, and has no parameters.
   * 3) Enclosing class is JUnit3 test (extends TestCase, has no RunWith annotation,
   *    and is not abstract).
   */
@Override
public Description matchMethod(MethodTree methodTree, VisitorState state) {
    Matcher<MethodTree> methodMatcher = allOf(not(methodNameStartsWith("test")), Matchers.<MethodTree>hasModifier(Modifier.PUBLIC), methodReturns(VOID_TYPE), methodHasParameters(), enclosingClass(isJUnit3TestClass));
    if (!methodMatcher.matches(methodTree, state)) {
        return Description.NO_MATCH;
    }
    String name = methodTree.getName().toString();
    String fixedName;
    // regex.Matcher class name collides with errorprone.Matcher
    java.util.regex.Matcher matcher = MISSPELLED_NAME.matcher(name);
    if (matcher.lookingAt()) {
        fixedName = matcher.replaceFirst("test");
    } else if (wouldRunInJUnit4.matches(methodTree, state)) {
        fixedName = "test" + name.substring(0, 1).toUpperCase() + name.substring(1);
    } else {
        return Description.NO_MATCH;
    }
    // We don't have start position for a method symbol, so we replace everything between result
    // type and body.
    JCMethodDecl decl = (JCMethodDecl) methodTree;
    Fix fix = SuggestedFix.replace(decl.restype.getStartPosition() + 4, decl.body.getStartPosition(), " " + fixedName + "() ");
    return describeMatch(methodTree, fix);
}
Also used : JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Fix(com.google.errorprone.fixes.Fix) MethodTree(com.sun.source.tree.MethodTree)

Example 30 with JCMethodDecl

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

the class AbstractTestExceptionChecker method matchMethod.

@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
    if (tree.getBody() == null) {
        return NO_MATCH;
    }
    SuggestedFix.Builder baseFixBuilder = SuggestedFix.builder();
    JCExpression expectedException = deleteExpectedException(baseFixBuilder, ((JCMethodDecl) tree).getModifiers().getAnnotations(), state);
    SuggestedFix baseFix = baseFixBuilder.build();
    if (expectedException == null) {
        return NO_MATCH;
    }
    return handleStatements(tree, state, expectedException, baseFix);
}
Also used : JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCMethodDecl(com.sun.tools.javac.tree.JCTree.JCMethodDecl) SuggestedFix(com.google.errorprone.fixes.SuggestedFix)

Aggregations

JCMethodDecl (com.sun.tools.javac.tree.JCTree.JCMethodDecl)45 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)31 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)20 Name (com.sun.tools.javac.util.Name)17 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)16 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)16 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)15 ListBuffer (com.sun.tools.javac.util.ListBuffer)14 JCClassDecl (com.sun.tools.javac.tree.JCTree.JCClassDecl)13 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)13 JavacNode (lombok.javac.JavacNode)13 JCTree (com.sun.tools.javac.tree.JCTree)12 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)5 Type (com.sun.tools.javac.code.Type)5 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)5 JCFieldAccess (com.sun.tools.javac.tree.JCTree.JCFieldAccess)5 JCNewClass (com.sun.tools.javac.tree.JCTree.JCNewClass)5 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)4 JavacTreeMaker (lombok.javac.JavacTreeMaker)4 JCExpressionStatement (com.sun.tools.javac.tree.JCTree.JCExpressionStatement)3