Search in sources :

Example 16 with AnnotationMirror

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

the class AbstractModelLoader method getLocalContainer.

private Scope getLocalContainer(Package pkg, ClassMirror classMirror, Declaration declaration) {
    AnnotationMirror localContainerAnnotation = classMirror.getAnnotation(CEYLON_LOCAL_CONTAINER_ANNOTATION);
    String qualifier = getAnnotationStringValue(classMirror, CEYLON_LOCAL_DECLARATION_ANNOTATION, "qualifier");
    // deal with types local to functions in the body of toplevel non-lazy attributes, whose container is ultimately the package
    Boolean isPackageLocal = getAnnotationBooleanValue(classMirror, CEYLON_LOCAL_DECLARATION_ANNOTATION, "isPackageLocal");
    if (BooleanUtil.isTrue(isPackageLocal)) {
        // make sure it still knows it's a local
        declaration.setQualifier(qualifier);
        return null;
    }
    LocalDeclarationContainer methodDecl = null;
    // we get a @LocalContainer annotation for local interfaces
    if (localContainerAnnotation != null) {
        methodDecl = (LocalDeclarationContainer) findLocalContainerFromAnnotationAndSetCompanionClass(pkg, (Interface) declaration, localContainerAnnotation);
    } else {
        // all the other cases stay where they belong
        MethodMirror method = classMirror.getEnclosingMethod();
        if (method == null)
            return null;
        // see where that method belongs
        ClassMirror enclosingClass = method.getEnclosingClass();
        while (enclosingClass.isAnonymous()) {
            // this gives us the method in which the anonymous class is, which should be the one we're looking for
            method = enclosingClass.getEnclosingMethod();
            if (method == null)
                return null;
            // and the method's containing class
            enclosingClass = method.getEnclosingClass();
        }
        // if we are in a setter class, the attribute is declared in the getter class, so look for its declaration there
        TypeMirror getterClass = (TypeMirror) getAnnotationValue(enclosingClass, CEYLON_SETTER_ANNOTATION, "getterClass");
        boolean isSetter = false;
        // we use void.class as default value
        if (getterClass != null && !getterClass.isPrimitive()) {
            enclosingClass = getterClass.getDeclaredClass();
            isSetter = true;
        }
        String javaClassName = enclosingClass.getQualifiedName();
        // make sure we don't go looking in companion classes
        if (javaClassName.endsWith(NamingBase.Suffix.$impl.name()))
            javaClassName = javaClassName.substring(0, javaClassName.length() - 5);
        // find the enclosing declaration
        Declaration enclosingClassDeclaration = convertToDeclaration(pkg.getModule(), javaClassName, DeclarationType.TYPE);
        if (enclosingClassDeclaration instanceof ClassOrInterface) {
            ClassOrInterface containerDecl = (ClassOrInterface) enclosingClassDeclaration;
            // now find the method's declaration
            // FIXME: find the proper overload if any
            String name = method.getName();
            if (method.isConstructor() || name.startsWith(NamingBase.Prefix.$default$.toString())) {
                methodDecl = (LocalDeclarationContainer) containerDecl;
            } else {
                // this is only for error messages
                String type;
                // lots of special cases
                if (isStringAttribute(method)) {
                    name = "string";
                    type = "attribute";
                } else if (isHashAttribute(method)) {
                    name = "hash";
                    type = "attribute";
                } else if (isGetter(method)) {
                    // simple attribute
                    name = getJavaAttributeName(method);
                    type = "attribute";
                } else if (isSetter(method)) {
                    // simple attribute
                    name = getJavaAttributeName(method);
                    type = "attribute setter";
                    isSetter = true;
                } else {
                    type = "method";
                }
                // it can be foo$priv$canonical so get rid of that one first
                if (name.endsWith(NamingBase.Suffix.$canonical$.toString())) {
                    name = name.substring(0, name.length() - 11);
                }
                name = JvmBackendUtil.strip(name, true, method.isPublic() || method.isProtected() || method.isDefaultAccess());
                if (name.indexOf('$') > 0) {
                    // may be a default parameter expression? get the method name which is first
                    name = name.substring(0, name.indexOf('$'));
                }
                methodDecl = (LocalDeclarationContainer) containerDecl.getDirectMember(name, null, false);
                if (methodDecl == null)
                    throw new ModelResolutionException("Failed to load outer " + type + " " + name + " for local type " + classMirror.getQualifiedName().toString());
                // if it's a setter we wanted, let's get it
                if (isSetter) {
                    LocalDeclarationContainer setter = (LocalDeclarationContainer) ((Value) methodDecl).getSetter();
                    if (setter == null)
                        throw new ModelResolutionException("Failed to load outer " + type + " " + name + " for local type " + classMirror.getQualifiedName().toString());
                    methodDecl = setter;
                }
            }
        } else if (enclosingClassDeclaration instanceof LazyFunction) {
            // local and toplevel methods
            methodDecl = (LazyFunction) enclosingClassDeclaration;
        } else if (enclosingClassDeclaration instanceof LazyValue) {
            // local and toplevel attributes
            if (enclosingClassDeclaration.isToplevel() && method.getName().equals(NamingBase.Unfix.set_.name()))
                isSetter = true;
            if (isSetter) {
                LocalDeclarationContainer setter = (LocalDeclarationContainer) ((LazyValue) enclosingClassDeclaration).getSetter();
                if (setter == null)
                    throw new ModelResolutionException("Failed to toplevel attribute setter " + enclosingClassDeclaration.getName() + " for local type " + classMirror.getQualifiedName().toString());
                methodDecl = setter;
            } else
                methodDecl = (LazyValue) enclosingClassDeclaration;
        } else {
            throw new ModelResolutionException("Unknown container type " + enclosingClassDeclaration + " for local type " + classMirror.getQualifiedName().toString());
        }
    }
    // we have the method, now find the proper local qualifier if any
    if (qualifier == null)
        return null;
    declaration.setQualifier(qualifier);
    methodDecl.addLocalDeclaration(declaration);
    return methodDecl;
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyValue(org.eclipse.ceylon.model.loader.model.LazyValue) LocalDeclarationContainer(org.eclipse.ceylon.model.loader.model.LocalDeclarationContainer) LazyFunction(org.eclipse.ceylon.model.loader.model.LazyFunction) ClassMirror(org.eclipse.ceylon.model.loader.mirror.ClassMirror) AnnotationMirror(org.eclipse.ceylon.model.loader.mirror.AnnotationMirror) MethodMirror(org.eclipse.ceylon.model.loader.mirror.MethodMirror) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Example 17 with AnnotationMirror

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

the class AbstractModelLoader method loadCompiledModule.

private boolean loadCompiledModule(Module module, ClassMirror moduleClass, boolean loadModuleImports) {
    String moduleClassName = moduleClass.getQualifiedName();
    String name = getAnnotationStringValue(moduleClass, CEYLON_MODULE_ANNOTATION, "name");
    String version = getAnnotationStringValue(moduleClass, CEYLON_MODULE_ANNOTATION, "version");
    if (name == null || name.isEmpty()) {
        logWarning("Module class " + moduleClassName + " contains no name, ignoring it");
        return false;
    }
    if (!name.equals(module.getNameAsString())) {
        logWarning("Module class " + moduleClassName + " declares an invalid name: " + name + ". It should be: " + module.getNameAsString());
        return false;
    }
    if (version == null || version.isEmpty()) {
        logWarning("Module class " + moduleClassName + " contains no version, ignoring it");
        return false;
    }
    if (!version.equals(module.getVersion())) {
        logWarning("Module class " + moduleClassName + " declares an invalid version: " + version + ". It should be: " + module.getVersion());
        return false;
    }
    // String label = getAnnotationStringValue(moduleClass, CEYLON_MODULE_ANNOTATION, "label");
    // module.setLabel(label);
    int major = getAnnotationIntegerValue(moduleClass, CEYLON_CEYLON_ANNOTATION, "major", 0);
    int minor = getAnnotationIntegerValue(moduleClass, CEYLON_CEYLON_ANNOTATION, "minor", 0);
    module.setJvmMajor(major);
    module.setJvmMinor(minor);
    // no need to load the "nativeBackends" annotation value, it's loaded from annotations
    setAnnotations(module, moduleClass, false);
    if (loadModuleImports) {
        List<AnnotationMirror> imports = getAnnotationArrayValue(moduleClass, CEYLON_MODULE_ANNOTATION, "dependencies");
        if (imports != null) {
            boolean supportsNamespaces = ModuleUtil.supportsImportsWithNamespaces(major, minor);
            for (AnnotationMirror importAttribute : imports) {
                String dependencyName = (String) importAttribute.getValue("name");
                if (dependencyName != null) {
                    String namespace;
                    if (supportsNamespaces) {
                        namespace = (String) importAttribute.getValue("namespace");
                        if (namespace != null && namespace.isEmpty()) {
                            namespace = null;
                        }
                    } else {
                        if (ModuleUtil.isMavenModule(dependencyName)) {
                            namespace = "maven";
                        } else {
                            namespace = null;
                        }
                    }
                    String dependencyVersion = (String) importAttribute.getValue("version");
                    Module dependency = moduleManager.getOrCreateModule(ModuleManager.splitModuleName(dependencyName), dependencyVersion);
                    Boolean optionalVal = (Boolean) importAttribute.getValue("optional");
                    Boolean exportVal = (Boolean) importAttribute.getValue("export");
                    List<String> nativeBackends = (List<String>) importAttribute.getValue("nativeBackends");
                    Backends backends = nativeBackends == null ? Backends.ANY : Backends.fromAnnotations(nativeBackends);
                    ModuleImport moduleImport = moduleManager.findImport(module, dependency);
                    if (moduleImport == null) {
                        boolean optional = optionalVal != null && optionalVal;
                        boolean export = exportVal != null && exportVal;
                        moduleImport = new ModuleImport(namespace, dependency, optional, export, backends);
                        module.addImport(moduleImport);
                    }
                }
            }
        }
    }
    module.setAvailable(true);
    modules.getListOfModules().add(module);
    Module languageModule = modules.getLanguageModule();
    module.setLanguageModule(languageModule);
    if (loadModuleImports) {
        if (!ModelUtil.equalModules(module, languageModule)) {
            boolean found = false;
            for (ModuleImport mi : module.getImports()) {
                if (mi.getModule().isLanguageModule()) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                // It's not really a LazyModule because we're not loading
                // it lazily. It's only here for module version analysis.
                // But other stuff expects non-source modules to be lazy.
                LazyModule oldLangMod = new LazyModule() {

                    @Override
                    protected AbstractModelLoader getModelLoader() {
                        return AbstractModelLoader.this;
                    }
                };
                oldLangMod.setLanguageModule(oldLangMod);
                oldLangMod.setName(Arrays.asList("ceylon", "language"));
                oldLangMod.setVersion(getJvmLanguageModuleVersion(major, minor));
                oldLangMod.setNativeBackends(Backends.JAVA);
                oldLangMod.setJvmMajor(major);
                oldLangMod.setJvmMinor(minor);
                ModuleImport moduleImport = new ModuleImport(null, oldLangMod, false, false);
                module.addImport(moduleImport);
            }
        }
    }
    return true;
}
Also used : AnnotationMirror(org.eclipse.ceylon.model.loader.mirror.AnnotationMirror) Backends(org.eclipse.ceylon.common.Backends) ModuleImport(org.eclipse.ceylon.model.typechecker.model.ModuleImport) List(java.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) Module(org.eclipse.ceylon.model.typechecker.model.Module) LazyModule(org.eclipse.ceylon.model.loader.model.LazyModule) LazyModule(org.eclipse.ceylon.model.loader.model.LazyModule)

Example 18 with AnnotationMirror

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

the class AbstractModelLoader method completeLazyAlias.

private void completeLazyAlias(TypeDeclaration alias, ClassMirror mirror, String aliasAnnotationName) {
    // now resolve the extended type
    AnnotationMirror aliasAnnotation = mirror.getAnnotation(aliasAnnotationName);
    String extendedTypeString = (String) aliasAnnotation.getValue();
    Type extendedType = decodeType(extendedTypeString, alias, ModelUtil.getModuleContainer(alias), "alias target");
    alias.setExtendedType(extendedType);
}
Also used : AnnotationMirror(org.eclipse.ceylon.model.loader.mirror.AnnotationMirror) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType)

