All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.compiler.java.codegen.AnnotationInvocationVisitor Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/*
 * Copyright Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the authors tag. All rights reserved.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License version 2.
 * 
 * This particular file is subject to the "Classpath" exception as provided in the 
 * LICENSE file that accompanied this code.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License,
 * along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */
package com.redhat.ceylon.compiler.java.codegen;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.redhat.ceylon.compiler.java.codegen.AbstractTransformer.BoxingStrategy;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.PositionalArgument;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCAssign;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCExpression;
import com.redhat.ceylon.langtools.tools.javac.tree.JCTree.JCNewArray;
import com.redhat.ceylon.langtools.tools.javac.util.ListBuffer;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;
import com.redhat.ceylon.model.typechecker.model.Class;
import com.redhat.ceylon.model.typechecker.model.ClassOrInterface;
import com.redhat.ceylon.model.typechecker.model.Declaration;
import com.redhat.ceylon.model.typechecker.model.Functional;
import com.redhat.ceylon.model.typechecker.model.Function;
import com.redhat.ceylon.model.typechecker.model.Module;
import com.redhat.ceylon.model.typechecker.model.Package;
import com.redhat.ceylon.model.typechecker.model.Parameter;
import com.redhat.ceylon.model.typechecker.model.Type;
import com.redhat.ceylon.model.typechecker.model.TypeDeclaration;
import com.redhat.ceylon.model.typechecker.model.Value;

class AnnotationInvocationVisitor extends Visitor {

    public static Class annoClass(Tree.InvocationExpression invocation) {
        Declaration declaration = ((Tree.BaseMemberOrTypeExpression)invocation.getPrimary()).getDeclaration();
        Set ctors = new HashSet();
        while (declaration instanceof Function) {
            if (!ctors.add(declaration)) {
                throw new BugException(invocation, "recursive annotation constructor");
            }
            declaration = ((AnnotationInvocation)((Function)declaration).getAnnotationConstructor()).getPrimary();
        } 
        
        if (declaration instanceof Class) {
            return (Class)declaration;
        } else {
            throw new BugException(invocation, "invocation primary has unexpected declaration: " + declaration);
        }
    }
    
    public static Function annoCtor(Tree.InvocationExpression invocation) {
        Declaration declaration = ((Tree.BaseMemberOrTypeExpression)invocation.getPrimary()).getDeclaration();
        if (declaration instanceof Function) {
            return (Function)declaration;
        } else if (declaration instanceof Class) {
            return null;
        } else {
            throw new BugException(invocation, "invocation primary has unexpected declaration: " + declaration);
        }
    }
    
    public static AnnotationInvocation annoCtorModel(Tree.InvocationExpression invocation) {
        Declaration declaration = ((Tree.BaseMemberOrTypeExpression)invocation.getPrimary()).getDeclaration();
        if (declaration instanceof Function) {
            return (AnnotationInvocation)((Function)declaration).getAnnotationConstructor();
        } else if (declaration instanceof Class) {
            // TODO Why doesn't the AnnotationModelVisitor do this? I guess because
            // an annotation Class's doesn't have a body, so there's no need for Visitor
            // But it could have defaulted arguments
            AnnotationInvocation in = new AnnotationInvocation();
            in.setPrimary((Class)declaration);
            java.util.List args = new ArrayList<>();
            for (Parameter p : ((Class)declaration).getParameterList().getParameters()) {
                AnnotationArgument arg = new AnnotationArgument();
                arg.setParameter(p);
                ParameterAnnotationTerm term = new ParameterAnnotationTerm();
                term.setSourceParameter(p);
                term.setSpread(false);
                arg.setTerm(term);
                args.add(arg);
            }
            in.getAnnotationArguments().addAll(args);
            in.setInterop(false);
            in.setConstructorDeclaration(null);
            return in;
        } else {
            throw new BugException(invocation, "invocation primary has unexpected declaration: " + declaration);
        }
    }
    
    private final Node errorNode;
    private final ExpressionTransformer exprGen;
    private final AnnotationInvocation anno;
    
    
    private Parameter parameter;
    private Type expectedType;
    private ListBuffer arrayExprs = null;
    private JCExpression argumentExpr;

