Search in sources :

Example 11 with ListBuffer

use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.

the class CallableBuilder method build.

public JCExpression build() {
    // Generate a subclass of Callable
    ListBuffer<JCTree> classBody = new ListBuffer<JCTree>();
    gen.at(node);
    if (parameterDefaultValueMethods != null) {
        for (MethodDefinitionBuilder mdb : parameterDefaultValueMethods) {
            classBody.append(mdb.build());
        }
    }
    transformation.appendMethods(classBody);
    gen.at(node);
    JCClassDecl classDef = gen.make().AnonymousClassDef(gen.make().Modifiers(0, annotations != null ? annotations : List.<JCAnnotation>nil()), classBody.toList());
    int variadicIndex = isVariadic ? numParams - 1 : -1;
    Type callableType;
    if (typeModel.isTypeConstructor()) {
        callableType = typeModel.getDeclaration().getExtendedType();
    } else {
        callableType = typeModel;
    }
    JCNewClass callableInstance;
    if (functionalInterface == null) {
        callableInstance = gen.at(node).NewClass(null, null, gen.makeJavaType(callableType, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>of(gen.makeReifiedTypeArgument(callableType.getTypeArgumentList().get(0)), gen.makeReifiedTypeArgument(callableType.getTypeArgumentList().get(1)), gen.make().Literal(callableType.asString(true)), gen.make().TypeCast(gen.syms().shortType, gen.makeInteger(variadicIndex))), classDef);
    } else {
        callableInstance = gen.make().NewClass(null, null, gen.makeJavaType(functionalInterface, JT_EXTENDS | JT_CLASS_NEW), List.<JCExpression>nil(), classDef);
    }
    JCExpression result;
    if (typeModel.isTypeConstructor()) {
        result = buildTypeConstructor(callableType, callableInstance);
    } else {
        result = callableInstance;
    }
    gen.at(null);
    if (instanceSubstitution != null) {
        instanceSubstitution.close();
    }
    return result;
}
Also used : JCClassDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCClassDecl) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)

Example 12 with ListBuffer

use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.

the class CallableBuilder method methodReference.

/**
 * Constructs an {@code AbstractCallable} suitable for wrapping a
 * method reference. For example:
 * <pre>
 *   void someMethod() { ... }
 *   Anything() ref = someMethod;
 * </pre>
 */
