Search in sources :

Example 1 with FieldValue

use of org.eclipse.ceylon.model.loader.model.FieldValue in project ceylon by eclipse.

the class ExpressionTransformer method transformMemberReference.

JCExpression transformMemberReference(Tree.QualifiedMemberOrTypeExpression expr, Tree.MemberOrTypeExpression primary) {
    Declaration member = expr.getDeclaration();
    Type qualifyingType = primary.getTypeModel();
    Tree.TypeArguments typeArguments = expr.getTypeArguments();
    Type expectedTypeIfCoerced = coerced ? expectedType : null;
    boolean prevSyntheticClassBody = withinSyntheticClassBody(true);
    try {
        if (member.isStatic()) {
            if (member instanceof Function) {
                Function method = (Function) member;
                // method.appliedReference(qualifyingType, typeArguments.getTypeModels());
                Reference producedReference = expr.getTarget();
                return CallableBuilder.javaStaticMethodReference(gen(), expr, expr.getTypeModel(), method, producedReference, expectedTypeIfCoerced).build();
            } else if (member instanceof FieldValue) {
                return naming.makeName((TypedDeclaration) member, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED);
            } else if (member instanceof Value) {
                CallBuilder callBuilder = CallBuilder.instance(this);
                JCExpression qualExpr = naming.makeTypeDeclarationExpression(null, (TypeDeclaration) member.getContainer(), DeclNameFlag.QUALIFIED);
                Type primType = primary.getTarget().getType();
                if (ModelUtil.isCeylonDeclaration(member) && !primType.getTypeArgumentList().isEmpty()) {
                    for (Type pt : primType.getTypeArgumentList()) {
                        callBuilder.typeArgument(makeJavaType(pt, JT_TYPE_ARGUMENT));
                        callBuilder.argument(makeReifiedTypeArgument(pt));
                    }
                }
                callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
                return callBuilder.build();
            } else if (member instanceof Class) {
                Reference producedReference = expr.getTarget();
                return CallableBuilder.javaStaticMethodReference(gen(), expr, expr.getTypeModel(), (Class) member, producedReference, expectedTypeIfCoerced).build();
            }
        }
        if (member instanceof Value) {
            if (expr.getStaticMethodReference() && ModelUtil.isEnumeratedConstructor((Value) member)) {
                CallBuilder callBuilder = CallBuilder.instance(this);
                JCExpression qualExpr;
                Class class1 = (Class) member.getContainer();
                if (class1.isToplevel() || class1.isStatic()) {
                    qualExpr = naming.makeTypeDeclarationExpression(null, class1.isStatic() ? (TypeDeclaration) class1.getContainer() : class1, DeclNameFlag.QUALIFIED);
                    callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
                } else if (class1.isMember()) {
                    // creates a Callable<Outer.Inner,[Outer]> that returns the enumeratedConstructor given an outer instance
                    if (primary instanceof Tree.QualifiedMemberOrTypeExpression && (((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary() instanceof Tree.BaseTypeExpression || ((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary() instanceof Tree.QualifiedTypeExpression))
                        return CallableBuilder.unboundValueMemberReference(gen(), expr, expr.getTypeModel(), ((TypedDeclaration) member), expectedTypeIfCoerced).build();
                    else {
                        qualExpr = primary instanceof Tree.QualifiedMemberOrTypeExpression ? transformExpression(((Tree.QualifiedMemberOrTypeExpression) primary).getPrimary()) : null;
                        callBuilder.invoke(naming.makeQualifiedName(qualExpr, (TypedDeclaration) member, Naming.NA_GETTER | Naming.NA_MEMBER));
                    }
                } else {
                    // Local enumerated constructor values are boxed
                    qualExpr = naming.makeQualifiedName(null, (TypedDeclaration) member, Naming.NA_Q_LOCAL_INSTANCE);
                    qualExpr = gen().makeSelect(qualExpr, naming.selector((TypedDeclaration) member));
                    callBuilder.fieldRead(qualExpr);
                }
                return callBuilder.build();
            } else {
                return CallableBuilder.unboundValueMemberReference(gen(), expr, expr.getTypeModel(), ((TypedDeclaration) member), expectedTypeIfCoerced).build();
            }
        } else if (Decl.isConstructor(member)) {
            Reference producedReference = expr.getTarget();
            return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), ModelUtil.getConstructor(member), producedReference, expectedTypeIfCoerced);
        } else if (member instanceof Function) {
            Function method = (Function) member;
            if (!method.isParameter()) {
                Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
                return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), method, producedReference, expectedTypeIfCoerced);
            } else {
                Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
                return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), method, producedReference, expectedTypeIfCoerced);
            }
        } else if (member instanceof Class) {
            Reference producedReference = expr.getTarget();
            return CallableBuilder.unboundFunctionalMemberReference(gen(), expr, expr.getTypeModel(), (Class) member, producedReference, expectedTypeIfCoerced);
        } else {
            return makeErroneous(expr, "compiler bug: member reference of " + expr + " not supported yet");
        }
    } finally {
        withinSyntheticClassBody(prevSyntheticClassBody);
    }
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) Function(org.eclipse.ceylon.model.typechecker.model.Function) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) Value(org.eclipse.ceylon.model.typechecker.model.Value) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue)

