Search in sources :

Example 6 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class AbstractModelLoader method applyTypeCoercion.

private Type applyTypeCoercion(TypeMirror type, AnnotatedMirror annotatedMirror, MethodMirror methodMirror, String paramName, Declaration decl, Module module, Scope scope) {
    if (sameType(type, CHAR_SEQUENCE_TYPE))
        return typeFactory.getStringType();
    if (sameType(type, CLASS_TYPE)) {
        // It's much easier to obtain the java.lang.Class<...> type and extract its TP than
        // just obtain its TP, because wildcards are dealt with in obtainTypeArguments, not
        // for "toplevel" wildcards
        Type classType = obtainType(type, annotatedMirror, scope, module, "parameter '" + paramName + "' of method '" + methodMirror.getName() + "'", (Declaration) decl);
        // gracefully give up with the original type in case of errors
        if (classType.isUnknown() || classType.getTypeArgumentList().isEmpty())
            return classType;
        return typeFactory.getClassOrInterfaceModelType(classType.getTypeArgumentList().get(0));
    }
    if (type.getKind() == TypeKind.ARRAY) {
        TypeDeclaration ad = typeFactory.getArrayDeclaration();
        TypeMirror elementType = type.getComponentType();
        switch(elementType.getKind()) {
            case LONG:
                return ad.appliedType(null, Arrays.asList(typeFactory.getIntegerType()));
            case DOUBLE:
                return ad.appliedType(null, Arrays.asList(typeFactory.getFloatType()));
            case BOOLEAN:
                return ad.appliedType(null, Arrays.asList(typeFactory.getBooleanType()));
            case BYTE:
                return ad.appliedType(null, Arrays.asList(typeFactory.getByteType()));
            case DECLARED:
            case TYPEVAR:
                Type elemType = obtainType(module, elementType, scope, TypeLocation.TYPE_PARAM);
                return ad.appliedType(null, Arrays.asList(typeFactory.getOptionalType(elemType)));
            // impossible!
            default:
        }
    }
    return getFunctionalInterfaceAsCallable(module, scope, type);
}
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) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 7 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class AbstractModelLoader method loadFunctionCoercionParameter.

@SuppressWarnings("incomplete-switch")
private Function loadFunctionCoercionParameter(Declaration decl, String paramName, TypeMirror typeMirror, Module moduleScope, Scope scope) {
    Function method = new Function();
    method.setName(paramName);
    method.setUnit(decl.getUnit());
    try {
        FunctionalInterfaceType functionalInterfaceType = getFunctionalInterfaceType(typeMirror);
        MethodMirror functionalMethod = functionalInterfaceType.getMethod();
        Type returnType = obtainType(moduleScope, functionalInterfaceType.getReturnType(), scope, TypeLocation.TOPLEVEL);
        switch(getUncheckedNullPolicy(false, functionalInterfaceType.getReturnType(), functionalMethod)) {
            case Optional:
            case UncheckedNull:
                returnType = makeOptionalTypePreserveUnderlyingType(returnType, moduleScope);
                break;
        }
        method.setType(returnType);
        ParameterList pl = new ParameterList();
        // List<VariableMirror> functionalParameters = functionalMethod.getParameters();
        List<TypeMirror> parameterTypes = functionalInterfaceType.getParameterTypes();
        Map<String, Integer> used = new HashMap<String, Integer>();
        for (TypeMirror parameterType : parameterTypes) {
            String name;
            if (parameterTypes.size() == 1) {
                name = "it";
            } else {
                switch(parameterType.getKind()) {
                    case ARRAY:
                        name = "array";
                        break;
                    case BOOLEAN:
                        name = "boolean";
                        break;
                    case CHAR:
                        name = "character";
                        break;
                    case BYTE:
                        name = "byte";
                        break;
                    case INT:
                    case LONG:
                    case SHORT:
                        name = "integer";
                        break;
                    case FLOAT:
                    case DOUBLE:
                        name = "float";
                        break;
                    case DECLARED:
                        String typeName = parameterType.getDeclaredClass().getName();
                        int first = typeName.codePointAt(0);
                        name = String.valueOf(Character.toChars(Character.toLowerCase(first))) + typeName.substring(Character.charCount(first));
                        break;
                    default:
                        name = "arg";
                }
                Integer count = used.get(name);
                if (count == null) {
                    used.put(name, 1);
                } else {
                    int next = count + 1;
                    used.put(name, next);
                    name += next;
                }
            }
            Type modelParameterType = obtainType(moduleScope, parameterType, scope, TypeLocation.TOPLEVEL);
            Parameter p = new Parameter();
            Value v = new Value();
            p.setName(name);
            v.setName(name);
            v.setContainer(method);
            v.setScope(method);
            p.setModel(v);
            v.setInitializerParameter(p);
            // Java parameters are all optional unless primitives or annotated as such
            switch(getUncheckedNullPolicy(false, parameterType, functionalMethod)) {
                case Optional:
                    modelParameterType = makeOptionalTypePreserveUnderlyingType(modelParameterType, moduleScope);
                    break;
                case UncheckedNull:
                    v.setUncheckedNullType(true);
                    break;
            }
            v.setType(modelParameterType);
            pl.getParameters().add(p);
            method.addMember(v);
        }
        method.addParameterList(pl);
    } catch (ModelResolutionException x) {
        method.setType(logModelResolutionException(x, scope, "Failure to turn functional interface to Callable type"));
    }
    return method;
}
Also used : FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Function(org.eclipse.ceylon.model.typechecker.model.Function) LazyFunction(org.eclipse.ceylon.model.loader.model.LazyFunction) MethodMirror(org.eclipse.ceylon.model.loader.mirror.MethodMirror) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) 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) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter)

Example 8 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class AbstractModelLoader method setParameters.

private void setParameters(Functional decl, ClassMirror classMirror, MethodMirror methodMirror, boolean isCeylon, Scope container, boolean isCoercedMethod) {
    ParameterList parameters = new ParameterList();
    parameters.setNamedParametersSupported(isCeylon);
    decl.addParameterList(parameters);
    int parameterCount = methodMirror.getParameters().size();
    int parameterIndex = 0;
    for (VariableMirror paramMirror : methodMirror.getParameters()) {
        // ignore some parameters
        if (paramMirror.getAnnotation(CEYLON_IGNORE_ANNOTATION) != null)
            continue;
        boolean isLastParameter = parameterIndex == parameterCount - 1;
        boolean isVariadic = isLastParameter && methodMirror.isVariadic();
        String paramName = getAnnotationStringValue(paramMirror, CEYLON_NAME_ANNOTATION);
        // use whatever param name we find as default
        if (paramName == null)
            paramName = paramMirror.getName();
        Parameter parameter = new Parameter();
        parameter.setName(paramName);
        TypeMirror typeMirror = paramMirror.getType();
        Scope scope = (Scope) decl;
        Module module = ModelUtil.getModuleContainer(scope);
        Type type;
        boolean coercedParameter = false;
        if (isVariadic) {
            // possibly make it optional
            TypeMirror variadicType = typeMirror.getComponentType();
            // we pretend it's toplevel because we want to get magic string conversion for variadic methods
            if (isCoercedMethod && isCoercedType(variadicType)) {
                type = applyTypeCoercion(variadicType, paramMirror, methodMirror, paramName, (Declaration) decl, module, scope);
                coercedParameter = true;
            } else {
                type = obtainType(module, variadicType, scope, TypeLocation.TOPLEVEL);
            }
            if (!isCeylon) {
                // Java parameters are all optional unless primitives or annotated as such
                if (getUncheckedNullPolicy(isCeylon, variadicType, paramMirror) != NullStatus.NonOptional) {
                    type = makeOptionalTypePreserveUnderlyingType(type, module);
                }
            }
            // turn it into a Sequential<T>
            type = typeFactory.getSequentialType(type);
        } else {
            if (isCoercedMethod && isCoercedType(typeMirror)) {
                type = applyTypeCoercion(typeMirror, paramMirror, methodMirror, paramName, (Declaration) decl, module, scope);
                coercedParameter = true;
            } else {
                type = obtainType(typeMirror, paramMirror, scope, module, "parameter '" + paramName + "' of method '" + methodMirror.getName() + "'", (Declaration) decl);
            }
            if (!isCeylon) {
                // Java parameters are all optional unless primitives or annotated as such
                if (getUncheckedNullPolicy(isCeylon, typeMirror, paramMirror) != NullStatus.NonOptional) {
                    type = makeOptionalTypePreserveUnderlyingType(type, module);
                }
            }
        }
        if (type.isCached()) {
            type = type.clone();
        }
        if (!type.isRaw())
            type.setRaw(isRaw(ModelUtil.getModuleContainer(container), typeMirror));
        FunctionOrValue value = null;
        boolean lookedup = false;
        if (isCeylon && decl instanceof Class) {
            // For a functional parameter to a class, we can just lookup the member
            value = (FunctionOrValue) ((Class) decl).getDirectMember(paramName, null, false);
            lookedup = value != null;
        }
        if (value == null) {
            // So either decl is not a Class,
            // or the method or value member of decl is not shared
            AnnotationMirror functionalParameterAnnotation = paramMirror.getAnnotation(CEYLON_FUNCTIONAL_PARAMETER_ANNOTATION);
            if (functionalParameterAnnotation != null) {
                // A functional parameter to a method
                Function method = loadFunctionalParameter((Declaration) decl, paramName, type, (String) functionalParameterAnnotation.getValue());
                value = method;
                parameter.setDeclaredAnything(method.isDeclaredVoid());
            } else if (coercedParameter && isFunctionCercion(typeMirror)) {
                Function method = loadFunctionCoercionParameter((Declaration) decl, paramName, typeMirror, module, scope);
                value = method;
                parameter.setDeclaredAnything(method.isDeclaredVoid());
            } else {
                // A value parameter to a method
                value = isCeylon ? new Value() : new JavaParameterValue();
                value.setType(type);
            }
            value.setContainer(scope);
            value.setScope(scope);
            ModelUtil.setVisibleScope(value);
            value.setUnit(scope.getUnit());
            value.setName(paramName);
        } else {
            // the method return type, so we try to detect this and fix it
            if (value instanceof Function && isCeylon1Dot1(classMirror)) {
                Type newType = getSimpleCallableReturnType(value.getType());
                if (!newType.isUnknown())
                    value.setType(newType);
            }
        }
        value.setInitializerParameter(parameter);
        value.setCoercionPoint(coercedParameter);
        parameter.setModel(value);
        if (paramMirror.getAnnotation(CEYLON_SEQUENCED_ANNOTATION) != null || isVariadic)
            parameter.setSequenced(true);
        if (paramMirror.getAnnotation(CEYLON_DEFAULTED_ANNOTATION) != null)
            parameter.setDefaulted(true);
        if (parameter.isSequenced() && // FIXME: store info in Sequenced
        "ceylon.language.Sequence".equals(paramMirror.getType().getQualifiedName())) {
            parameter.setAtLeastOne(true);
        }
        // unboxed is already set if it's a real method
        if (!lookedup) {
            // if it's variadic, consider the array element type (T[] == T...) for boxing rules
            markUnboxed(value, null, isVariadic ? paramMirror.getType().getComponentType() : paramMirror.getType());
            markSmall(value, paramMirror.getType());
        }
        parameter.setDeclaration((Declaration) decl);
        value.setDeprecated(value.isDeprecated() || isDeprecated(paramMirror));
        setAnnotations(value, paramMirror, false);
        parameters.getParameters().add(parameter);
        if (!lookedup) {
            parameter.getDeclaration().getMembers().add(parameter.getModel());
        }
        parameterIndex++;
    }
    if (decl instanceof Function) {
        // Multiple parameter lists
        AnnotationMirror functionalParameterAnnotation = methodMirror.getAnnotation(CEYLON_FUNCTIONAL_PARAMETER_ANNOTATION);
        if (functionalParameterAnnotation != null) {
            parameterNameParser.parseMpl((String) functionalParameterAnnotation.getValue(), ((Function) decl).getType().getFullType(), (Function) decl);
        }
    }
}
Also used : AnnotationMirror(org.eclipse.ceylon.model.loader.mirror.AnnotationMirror) Function(org.eclipse.ceylon.model.typechecker.model.Function) LazyFunction(org.eclipse.ceylon.model.loader.model.LazyFunction) 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) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) VariableMirror(org.eclipse.ceylon.model.loader.mirror.VariableMirror) 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) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) AnnotationProxyClass(org.eclipse.ceylon.model.loader.model.AnnotationProxyClass) LazyClass(org.eclipse.ceylon.model.loader.model.LazyClass) 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) Module(org.eclipse.ceylon.model.typechecker.model.Module) LazyModule(org.eclipse.ceylon.model.loader.model.LazyModule) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) JavaParameterValue(org.eclipse.ceylon.model.loader.model.JavaParameterValue)

Example 9 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class AbstractModelLoader method getContainer.

private ClassOrInterface getContainer(Module module, ClassMirror classMirror) {
    AnnotationMirror containerAnnotation = classMirror.getAnnotation(CEYLON_CONTAINER_ANNOTATION);
    if (containerAnnotation != null) {
        TypeMirror javaClassMirror = (TypeMirror) containerAnnotation.getValue("klass");
        String javaClassName = javaClassMirror.getQualifiedName();
        ClassOrInterface containerDecl = (ClassOrInterface) convertToDeclaration(module, javaClassName, DeclarationType.TYPE);
        if (containerDecl == null)
            throw new ModelResolutionException("Failed to load outer type " + javaClassName + " for inner type " + classMirror.getQualifiedName().toString());
        return containerDecl;
    } else {
        return (ClassOrInterface) convertToDeclaration(module, classMirror.getEnclosingClass(), DeclarationType.TYPE);
    }
}
Also used : AnnotationMirror(org.eclipse.ceylon.model.loader.mirror.AnnotationMirror) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror)

Example 10 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class ReflectionType method getTypeArguments.

@Override
public List<TypeMirror> getTypeArguments() {
    if (typeArguments != null)
        return typeArguments;
    if (type instanceof ParameterizedType) {
        Type[] javaTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
        typeArguments = new ArrayList<TypeMirror>(javaTypeArguments.length);
        for (Type typeArgument : javaTypeArguments) typeArguments.add(new ReflectionType(typeArgument));
        return typeArguments;
    } else
        typeArguments = Collections.<TypeMirror>emptyList();
    return typeArguments;
}
Also used : ParameterizedType(java.lang.reflect.ParameterizedType) GenericArrayType(java.lang.reflect.GenericArrayType) WildcardType(java.lang.reflect.WildcardType) ParameterizedType(java.lang.reflect.ParameterizedType) Type(java.lang.reflect.Type) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror)

Aggregations

TypeMirror (org.eclipse.ceylon.model.loader.mirror.TypeMirror)23 FunctionalInterfaceType (org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType)10 Type (org.eclipse.ceylon.model.typechecker.model.Type)10 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)10 ArrayList (java.util.ArrayList)7 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)6 AnnotationMirror (org.eclipse.ceylon.model.loader.mirror.AnnotationMirror)5 Type (org.eclipse.ceylon.langtools.tools.javac.code.Type)4 LazyFunction (org.eclipse.ceylon.model.loader.model.LazyFunction)4 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)4 Type (java.lang.reflect.Type)3 ClassMirror (org.eclipse.ceylon.model.loader.mirror.ClassMirror)3 TypeParameterMirror (org.eclipse.ceylon.model.loader.mirror.TypeParameterMirror)3 LazyClass (org.eclipse.ceylon.model.loader.model.LazyClass)3 LazyValue (org.eclipse.ceylon.model.loader.model.LazyValue)3 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)3 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)3 Function (org.eclipse.ceylon.model.typechecker.model.Function)3 Module (org.eclipse.ceylon.model.typechecker.model.Module)3 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)3