    private AnnotationInvocationVisitor(
            ExpressionTransformer expressionTransformer, Node errorNode, AnnotationInvocation anno) {
        this.exprGen = expressionTransformer;
        this.errorNode = errorNode;
        this.anno = anno;
    }
    
    private JCExpression getExpression() {
        if (argumentExpr != null) {
            return argumentExpr;
        } else if (arrayExprs != null) {
            return exprGen.make().NewArray(null, null, arrayExprs.toList());
        } else if (anno.isInterop()) {
            // This can happen if we're invoking an interop constructor
            // and defaulting an argument
            return null;
        } else {
            return exprGen.makeErroneous(errorNode, "compiler bug: no result when transforming annotation");
        }
        
    }
    
    public static JCAnnotation transform(ExpressionTransformer expressionTransformer, Tree.InvocationExpression invocation) {
        AnnotationInvocationVisitor visitor = new AnnotationInvocationVisitor(expressionTransformer, invocation, annoCtorModel(invocation));
        visitor.visit(invocation);
        return (JCAnnotation) visitor.getExpression();
    }
    
    public void visit(Tree.InvocationExpression invocation) {
        // Is it a class instantiation or a constructor invocation?
        Tree.Primary primary = invocation.getPrimary();
        try {
            if (primary instanceof Tree.BaseMemberExpression) {
                Tree.BaseMemberExpression ctor = (Tree.BaseMemberExpression)primary;
                if (!Decl.isAnnotationConstructor(ctor.getDeclaration())) {
                    append(exprGen.makeErroneous(primary, "compiler bug: " + ctor.getDeclaration().getName() + " is not an annotation constructor"));
                }
                append(transformConstructor(exprGen, invocation));
            } else if (primary instanceof Tree.BaseTypeExpression) {
                Tree.BaseTypeExpression bte = (Tree.BaseTypeExpression)primary;
                if (((TypeDeclaration) bte.getDeclaration()).isByte()) {
                    // Special case for "Byte(x)" where we make use of the fact that it looks
                    // like an annotation class instantiation but is in fact a byte literal
                    PositionalArgument arg = invocation.getPositionalArgumentList().getPositionalArguments().get(0);
                    arg.visit(this);
                } else {
                    if (!Decl.isAnnotationClass(bte.getDeclaration())) {
                        append(exprGen.makeErroneous(primary, "compiler bug: " + bte.getDeclaration().getName() + " is not an annotation class"));
                    }
                    append(transformInstantiation(exprGen, invocation));
                }
            } else {
                append(exprGen.makeErroneous(primary, "compiler bug: primary is not an annotation constructor or annotation class"));
            }
        } catch (BugException e) {
            e.addError(invocation);
        }
    }
    
    private static JCAnnotation transformInstantiation(ExpressionTransformer exprGen, Tree.InvocationExpression invocation) {
        AnnotationInvocation ai = annoCtorModel(invocation);
        AnnotationInvocationVisitor visitor = new AnnotationInvocationVisitor(exprGen, invocation, annoCtorModel(invocation));
        ListBuffer annotationArguments = ListBuffer.lb();
        if (invocation.getPositionalArgumentList() != null) {
            for (Tree.PositionalArgument arg : invocation.getPositionalArgumentList().getPositionalArguments()) {
                visitor.parameter = arg.getParameter();
                arg.visit(visitor);
                annotationArguments.append(makeArgument(exprGen, invocation, visitor.parameter, visitor.getExpression()));
            }
        } 
        if (invocation.getNamedArgumentList() != null) {
            for (Tree.NamedArgument arg : invocation.getNamedArgumentList().getNamedArguments()) {
                visitor.parameter = arg.getParameter();
                arg.visit(visitor);
                annotationArguments.append(makeArgument(exprGen, invocation, visitor.parameter, visitor.getExpression()));
            }
        }
        return exprGen.at(invocation).Annotation(
                ai.makeAnnotationType(exprGen),
                annotationArguments.toList());
    }
    