Example 2 with FieldValue

use of org.eclipse.ceylon.model.loader.model.FieldValue in project ceylon by eclipse.

the class ExpressionTransformer method transformJavaStaticOrInterfaceMember.

private JCExpression transformJavaStaticOrInterfaceMember(Tree.QualifiedMemberOrTypeExpression qmte, Type staticType) {
    Declaration decl = qmte.getDeclaration();
    if (decl instanceof FieldValue) {
        Value member = (Value) decl;
        return naming.makeName(member, Naming.NA_FQ | Naming.NA_WRAPPER_UNQUOTED);
    } else if (decl instanceof Value) {
        Value member = (Value) decl;
        CallBuilder callBuilder = CallBuilder.instance(this);
        Type qualifyingType = ((TypeDeclaration) member.getContainer()).getType();
        callBuilder.invoke(naming.makeQualifiedName(makeJavaType(qualifyingType, JT_RAW | JT_NO_PRIMITIVES), member, Naming.NA_GETTER | Naming.NA_MEMBER));
        return utilInvocation().checkNull(callBuilder.build());
    } else if (decl instanceof Function) {
        Function method = (Function) decl;
        final ParameterList parameterList = method.getFirstParameterList();
        Type qualifyingType = qmte.getPrimary().getTypeModel();
        Tree.TypeArguments typeArguments = qmte.getTypeArguments();
        Reference producedReference = method.appliedReference(qualifyingType, typeArguments.getTypeModels());
        return utilInvocation().checkNull(makeJavaStaticInvocation(gen(), method, producedReference, parameterList));
    } else if (decl instanceof Class) {
        Class class_ = (Class) decl;
        if (class_.isStatic()) {
            return naming.makeTypeDeclarationExpression(null, class_, Naming.DeclNameFlag.QUALIFIED);
        } else {
            final ParameterList parameterList = class_.getFirstParameterList();
            Reference producedReference = qmte.getTarget();
            return utilInvocation().checkNull(makeJavaStaticInvocation(gen(), class_, producedReference, parameterList));
        }
    } else if (decl instanceof Interface) {
        return naming.makeTypeDeclarationExpression(null, (Interface) decl, Naming.DeclNameFlag.QUALIFIED);
    } else {
        return makeErroneous(qmte, "compiler bug: unsupported static");
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) Value(org.eclipse.ceylon.model.typechecker.model.Value) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface)

Example 3 with FieldValue

use of org.eclipse.ceylon.model.loader.model.FieldValue in project ceylon by eclipse.

the class AbstractModelLoader method setCaseTypes.

private void setCaseTypes(ClassOrInterface klass, ClassMirror classMirror) {
    if (classMirror.isEnum()) {
        ArrayList<Type> caseTypes = new ArrayList<Type>();
        for (Declaration member : klass.getMembers()) {
            if (member instanceof FieldValue && ((FieldValue) member).isEnumValue()) {
                caseTypes.add(((FieldValue) member).getType());
            }
        }
        klass.setCaseTypes(caseTypes);
    } else {
        String selfType = getSelfTypeFromAnnotations(classMirror);
        Module moduleScope = ModelUtil.getModuleContainer(klass);
        if (selfType != null && !selfType.isEmpty()) {
            Type type = decodeType(selfType, klass, moduleScope, "self type");
            if (!type.isTypeParameter()) {
                logError("Invalid type signature for self type of " + klass.getQualifiedNameString() + ": " + selfType + " is not a type parameter");
            } else {
                klass.setSelfType(type);
                List<Type> caseTypes = new LinkedList<Type>();
                caseTypes.add(type);
                klass.setCaseTypes(caseTypes);
            }
        } else {
            List<String> caseTypes = getCaseTypesFromAnnotations(classMirror);
            if (caseTypes != null && !caseTypes.isEmpty()) {
                klass.setCaseTypes(getTypesList(caseTypes, klass, moduleScope, "case types", klass.getQualifiedNameString()));
            }
        }
    }
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) ArrayList(java.util.ArrayList) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) Module(org.eclipse.ceylon.model.typechecker.model.Module) LazyModule(org.eclipse.ceylon.model.loader.model.LazyModule) LinkedList(java.util.LinkedList)