public static JCExpression methodReference(CeylonTransformer gen, final Tree.StaticMemberOrTypeExpression forwardCallTo, ParameterList parameterList, Type expectedType, Type callableType, boolean useParameterTypesFromCallableModel) {
    ListBuffer<JCStatement> letStmts = new ListBuffer<JCStatement>();
    CallableBuilder cb = new CallableBuilder(gen, forwardCallTo, callableType, parameterList);
    cb.parameterTypes = useParameterTypesFromCallableModel ? cb.getParameterTypesFromCallableModel() : cb.getParameterTypesFromParameterModels();
    Naming.SyntheticName instanceFieldName;
    boolean instanceFieldIsBoxed = false;
    if (forwardCallTo instanceof Tree.QualifiedMemberOrTypeExpression && !ExpressionTransformer.isSuperOrSuperOf(((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getPrimary()) && !ExpressionTransformer.isPackageQualified((Tree.QualifiedMemberOrTypeExpression) forwardCallTo)) {
        if ((((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getMemberOperator() instanceof Tree.SpreadOp)) {
            instanceFieldIsBoxed = true;
            instanceFieldName = null;
        } else {
            Tree.QualifiedMemberOrTypeExpression qmte = (Tree.QualifiedMemberOrTypeExpression) forwardCallTo;
            boolean prevCallableInv = gen.expressionGen().withinSyntheticClassBody(true);
            try {
                instanceFieldName = gen.naming.synthetic(Unfix.$instance$);
                int varTypeFlags = Decl.isPrivateAccessRequiringCompanion(qmte) ? JT_COMPANION : 0;
                Type primaryType;
                if (Decl.isValueTypeDecl(qmte.getPrimary().getTypeModel())) {
                    primaryType = qmte.getPrimary().getTypeModel();
                } else {
                    primaryType = qmte.getTarget().getQualifyingType();
                }
                if (((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getMemberOperator() instanceof Tree.SafeMemberOp) {
                    primaryType = gen.typeFact().getOptionalType(primaryType);
                }
                JCExpression primaryExpr = gen.expressionGen().transformQualifiedMemberPrimary(qmte);
                Declaration dec = qmte.getDeclaration();
                if (Decl.isPrivateAccessRequiringCompanion(qmte)) {
                    primaryExpr = gen.naming.makeCompanionAccessorCall(primaryExpr, (Interface) dec.getContainer());
                }
                Type varType = dec.isShared() ? primaryType : Decl.getPrivateAccessType(qmte);
                if (qmte.getPrimary().getUnboxed() == false) {
                    varTypeFlags |= JT_NO_PRIMITIVES;
                    instanceFieldIsBoxed = true;
                }
                letStmts.add(gen.makeVar(Flags.FINAL, instanceFieldName, gen.makeJavaType(varType, varTypeFlags), primaryExpr));
                if (qmte.getPrimary() instanceof Tree.MemberOrTypeExpression && ((Tree.MemberOrTypeExpression) qmte.getPrimary()).getDeclaration() instanceof TypedDeclaration) {
                    cb.instanceSubstitution = gen.naming.addVariableSubst((TypedDeclaration) ((Tree.MemberOrTypeExpression) qmte.getPrimary()).getDeclaration(), instanceFieldName.getName());
                }
            } finally {
                gen.expressionGen().withinSyntheticClassBody(prevCallableInv);
            }
        }
    } else {
        instanceFieldName = null;
    }
    CallableTransformation tx;
    cb.defaultValueCall = new DefaultValueMethodTransformation() {

        @Override
        public JCExpression makeDefaultValueMethod(AbstractTransformer gen, Parameter defaultedParam, List<JCExpression> defaultMethodArgs) {
            JCExpression fn = null;
            if (forwardCallTo instanceof Tree.BaseMemberOrTypeExpression) {
                fn = gen.naming.makeDefaultedParamMethod(null, defaultedParam);
            } else if (forwardCallTo instanceof Tree.QualifiedMemberOrTypeExpression) {
                JCExpression qualifier = gen.expressionGen().transformTermForInvocation(((Tree.QualifiedMemberOrTypeExpression) forwardCallTo).getPrimary(), null);
                fn = gen.naming.makeDefaultedParamMethod(qualifier, defaultedParam);
            }
            return gen.make().Apply(null, fn, defaultMethodArgs);
        }
    };
    if (cb.isVariadic) {
        tx = cb.new VariadicCallableTransformation(cb.new CallMethodWithForwardedBody(instanceFieldName, instanceFieldIsBoxed, forwardCallTo, false, callableType));
    } else {
        tx = cb.new FixedArityCallableTransformation(cb.new CallMethodWithForwardedBody(instanceFieldName, instanceFieldIsBoxed, forwardCallTo, true, callableType), null);
    }
    cb.useTransformation(tx);
    cb.checkForFunctionalInterface(expectedType);
    return letStmts.isEmpty() ? cb.build() : gen.make().LetExpr(letStmts.toList(), cb.build());
}
Also used : ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) QualifiedMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberOrTypeExpression) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) QualifiedMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberOrTypeExpression) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) QualifiedMemberOrTypeExpression(org.eclipse.ceylon.compiler.typechecker.tree.Tree.QualifiedMemberOrTypeExpression) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) JCTypeParameter(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter) SyntheticName(org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName) Interface(org.eclipse.ceylon.model.typechecker.model.Interface)

Example 13 with ListBuffer

use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.

the class AnnotationInvocation method makeAnnotation.

public JCExpression makeAnnotation(ExpressionTransformer exprGen, AnnotationInvocation ai, org.eclipse.ceylon.langtools.tools.javac.util.List<AnnotationFieldName> parameterPath) {
    ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
    for (AnnotationArgument aa : getAnnotationArguments()) {
        Parameter name = aa.getParameter();
        if (!isInstantiation()) {
            AnnotationInvocation annotationInvocation = (AnnotationInvocation) getConstructorDeclaration().getAnnotationConstructor();
            for (AnnotationArgument a2 : annotationInvocation.getAnnotationArguments()) {
                if (a2.getTerm() instanceof ParameterAnnotationTerm) {
                    if (((ParameterAnnotationTerm) a2.getTerm()).getSourceParameter().equals(aa.getParameter())) {
                        name = a2.getParameter();
                        break;
                    }
                }
            }
        }
        args.append(makeAnnotationArgument(exprGen, ai, name, parameterPath.append(aa), aa.getTerm()));
    }
    return exprGen.make().Annotation(makeAnnotationType(exprGen), args.toList());
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter)

Example 14 with ListBuffer

use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.

the class AnnotationInvocationVisitor method transformConstructor.

private static JCAnnotation transformConstructor(ExpressionTransformer exprGen, Tree.InvocationExpression invocation, AnnotationInvocation ai, org.eclipse.ceylon.langtools.tools.javac.util.List<AnnotationFieldName> fieldPath) {
    Map<Parameter, ListBuffer<JCExpression>> args = new LinkedHashMap<Parameter, ListBuffer<JCExpression>>();
    List<Parameter> classParameters = ai.getClassParameters();
    // The class parameter's we've not yet figured out the value for
    ArrayList<Parameter> unbound = new ArrayList<Parameter>(classParameters);
    for (Parameter classParameter : classParameters) {
        for (AnnotationArgument argument : ai.findAnnotationArgumentForClassParameter(invocation, new HashSet<Function>(), classParameter)) {
            JCExpression expr = transformConstructorArgument(exprGen, invocation, classParameter, argument, fieldPath);
            appendArgument(args, classParameter, expr);
            unbound.remove(classParameter);
        }
    }
    outer: for (Parameter classParameter : new ArrayList<>(unbound)) {
        // 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, org.eclipse.ceylon.langtools.tools.javac.util.List.<AnnotationFieldName>of(aa)));
                    unbound.remove(classParameter);
                    continue outer;
                }
            }
        }
        if (Strategy.hasEmptyDefaultArgument(classParameter)) {
            appendArgument(args, classParameter, exprGen.make().NewArray(null, null, org.eclipse.ceylon.langtools.tools.javac.util.List.<JCExpression>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<JCExpression> assignments = new ListBuffer<JCExpression>();
    for (Map.Entry<Parameter, ListBuffer<JCExpression>> entry : args.entrySet()) {
        ListBuffer<JCExpression> 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;
}
Also used : ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Function(org.eclipse.ceylon.model.typechecker.model.Function) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) JCAnnotation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation)

Example 15 with ListBuffer

use of org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer in project ceylon by eclipse.

the class ClassTransformer method makeArrayInitializer.

/**
 * Makes a new Array expression suitable for use in initializing a Java array
 * using as elements the positional arguments
 * of the given {@link Tree.SequencedArgument} (which must
 * be {@link Tree.ListedArgument}s).
 *
 * <pre>
 *     Whatever[] w = <strong>{ listedArg1, listedArg2, ... }</strong>
 *     //             ^---------- this bit ---------^
 * </pre>
 *
 * @param sequencedArgument
 * @return The array initializer expression
 */
JCExpression makeArrayInitializer(Tree.SequencedArgument sequencedArgument) {
    JCExpression defaultLiteral;
    ListBuffer<JCExpression> elements = new ListBuffer<JCExpression>();
    if (sequencedArgument != null) {
        for (Tree.PositionalArgument arg : sequencedArgument.getPositionalArguments()) {
            if (arg instanceof Tree.ListedArgument) {
                Tree.ListedArgument la = (Tree.ListedArgument) arg;
                elements.append(expressionGen().transformExpression(la.getExpression().getTerm(), BoxingStrategy.UNBOXED, la.getExpression().getTypeModel()));
            } else {
                elements = null;
                break;
            }
        }
    }
    defaultLiteral = elements == null ? null : make().NewArray(null, List.<JCExpression>nil(), elements.toList());
    return defaultLiteral;
}
Also used : JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCPrimitiveTypeTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Aggregations

ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)67 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)53 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)30 Type (org.eclipse.ceylon.model.typechecker.model.Type)23 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)22 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)20 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)16 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)16 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)15 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)14 JCAnnotation (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation)13 JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)12 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)12 SyntheticName (org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)11 Function (org.eclipse.ceylon.model.typechecker.model.Function)10 Class (org.eclipse.ceylon.model.typechecker.model.Class)9 JCTypeParameter (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter)8 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)8 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)8 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)7