    public static JCAnnotation transformConstructor(ExpressionTransformer exprGen, Tree.InvocationExpression invocation) {
        AnnotationInvocation ai = annoCtorModel(invocation);
        return transformConstructor(exprGen, invocation, ai, com.redhat.ceylon.langtools.tools.javac.util.List.nil());
    }

    static String checkForBannedJavaAnnotation(Tree.InvocationExpression invocation) {
        if (invocation.getPrimary() instanceof Tree.BaseMemberExpression
                && ((Tree.BaseMemberExpression)invocation.getPrimary()).getDeclaration() != null) {
            String name = ((Tree.BaseMemberExpression)invocation.getPrimary()).getDeclaration().getQualifiedNameString();
            if ("java.lang::deprecated".equals(name)) {
                return "inappropiate java annotation: interoperation with @Deprecated is not supported: use deprecated";
            } else if ("java.lang::override".equals(name)) {
                return "inappropiate java annotation: interoperation with @Override is not supported: use actual";
            } else if ("java.lang.annotation::target".equals(name)) {
                return "inappropiate java annotation: interoperation with @Target is not supported";
            } else if ("java.lang.annotation::retention".equals(name)) {
                return "inappropiate java annotation: interoperation with @Retention is not supported";
            }
        }
        return null;
    }
    
    private static JCAnnotation transformConstructor(
            ExpressionTransformer exprGen,
            Tree.InvocationExpression invocation, AnnotationInvocation ai, 
            com.redhat.ceylon.langtools.tools.javac.util.List fieldPath) {
        Map> args = new LinkedHashMap>();
        
        List classParameters = ai.getClassParameters();
        // The class parameter's we've not yet figured out the value for
        ArrayList unbound = new ArrayList(classParameters);
        for (Parameter classParameter : classParameters) {
            for (AnnotationArgument argument : ai.findAnnotationArgumentForClassParameter(classParameter)) {
                JCExpression expr = transformConstructorArgument(exprGen, invocation, classParameter, argument, fieldPath);
                appendArgument(args, classParameter, expr);
                unbound.remove(classParameter);
            }
        }
        outer: for (Parameter classParameter : ((ArrayList)unbound.clone())) {
            // Defaulted argument
            if (ai.isInstantiation()) {
                if (classParameter.isDefaulted()) {
                    // That's OK, we'll pick up the default argument from 
                    // the Java Annotation type
                    unbound.remove(classParameter);
                    continue outer;
                }
            } else {
                Function ac2 = (Function)ai.getPrimary();
                AnnotationInvocation i = (AnnotationInvocation)ac2.getAnnotationConstructor();
                for (AnnotationArgument aa : i.getAnnotationArguments()) {
                    if (aa.getParameter().equals(classParameter)) {
                        appendArgument(args, classParameter, 
                                aa.getTerm().makeAnnotationArgumentValue(exprGen, i,com.redhat.ceylon.langtools.tools.javac.util.List.of(aa)));
                        unbound.remove(classParameter);
                        continue outer;
                    }
                }
            }
            
            if (Strategy.hasEmptyDefaultArgument(classParameter)) {
                appendArgument(args, classParameter, 
                        exprGen.make().NewArray(null,  null, com.redhat.ceylon.langtools.tools.javac.util.List.nil()));
                unbound.remove(classParameter);
                continue outer;
            }
            
        }
        
        for (Parameter classParameter : unbound) {
            appendArgument(args, classParameter, 
                exprGen.makeErroneous(invocation, "compiler bug: unbound annotation class parameter " + classParameter.getName()));
        }
        ListBuffer assignments = ListBuffer.lb();
        for (Map.Entry> entry : args.entrySet()) {
            ListBuffer exprs = entry.getValue();
            if (exprs.size() == 1) {
                assignments.append(makeArgument(exprGen, invocation, entry.getKey(), exprs.first()));
            } else {
                assignments.append(makeArgument(exprGen, invocation, entry.getKey(), 
                        exprGen.make().NewArray(null, null, exprs.toList())));
            }
            
        }
        
        JCAnnotation annotation = exprGen.at(invocation).Annotation(
                ai.makeAnnotationType(exprGen),
                assignments.toList());
        return annotation;
    }
    