Example 4 with FieldValue

use of org.eclipse.ceylon.model.loader.model.FieldValue in project ceylon by eclipse.

the class AbstractModelLoader method addValue.

private Value addValue(ClassOrInterface klass, String ceylonName, FieldMirror fieldMirror, boolean isCeylon, boolean isNativeHeader) {
    // make sure it's a FieldValue so we can figure it out in the backend
    Value value = new FieldValue(fieldMirror.getName());
    value.setContainer(klass);
    value.setScope(klass);
    // use the name annotation if present (used by Java arrays)
    String nameAnnotation = getAnnotationStringValue(fieldMirror, CEYLON_NAME_ANNOTATION);
    value.setName(nameAnnotation != null ? nameAnnotation : ceylonName);
    value.setUnit(klass.getUnit());
    value.setShared(fieldMirror.isPublic() || fieldMirror.isProtected() || fieldMirror.isDefaultAccess());
    value.setProtectedVisibility(fieldMirror.isProtected());
    value.setPackageVisibility(fieldMirror.isDefaultAccess());
    value.setStatic(fieldMirror.isStatic());
    setDeclarationAliases(value, fieldMirror);
    setDeclarationRestrictions(value, fieldMirror);
    // field can't be abstract or interface, so not formal
    // can we override fields? good question. Not really, but from an external point of view?
    // FIXME: figure this out: (default)
    // FIXME: for the same reason, can it be an overriding field? (actual)
    value.setVariable(!fieldMirror.isFinal());
    // figure out if it's an enum subtype in a final static field
    if (fieldMirror.getType().getKind() == TypeKind.DECLARED && fieldMirror.getType().getDeclaredClass() != null && fieldMirror.getType().getDeclaredClass().isEnum() && fieldMirror.isFinal() && fieldMirror.isStatic())
        value.setEnumValue(true);
    Module module = ModelUtil.getModuleContainer(klass);
    Type type = obtainType(fieldMirror.getType(), fieldMirror, klass, module, "field '" + value.getName() + "'", klass);
    if (type.isCached()) {
        type = type.clone();
    }
    if (value.isEnumValue()) {
        Constructor enumValueType = new Constructor();
        enumValueType.setJavaEnum(true);
        enumValueType.setExtendedType(type);
        Scope scope = value.getContainer();
        enumValueType.setContainer(scope);
        enumValueType.setScope(scope);
        enumValueType.setDeprecated(value.isDeprecated());
        enumValueType.setName(value.getName());
        enumValueType.setUnit(value.getUnit());
        enumValueType.setStatic(value.isStatic());
        value.setType(enumValueType.getType());
        value.setUncheckedNullType(false);
    } else {
        NullStatus nullPolicy = getUncheckedNullPolicy(isCeylon, fieldMirror.getType(), fieldMirror);
        switch(nullPolicy) {
            case Optional:
                if (!isCeylon) {
                    type = makeOptionalTypePreserveUnderlyingType(type, module);
                }
                break;
            case UncheckedNull:
                value.setUncheckedNullType(true);
                break;
        }
        value.setType(type);
    }
    type.setRaw(isRaw(module, fieldMirror.getType()));
    markUnboxed(value, null, fieldMirror.getType());
    markSmall(value, fieldMirror.getType());
    markTypeErased(value, fieldMirror, fieldMirror.getType());
    markUntrustedType(value, fieldMirror, fieldMirror.getType());
    value.setDeprecated(isDeprecated(fieldMirror));
    setAnnotations(value, fieldMirror, isNativeHeader);
    klass.addMember(value);
    ModelUtil.setVisibleScope(value);
    return value;
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) JavaParameterValue(org.eclipse.ceylon.model.loader.model.JavaParameterValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) LazyValue(org.eclipse.ceylon.model.loader.model.LazyValue) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JavaBeanValue(org.eclipse.ceylon.model.loader.model.JavaBeanValue) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) Module(org.eclipse.ceylon.model.typechecker.model.Module) LazyModule(org.eclipse.ceylon.model.loader.model.LazyModule)

Example 5 with FieldValue

use of org.eclipse.ceylon.model.loader.model.FieldValue in project ceylon by eclipse.

the class ValueImpl method initField.

private void initField(Object instance, Type valueType) {
    org.eclipse.ceylon.model.typechecker.model.Value decl = (org.eclipse.ceylon.model.typechecker.model.Value) declaration.declaration;
    String name = decl.getName();
    if (decl instanceof JavaBeanValue) {
        java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
        if (javaClass == ceylon.language.Object.class || javaClass == ceylon.language.Basic.class || javaClass == ceylon.language.Identifiable.class) {
            if ("string".equals(name) || "hash".equals(name)) {
                // look it up on j.l.Object, getterName should work
                javaClass = java.lang.Object.class;
            } else {
                throw Metamodel.newModelError("Object/Basic/Identifiable member not supported: " + name);
            }
        } else if (javaClass == ceylon.language.Throwable.class) {
            if ("cause".equals(name) || "message".equals(name) || "suppressed".equals(name)) {
                javaClass = instance.getClass();
                isSuppressed = "suppressed".equals(name);
            }
        }
        String getterName = ((JavaBeanValue) decl).getGetterName();
        try {
            Class<?>[] params;
            if (!declaration.getStatic()) {
                params = NO_PARAMS;
            } else {
                int numCapturedTypeParams = ((ClassOrInterface) declaration.declaration.getContainer()).getTypeParameters().size();
                params = new Class[numCapturedTypeParams];
                Arrays.fill(params, TypeDescriptor.class);
            }
            boolean isJavaArray = MethodHandleUtil.isJavaArray(javaClass);
            if (isJavaArray)
                params = MethodHandleUtil.getJavaArrayGetArrayParameterTypes(javaClass, getterName);
            // if it is shared we may want to get an inherited getter, but if it's private we need the declared method to return it
            Method m = decl.isShared() ? javaClass.getMethod(getterName, params) : javaClass.getDeclaredMethod(getterName, params);
            m.setAccessible(true);
            getter = MethodHandles.lookup().unreflect(m);
            java.lang.Class<?> getterType = m.getReturnType();
            getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
            if (instance != null && // XXXArray.getArray is static but requires an instance as first param
            (isJavaArray || !Modifier.isStatic(m.getModifiers()))) {
                getter = getter.bindTo(instance);
            }
            if (declaration.getStatic()) {
                getter = getter.asType(MethodType.methodType(Object.class, params));
                TypeDescriptor[] typeArguments = ((TypeDescriptor.Class) ((ClassOrInterfaceImpl<?>) container).$reifiedType).getTypeArguments();
                getter = getter.asSpreader(TypeDescriptor[].class, typeArguments.length);
                getter = getter.bindTo(typeArguments);
            } else {
                // we need to cast to Object because this is what comes out when calling it in $call
                getter = getter.asType(MethodType.methodType(Object.class));
            }
            initSetter(decl, javaClass, getterType, instance, valueType);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
            throw Metamodel.newModelError("Failed to find getter method " + getterName + " for: " + decl, e);
        }
    } else if (decl instanceof LazyValue) {
        LazyValue lazyDecl = (LazyValue) decl;
        java.lang.Class<?> javaClass = ((ReflectionClass) lazyDecl.classMirror).klass;
        // FIXME: we should really save the getter name in the LazyDecl
        String getterName = NamingBase.getGetterName(lazyDecl);
        try {
            // toplevels don't have inheritance
            Method m = javaClass.getDeclaredMethod(getterName);
            m.setAccessible(true);
            getter = MethodHandles.lookup().unreflect(m);
            java.lang.Class<?> getterType = m.getReturnType();
            getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
            // we need to cast to Object because this is what comes out when calling it in $call
            getter = getter.asType(MethodType.methodType(Object.class));
            initSetter(decl, javaClass, getterType, null, valueType);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
            throw Metamodel.newModelError("Failed to find getter method " + getterName + " for: " + decl, e);
        }
    } else if (decl instanceof FieldValue) {
        FieldValue fieldDecl = (FieldValue) decl;
        java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
        String fieldName = fieldDecl.getRealName();
        if (MethodHandleUtil.isJavaArray(javaClass)) {
            try {
                Method method = Array.class.getDeclaredMethod("getLength", Object.class);
                getter = MethodHandles.lookup().unreflect(method);
                java.lang.Class<?> getterType = method.getReturnType();
                getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
                // this one is static but requires an instance a first param
                if (instance != null)
                    getter = getter.bindTo(instance);
                // we need to cast to Object because this is what comes out when calling it in $call
                getter = getter.asType(MethodType.methodType(Object.class));
            } catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
                throw Metamodel.newModelError("Failed to find Array.getLength method for: " + decl, e);
            }
        } else {
            try {
                // fields are not inherited
                Field f = javaClass.getDeclaredField(fieldName);
                f.setAccessible(true);
                getter = MethodHandles.lookup().unreflectGetter(f);
                java.lang.Class<?> getterType = f.getType();
                getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
                if (instance != null && !Modifier.isStatic(f.getModifiers()))
                    getter = getter.bindTo(instance);
                // we need to cast to Object because this is what comes out when calling it in $call
                getter = getter.asType(MethodType.methodType(Object.class));
                initSetter(decl, javaClass, getterType, instance, valueType);
            } catch (NoSuchFieldException | SecurityException | IllegalAccessException e) {
                throw Metamodel.newModelError("Failed to find field " + fieldName + " for: " + decl, e);
            }
        }
    } else if (ModelUtil.isEnumeratedConstructor(decl)) {
        java.lang.Class<?> javaClass = Metamodel.getJavaClass((org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) decl.getContainer());
        String getterName = NamingBase.getGetterName(decl);
        try {
            Class<?>[] params = NO_PARAMS;
            // if it is shared we may want to get an inherited getter, but if it's private we need the declared method to return it
            Method m = decl.isShared() ? javaClass.getMethod(getterName, params) : javaClass.getDeclaredMethod(getterName, params);
            m.setAccessible(true);
            getter = MethodHandles.lookup().unreflect(m);
            java.lang.Class<?> getterType = m.getReturnType();
            getter = MethodHandleUtil.boxReturnValue(getter, getterType, valueType);
            if (instance != null && // XXXArray.getArray is static but requires an instance as first param
            (!Modifier.isStatic(m.getModifiers()))) {
                getter = getter.bindTo(instance);
            }
            // we need to cast to Object because this is what comes out when calling it in $call
            getter = getter.asType(MethodType.methodType(Object.class));
            initSetter(decl, javaClass, getterType, instance, valueType);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException e) {
            throw Metamodel.newModelError("Failed to find getter method " + getterName + " for: " + decl, e);
        }
    } else
        throw new StorageException("Attribute " + name + " is neither captured nor shared so it has no physical storage allocated and cannot be read by the metamodel");
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyValue(org.eclipse.ceylon.model.loader.model.LazyValue) Field(java.lang.reflect.Field) Metamodel(org.eclipse.ceylon.compiler.java.runtime.metamodel.Metamodel) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) Method(java.lang.reflect.Method) TypeDescriptor(org.eclipse.ceylon.compiler.java.runtime.model.TypeDescriptor) LazyValue(org.eclipse.ceylon.model.loader.model.LazyValue) JavaBeanValue(org.eclipse.ceylon.model.loader.model.JavaBeanValue) FieldValue(org.eclipse.ceylon.model.loader.model.FieldValue) ReflectionClass(org.eclipse.ceylon.model.loader.impl.reflect.mirror.ReflectionClass) JavaBeanValue(org.eclipse.ceylon.model.loader.model.JavaBeanValue) StorageException(ceylon.language.meta.model.StorageException)

Aggregations

FieldValue (org.eclipse.ceylon.model.loader.model.FieldValue)11 Type (org.eclipse.ceylon.model.typechecker.model.Type)7 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)7 Value (org.eclipse.ceylon.model.typechecker.model.Value)7 JavaBeanValue (org.eclipse.ceylon.model.loader.model.JavaBeanValue)6 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)6 Class (org.eclipse.ceylon.model.typechecker.model.Class)5 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)5 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)5 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)3 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)3 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)3 JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)3 LazyValue (org.eclipse.ceylon.model.loader.model.LazyValue)3 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)3 Function (org.eclipse.ceylon.model.typechecker.model.Function)3 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)3 Field (java.lang.reflect.Field)2 Method (java.lang.reflect.Method)2 JvmBackendUtil.isValue (org.eclipse.ceylon.model.loader.JvmBackendUtil.isValue)2