Example 19 with AnnotationMirror

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

the class AbstractModelLoader method getRepeatableContainer.

public Interface getRepeatableContainer(Class c) {
    if (c instanceof AnnotationProxyClass) {
        AnnotationMirror mirror = ((AnnotationProxyClass) c).iface.classMirror.getAnnotation("java.lang.annotation.Repeatable");
        if (mirror != null) {
            TypeMirror m = (TypeMirror) mirror.getValue();
            Module module = findModuleForClassMirror(m.getDeclaredClass());
            return (Interface) convertDeclaredTypeToDeclaration(module, m, DeclarationType.TYPE);
        }
    }
    return null;
}
Also used : AnnotationMirror(org.eclipse.ceylon.model.loader.mirror.AnnotationMirror) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) AnnotationProxyClass(org.eclipse.ceylon.model.loader.model.AnnotationProxyClass) Module(org.eclipse.ceylon.model.typechecker.model.Module) LazyModule(org.eclipse.ceylon.model.loader.model.LazyModule) 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 20 with AnnotationMirror

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

the class AbstractModelLoader method makeLazyClass.

protected LazyClass makeLazyClass(ClassMirror classMirror, Class superClass, MethodMirror initOrDefaultConstructor, boolean isNativeHeader) {
    LazyClass klass = new LazyClass(classMirror, this, superClass, initOrDefaultConstructor);
    AnnotationMirror objectAnnotation = classMirror.getAnnotation(CEYLON_OBJECT_ANNOTATION);
    if (objectAnnotation != null) {
        klass.setAnonymous(true);
        // isFalse will only consider non-null arguments, and we default to true if null
        if (BooleanUtil.isFalse((Boolean) objectAnnotation.getValue("named")))
            klass.setNamed(false);
    }
    klass.setAnnotation(classMirror.getAnnotation(CEYLON_LANGUAGE_ANNOTATION_ANNOTATION) != null);
    if (klass.isCeylon())
        klass.setAbstract(classMirror.getAnnotation(CEYLON_LANGUAGE_ABSTRACT_ANNOTATION) != null || // the model annotation
        (!classMirror.isInnerClass() && !classMirror.isLocalClass() && classMirror.isAbstract()));
    else
        klass.setAbstract(classMirror.isAbstract() && !classMirror.isEnum());
    klass.setFormal(classMirror.getAnnotation(CEYLON_LANGUAGE_FORMAL_ANNOTATION) != null);
    klass.setDefault(classMirror.getAnnotation(CEYLON_LANGUAGE_DEFAULT_ANNOTATION) != null);
    klass.setSerializable(classMirror.getAnnotation(CEYLON_LANGUAGE_SERIALIZABLE_ANNOTATION) != null || classMirror.getQualifiedName().equals("ceylon.language.Array") || classMirror.getQualifiedName().equals("ceylon.language.Tuple"));
    // hack to make Throwable sealed until ceylon/ceylon.language#408 is fixed
    klass.setSealed(classMirror.getAnnotation(CEYLON_LANGUAGE_SEALED_ANNOTATION) != null || CEYLON_LANGUAGE.equals(classMirror.getPackage().getQualifiedName()) && "Throwable".equals(classMirror.getName()));
    boolean actual = classMirror.getAnnotation(CEYLON_LANGUAGE_ACTUAL_ANNOTATION) != null;
    klass.setActual(actual);
    klass.setActualCompleter(this);
    klass.setFinal(classMirror.isFinal());
    klass.setStatic(classMirror.isStatic());
    if (objectAnnotation == null) {
        manageNativeBackend(klass, classMirror, isNativeHeader);
    } else {
        manageNativeBackend(klass, getGetterMethodMirror(klass, klass.classMirror, true), isNativeHeader);
    }
    return klass;
}
Also used : AnnotationMirror(org.eclipse.ceylon.model.loader.mirror.AnnotationMirror) LazyClass(org.eclipse.ceylon.model.loader.model.LazyClass)

Aggregations

AnnotationMirror (org.eclipse.ceylon.model.loader.mirror.AnnotationMirror)25 LinkedList (java.util.LinkedList)6 LazyModule (org.eclipse.ceylon.model.loader.model.LazyModule)6 Module (org.eclipse.ceylon.model.typechecker.model.Module)6 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)6 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)6 ArrayList (java.util.ArrayList)5 List (java.util.List)5 TypeMirror (org.eclipse.ceylon.model.loader.mirror.TypeMirror)5 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)5 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)5 FunctionalInterfaceType (org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType)4 LazyClass (org.eclipse.ceylon.model.loader.model.LazyClass)4 Type (org.eclipse.ceylon.model.typechecker.model.Type)4 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)4 ClassMirror (org.eclipse.ceylon.model.loader.mirror.ClassMirror)3 AnnotationProxyClass (org.eclipse.ceylon.model.loader.model.AnnotationProxyClass)3 LazyInterface (org.eclipse.ceylon.model.loader.model.LazyInterface)3 LazyValue (org.eclipse.ceylon.model.loader.model.LazyValue)3 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)3