    private static void appendArgument(
            Map> args,
            Parameter classParameter, JCExpression expr) {
        if (expr != null) {
            ListBuffer exprList = args.get(classParameter);
            if (exprList == null) {
                exprList = ListBuffer.lb();
                args.put(classParameter, exprList);
            }
            exprList.append(expr);
        }
    }

    public static JCExpression transformConstructorArgument(
            ExpressionTransformer exprGen,
            Tree.InvocationExpression invocation,
            Parameter classParameter, AnnotationArgument argument, 
            com.redhat.ceylon.langtools.tools.javac.util.List fieldPath) {
        AnnotationInvocation anno = annoCtorModel(invocation);
        AnnotationInvocationVisitor visitor = new AnnotationInvocationVisitor(exprGen, invocation, anno);
        visitor.parameter = classParameter;
        AnnotationTerm term = argument.getTerm();
        if (term instanceof ParameterAnnotationTerm) {
            ParameterAnnotationTerm parameterArgument = (ParameterAnnotationTerm)term;
            Parameter sp = parameterArgument.getSourceParameter();
            int argumentIndex = ((Functional)sp.getDeclaration())
                    .getFirstParameterList().getParameters()
                    .indexOf(sp);
            if (invocation.getPositionalArgumentList() != null) {
                java.util.List positionalArguments = invocation.getPositionalArgumentList().getPositionalArguments();
                
                if (parameterArgument.isSpread()) {
                    visitor.transformSpreadArgument(positionalArguments.subList(argumentIndex, positionalArguments.size()), classParameter);
                } else {
                    if (0 <= argumentIndex && argumentIndex < positionalArguments.size()) {
                        Tree.PositionalArgument pargument = positionalArguments.get(argumentIndex);
                        if (pargument.getParameter().isSequenced()) {
                            visitor.transformVarargs(argumentIndex, positionalArguments);
                        } else {
                            visitor.transformArgument(pargument);
                        }
                    } else if (sp.isDefaulted()) {
                        visitor.makeDefaultExpr(invocation, parameterArgument, sp);
                    } else if (sp.isSequenced()) {
                        visitor.appendBuiltArray(visitor.startArray());
                    }
                }
            } else if (invocation.getNamedArgumentList() != null) {
                boolean found = false;
                for (Tree.NamedArgument na : invocation.getNamedArgumentList().getNamedArguments()) {
                    Parameter parameter = na.getParameter();
                    int parameterIndex = anno.indexOfConstructorParameter(parameter);
                    if (parameterIndex == argumentIndex) {
                        visitor.transformArgument(na);
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    if (sp.isDefaulted()) {
                        visitor.makeDefaultExpr(invocation, parameterArgument, sp);
                    } else if (sp.isSequenced()) {
                        visitor.appendBuiltArray(visitor.startArray());
                    }else {
                        visitor.append(exprGen.makeErroneous(invocation, "Unable to find argument"));
                    }
                }
            }
        } else if (term instanceof LiteralAnnotationTerm) {
            visitor.append(term.makeAnnotationArgumentValue(visitor.exprGen, visitor.anno, fieldPath.append(argument)));
        } else if (term instanceof InvocationAnnotationTerm) {
            AnnotationInvocation instantiation = ((InvocationAnnotationTerm)term).getInstantiation();
            visitor.append(transformConstructor(visitor.exprGen, invocation, instantiation, fieldPath.append(argument)));
        } else {
            visitor.append(visitor.exprGen.makeErroneous(invocation, "Unable to find argument"));
        }
        return visitor.getExpression();
    }
    
    
    private void makeDefaultExpr(Tree.InvocationExpression invocation,
            ParameterAnnotationTerm parameterArgument, Parameter sp) {
        AnnotationConstructorParameter defaultedCtorParam = null;
        for (AnnotationConstructorParameter ctorParam : anno.getConstructorParameters()) {
            if (ctorParam.getParameter().equals(parameterArgument.getSourceParameter())) {
                defaultedCtorParam = ctorParam;
                break;
            }
        }
        if (defaultedCtorParam == null) {
            append(exprGen.makeErroneous(invocation, "compiler bug: defaulted parameter " + anno.getConstructorDeclaration().getName() + " could not be found"));
            return;
        }
        
        // Use the default parameter from the constructor
        if (defaultedCtorParam.getDefaultArgument() instanceof LiteralAnnotationTerm) {
            JCExpression expr = ((LiteralAnnotationTerm)defaultedCtorParam.getDefaultArgument()).makeLiteral(exprGen);
            append(expr);
        } else if (Decl.isAnnotationClass(sp.getType().getDeclaration())) {
                InvocationAnnotationTerm defaultedInvocation = (InvocationAnnotationTerm)defaultedCtorParam.getDefaultArgument();
                append(transformConstructor(exprGen, invocation, defaultedInvocation.getInstantiation(), 
                        com.redhat.ceylon.langtools.tools.javac.util.List.of(defaultedCtorParam)));
        }
    }
    
    private void transformVarargs(int argumentIndex,
            java.util.List pa) {
        ListBuffer prevCollect = startArray();
        try {
            for (int jj = argumentIndex; jj < pa.size(); jj++) {
                transformArgument(pa.get(jj));
            }
        } finally {
            appendBuiltArray(prevCollect);
        }
    }

    private static JCAssign makeArgument(ExpressionTransformer exprGen, Node errorNode, 
            Parameter parameter, JCExpression expr) {
        JCExpression memberName;
        if (parameter != null) {
            memberName = exprGen.naming.makeUnquotedIdent(
            Naming.selector(parameter.getModel(), Naming.NA_ANNOTATION_MEMBER));
        } else {
            memberName = exprGen.makeErroneous(errorNode, "compiler bug: null parameter in makeArgument");
        }
        return exprGen.make().Assign(memberName, expr);
    }
    
    /**
     * If we're currently constructing an array then or append the given expression
     * Otherwise make an annotation argument for given expression and 
     * append it to the annotation arguments,
     */
    private void append(JCExpression expr) {
        if (arrayExprs != null) {
            arrayExprs.append(expr);
        } else {
            if (this.argumentExpr != null) {
                throw new BugException(errorNode, "assertion failed");
            }
            this.argumentExpr = expr;
        }
    }

    private void transformSpreadArgument(java.util.List arguments, Parameter classParameter) {
        boolean varargs = classParameter.isSequenced()
                && arguments.size() > 1 || arguments.size() == 0;
        ListBuffer prevCollect = varargs ? startArray() : null;
        try {
            for (Tree.PositionalArgument arg : arguments) {
                exprGen.at(arg); 
                arg.visit(this);
            }
        } finally {
            if (varargs) {
                appendBuiltArray(prevCollect);
            }
        }
    }
    
    private void transformArgument(Tree.NamedArgument node) {
        exprGen.at(node);
        node.visit(this);
    }
    
    private void transformArgument(Tree.PositionalArgument node) {
        exprGen.at(node);
        node.visit(this);
    }
    
    @Override
    public void handleException(Exception e, Node node) {
        if (e instanceof RuntimeException) {
            throw (RuntimeException)e;
        } else {
            throw new RuntimeException(e);
        }
    }
    
    public void visit(Tree.Expression term) {
        term.visitChildren(this);
    }
    
    public void visit(Tree.Term term) {
        append(exprGen.makeErroneous(term, "compiler bug: " + term.getNodeType() + " is an unsupported term in an annotation invocation"));
    }
    
    public void visit(Tree.NegativeOp term) {
        if (term.getTerm() instanceof Tree.NaturalLiteral
                || term.getTerm() instanceof Tree.FloatLiteral) {
            append(exprGen.transformExpression(term, BoxingStrategy.UNBOXED, expectedType(), 
                    ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK));
        } else {
            append(exprGen.makeErroneous(term, "compiler bug: " + term.getNodeType() + " is an unsupported term in an annotation invocation"));
        }
    }
    
    public void visit(Tree.Literal term) {
        append(exprGen.transformExpression(term, BoxingStrategy.UNBOXED, expectedType(), 
                ExpressionTransformer.EXPR_UNSAFE_PRIMITIVE_TYPECAST_OK));
    }

    private Type expectedType() {
        return this.expectedType != null ?  this.expectedType : this.parameter.getType();
    }
    
    public void visit(Tree.BaseMemberExpression term) {
        if (exprGen.isBooleanTrue(term.getDeclaration())
                || exprGen.isBooleanFalse(term.getDeclaration())) {
            append(exprGen.transformExpression(term, BoxingStrategy.UNBOXED, term.getTypeModel()));
        } else if (Decl.isAnonCaseOfEnumeratedType(term)
                && !exprGen.isJavaEnumType(term.getTypeModel())) {
            append(exprGen.makeClassLiteral(term.getTypeModel()));
        } else if (anno.isInterop()) {
            if (exprGen.isJavaEnumType(term.getTypeModel())) {
                // A Java enum
                append(exprGen.transformExpression(term, BoxingStrategy.UNBOXED, null));
            }
        } else {
            super.visit(term);
        }
    }
    
    public void visit(Tree.MemberOrTypeExpression term) {
        // Metamodel reference
        if (anno.isInterop()) {
            Declaration decl = term.getDeclaration();
            if (decl instanceof ClassOrInterface) {
                append(exprGen.naming.makeQualIdent(
                        exprGen.makeJavaType(((ClassOrInterface)decl).getType()),
                        "class"));
            } else if (decl instanceof Value) {
                append(exprGen.transformExpression(term, BoxingStrategy.UNBOXED, term.getTypeModel(),
                        // target doesn't actually accept null, but we can't put a checkNull() call in there.
                        exprGen.EXPR_TARGET_ACCEPTS_NULL));
            }
        } else {
            append(exprGen.make().Literal(term.getDeclaration().getQualifiedNameString()));
        }
    }
    
    @Override
    public void visit(Tree.TypeLiteral tl){
        if((tl.getType() != null && tl.getType().getTypeModel() != null)
                || (tl.getDeclaration() != null
                    && tl.getDeclaration().isAnonymous())){
            if (anno.isInterop()) {
                append(exprGen.naming.makeQualIdent(
                        exprGen.makeJavaType(tl.getType().getTypeModel(), AbstractTransformer.JT_NO_PRIMITIVES | AbstractTransformer.JT_RAW),
                        "class"));
            } else {
                append(exprGen.makeMetaLiteralStringLiteralForAnnotation(tl));
            }
        }
    }
    
    @Override
    public void visit(Tree.MetaLiteral tl){
        append(exprGen.makeMetaLiteralStringLiteralForAnnotation(tl));
    }
    
    private ListBuffer startArray() {
        ListBuffer prevArray = arrayExprs;
        arrayExprs = ListBuffer.lb();
        expectedType = exprGen.typeFact().getIteratedType(parameter.getType());
        return prevArray;
    }
    
    private JCNewArray endArray(ListBuffer prevArray) {
        ListBuffer collected = arrayExprs;
        arrayExprs = prevArray;
        expectedType = null;
        return exprGen.make().NewArray(null,  null, collected.toList());
    }
    
    private void appendBuiltArray(ListBuffer prevArray) {
        append(endArray(prevArray));
    }

    public void visit(Tree.SequenceEnumeration term) {
        ListBuffer prevCollect = startArray();
        try {
            term.visitChildren(this);
        } finally {
            appendBuiltArray(prevCollect);
        }
    }
    
    public void visit(Tree.Tuple term) {
        ListBuffer prevCollect = startArray();
        try {
            term.visitChildren(this);
        } finally {
            appendBuiltArray(prevCollect);
        }
    }
    
    public void visit(Tree.PositionalArgument arg) {
        append(exprGen.makeErroneous(arg, "compiler bug: " + arg.getNodeType() + " is an unsupported positional argument in an annotation invocation"));
    }
    
    public void visit(Tree.ListedArgument arg) {
        arg.visitChildren(this);
    }
    
    public void visit(Tree.NamedArgument arg) {
        append(exprGen.makeErroneous(arg, "compiler bug: " + arg.getNodeType() + " is an unsupported named argument in an annotation invocation"));
    }
    
    public void visit(Tree.SpecifiedArgument arg) {
        arg.visitChildren(this);
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy