Search in sources :

Example 31 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class MethodOrValueReferenceVisitor method isCapturableMplParameter.

/**
 * Because methods with MPL use nested anonymous AbstractCallables
 * if the declaration is a parameter in all but the last parameter list
 * it should be captured.
 */
private boolean isCapturableMplParameter(Declaration d) {
    if (!(d instanceof FunctionOrValue)) {
        return false;
    }
    org.eclipse.ceylon.model.typechecker.model.Parameter param = ((FunctionOrValue) d).getInitializerParameter();
    if (param == null) {
        return false;
    }
    Declaration paramDecl = param.getDeclaration();
    if (paramDecl instanceof Functional) {
        List<org.eclipse.ceylon.model.typechecker.model.ParameterList> parameterLists = ((Functional) paramDecl).getParameterLists();
        for (int i = 0; i < parameterLists.size() - 1; i++) {
            if (parameterLists.get(i).getParameters().contains(param)) {
                return true;
            }
        }
    }
    return false;
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 32 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class AbstractModelLoader method addConstructorMethorOrValue.

protected FunctionOrValue addConstructorMethorOrValue(Class klass, ClassMirror classMirror, MethodMirror ctor, Constructor constructor, boolean isNativeHeader) {
    boolean isCeylon = classMirror.getAnnotation(CEYLON_CEYLON_ANNOTATION) != null;
    if (ctor.getAnnotation(CEYLON_ENUMERATED_ANNOTATION) != null) {
        klass.setEnumerated(true);
        Value v = new Value();
        v.setName(constructor.getName());
        v.setType(constructor.getType());
        v.setContainer(klass);
        v.setScope(klass);
        v.setUnit(klass.getUnit());
        v.setVisibleScope(constructor.getVisibleScope());
        // read annotations from the getter method
        setNonLazyDeclarationProperties(v, ctor, ctor, classMirror, isCeylon);
        setAnnotations(v, ctor, isNativeHeader);
        klass.addMember(v);
        return v;
    } else {
        setParameters(constructor, classMirror, ctor, true, klass, false);
        klass.setConstructors(true);
        Function f = new Function();
        f.setName(constructor.getName());
        f.setType(constructor.getType());
        f.addParameterList(constructor.getParameterList());
        f.setContainer(klass);
        f.setScope(klass);
        f.setUnit(klass.getUnit());
        f.setVisibleScope(constructor.getVisibleScope());
        // read annotations from the constructor
        setNonLazyDeclarationProperties(f, ctor, ctor, classMirror, isCeylon);
        setAnnotations(f, ctor, isNativeHeader);
        klass.addMember(f);
        return f;
    }
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) LazyFunction(org.eclipse.ceylon.model.loader.model.LazyFunction) 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)

Example 33 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue 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 34 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class JvmBackendUtil method getTopmostRefinedDeclaration.

public static Declaration getTopmostRefinedDeclaration(Declaration decl, Map<Function, Function> methodOverrides) {
    if (decl instanceof FunctionOrValue && ((FunctionOrValue) decl).isParameter() && decl.getContainer() instanceof Class) {
        // Parameters in a refined class are not considered refinements themselves
        // We have in find the refined attribute
        Class c = (Class) decl.getContainer();
        boolean isAlias = c.isAlias();
        boolean isActual = c.isActual();
        // boxing and stuff
        if (isAlias || isActual) {
            Functional ctor = null;
            int index = c.getParameterList().getParameters().indexOf(findParamForDecl(((TypedDeclaration) decl)));
            // Note(Stef): not entirely sure about that one, what about aliases of actual classes?
            while ((isAlias && c.isAlias()) || (isActual && c.isActual())) {
                ctor = (isAlias && c.isAlias()) ? (Functional) ((ClassAlias) c).getConstructor() : c;
                Type et = c.getExtendedType();
                c = et != null && et.isClass() ? (Class) et.getDeclaration() : null;
                // handle compile errors
                if (c == null)
                    return null;
            }
            if (isActual) {
                ctor = c;
            }
            // be safe
            if (ctor == null || ctor.getParameterLists() == null || ctor.getParameterLists().isEmpty() || ctor.getFirstParameterList() == null || ctor.getFirstParameterList().getParameters() == null || ctor.getFirstParameterList().getParameters().size() <= index)
                return null;
            decl = ctor.getFirstParameterList().getParameters().get(index).getModel();
        }
        if (decl.isShared()) {
            Declaration refinedDecl = c.getRefinedMember(decl.getName(), getSignature(decl), isVariadic(decl));
            if (refinedDecl != null && !ModelUtil.equal(refinedDecl, decl)) {
                return getTopmostRefinedDeclaration(refinedDecl, methodOverrides);
            }
        }
        return decl;
    } else if (decl instanceof FunctionOrValue && // a parameter
    ((FunctionOrValue) decl).isParameter() && (// that's not parameter of a functional parameter
    (decl.getContainer() instanceof Function && !(((Function) decl.getContainer()).isParameter())) || // or is a parameter in a specification
    decl.getContainer() instanceof Specification || (decl.getContainer() instanceof Function && ((Function) decl.getContainer()).isParameter() && createMethod((Function) decl.getContainer())))) {
        // or is a class functional parameter
        // Parameters in a refined method are not considered refinements themselves
        // so we have to look up the corresponding parameter in the container's refined declaration
        Functional func = (Functional) getParameterized((FunctionOrValue) decl);
        if (func == null)
            return decl;
        Declaration kk = getTopmostRefinedDeclaration((Declaration) func, methodOverrides);
        // error recovery
        if (kk instanceof Functional == false)
            return decl;
        Functional refinedFunc = (Functional) kk;
        // shortcut if the functional doesn't override anything
        if (ModelUtil.equal((Declaration) refinedFunc, (Declaration) func)) {
            return decl;
        }
        if (func.getParameterLists().size() != refinedFunc.getParameterLists().size()) {
            // invalid input
            return decl;
        }
        for (int ii = 0; ii < func.getParameterLists().size(); ii++) {
            if (func.getParameterLists().get(ii).getParameters().size() != refinedFunc.getParameterLists().get(ii).getParameters().size()) {
                // invalid input
                return decl;
            }
            // find the index of the parameter in the declaration
            int index = 0;
            for (Parameter px : func.getParameterLists().get(ii).getParameters()) {
                if (px.getModel() == null || px.getModel().equals(decl)) {
                    // And return the corresponding parameter from the refined declaration
                    return refinedFunc.getParameterLists().get(ii).getParameters().get(index).getModel();
                }
                index++;
            }
            continue;
        }
    } else if (methodOverrides != null && decl instanceof Function && ModelUtil.equal(decl.getRefinedDeclaration(), decl) && decl.getContainer() instanceof Specification && ((Specification) decl.getContainer()).getDeclaration() instanceof Function && ((Function) ((Specification) decl.getContainer()).getDeclaration()).isShortcutRefinement() && // hash lookup we do next to make sure it is really one of those cases
    methodOverrides.containsKey(decl)) {
        // special case for class X() extends T(){ m = function() => e; } which we inline
        decl = methodOverrides.get(decl);
    }
    Declaration refinedDecl = decl.getRefinedDeclaration();
    if (refinedDecl != null && !ModelUtil.equal(refinedDecl, decl))
        return getTopmostRefinedDeclaration(refinedDecl);
    return decl;
}
Also used : Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Function(org.eclipse.ceylon.model.typechecker.model.Function) VisibilityType(org.eclipse.ceylon.model.cmr.VisibilityType) ArtifactResultType(org.eclipse.ceylon.model.cmr.ArtifactResultType) Type(org.eclipse.ceylon.model.typechecker.model.Type) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) Class(org.eclipse.ceylon.model.typechecker.model.Class) Specification(org.eclipse.ceylon.model.typechecker.model.Specification) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 35 with FunctionOrValue

use of org.eclipse.ceylon.model.typechecker.model.FunctionOrValue in project ceylon by eclipse.

the class ParameterNameParser method parseName.

private Parameter parseName(Type type, Function container) {
    String identifier = lexer.eatIdentifier();
    boolean declaredVoid = false;
    boolean sequenced = false;
    boolean atLeastOne = false;
    if (lexer.lookingAt(STAR)) {
        lexer.eat();
        sequenced = true;
    } else if (lexer.lookingAt(PLUS)) {
        lexer.eat();
        sequenced = true;
        atLeastOne = true;
    }
    if (lexer.lookingAt(BANG)) {
        lexer.eat();
        declaredVoid = true;
    }
    final FunctionOrValue result;
    if (lexer.lookingAt(LEFT_PAREN)) {
        // functionParameter()
        result = parseMethod(type, declaredVoid);
    } else {
        if (declaredVoid) {
            throw new ParameterNameParserException("void Value");
        }
        // valueParameter();
        result = parseValue(type);
    }
    result.setName(identifier);
    result.setUnit(unit);
    result.setContainer(container);
    result.setScope(container);
    Parameter p = new Parameter();
    p.setName(identifier);
    p.setSequenced(sequenced);
    p.setAtLeastOne(atLeastOne);
    p.setDeclaredAnything(declaredVoid);
    p.setModel(result);
    result.setInitializerParameter(p);
    container.addMember(result);
    return p;
}
Also used : Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Aggregations

FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)65 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)28 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)27 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)26 Type (org.eclipse.ceylon.model.typechecker.model.Type)25 Value (org.eclipse.ceylon.model.typechecker.model.Value)24 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)22 Function (org.eclipse.ceylon.model.typechecker.model.Function)22 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)21 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)19 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)13 ArrayList (java.util.ArrayList)12 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)11 TypedReference (org.eclipse.ceylon.model.typechecker.model.TypedReference)10 AnalyzerUtil.getTupleType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType)9 AnalyzerUtil.spreadType (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType)9 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)9 ModelUtil.genericFunctionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType)9 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)9 ModelUtil.unionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType)9