Search in sources :

Example 21 with Module

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

the class ModuleValidator method checkAndAddDependency.

private void checkAndAddDependency(List<Module> dependencies, Module module, LinkedList<Module> dependencyTree) {
    Module dupe = moduleManager.findModule(module, dependencies, false);
    boolean isDupe = dupe != null;
    if (dupe == null)
        dupe = moduleManager.findSimilarModule(module, dependencies);
    if (dupe != null && !isSameVersion(module, dupe)) {
        if (isDupe) {
            StringBuilder error = new StringBuilder("module (transitively) imports conflicting versions of dependency '");
            error.append(module.getNameAsString()).append("': ");
            String importPathA;
            String importPathB;
            String versionA;
            String versionB;
            if (VersionComparator.compareVersions(module.getVersion(), dupe.getVersion()) < 0) {
                versionA = module.getVersion();
                importPathA = importPathToString(dependencyTree);
                versionB = dupe.getVersion();
                importPathB = importPathToString(moduleToImportPath.get(dupe));
            } else {
                versionA = dupe.getVersion();
                importPathA = importPathToString(moduleToImportPath.get(dupe));
                versionB = module.getVersion();
                importPathB = importPathToString(dependencyTree);
            }
            error.append("version '").append(versionA).append("' (via import path '").append(importPathA).append("') and version '").append(versionB).append("' (via import path '").append(importPathB).append("')");
            moduleManagerUtil.addConflictingModuleErrorToModule(module.getNameAsString(), dependencyTree.getFirst(), error.toString());
        } else {
            // just possibly a dupe
            String moduleA;
            String moduleB;
            String importPathA;
            String importPathB;
            String moduleName = module.getNameAsString();
            String duplicateModuleName = dupe.getNameAsString();
            if (duplicateModuleName.compareTo(moduleName) < 0) {
                moduleA = ModuleUtil.makeModuleName(duplicateModuleName, dupe.getVersion());
                importPathA = importPathToString(moduleToImportPath.get(dupe));
                moduleB = ModuleUtil.makeModuleName(moduleName, module.getVersion());
                importPathB = importPathToString(dependencyTree);
            } else {
                moduleA = ModuleUtil.makeModuleName(moduleName, module.getVersion());
                importPathA = importPathToString(dependencyTree);
                moduleB = ModuleUtil.makeModuleName(duplicateModuleName, dupe.getVersion());
                importPathB = importPathToString(moduleToImportPath.get(dupe));
            }
            String error = "module (transitively) imports conflicting versions of similar dependencies '" + moduleA + "' (via import path '" + importPathA + "') and '" + moduleB + "' (via import path '" + importPathB + "')";
            moduleManagerUtil.addConflictingModuleWarningToModule(moduleA, dependencyTree.getFirst(), Warning.similarModule, error);
        }
    } else {
        dependencies.add(module);
        List<Module> importPath = new ArrayList<>(dependencyTree.size());
        importPath.addAll(dependencyTree);
        moduleToImportPath.put(module, importPath);
    }
}
Also used : ArrayList(java.util.ArrayList) ImportModule(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ImportModule) Module(org.eclipse.ceylon.model.typechecker.model.Module)

Example 22 with Module

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

the class ModuleValidator method verifyModuleDependencyTree.

private void verifyModuleDependencyTree(Collection<ModuleImport> moduleImports, LinkedList<Module> dependencyTree, List<Module> propagatedDependencies, ImportDepth importDepth, Map<Module, ArtifactResult> alreadySearchedArtifacts) {
    List<Module> visibleDependencies = new ArrayList<Module>();
    // first addition => no possible conflict
    visibleDependencies.add(dependencyTree.getLast());
    for (ModuleImport moduleImport : moduleImports) {
        if (moduleImport.isNative() && !isForBackend(moduleImport.getNativeBackends(), moduleManager.getSupportedBackends())) {
            // import is not for this backend
            continue;
        }
        Module module = moduleImport.getModule();
        if (moduleManager.findModule(module, dependencyTree, true) != null) {
            // circular dependency: stop right here
            continue;
        }
        ImportDepth newImportDepth = importDepth.forModuleImport(moduleImport);
        boolean forCompiledModule = newImportDepth.isVisibleToCompiledModules();
        resolveModuleIfRequired(module, forCompiledModule, moduleImport, importDepth, dependencyTree, alreadySearchedArtifacts);
        moduleManager.visitedModule(module, forCompiledModule);
        dependencyTree.addLast(module);
        List<Module> subModulePropagatedDependencies = new ArrayList<Module>();
        verifyModuleDependencyTree(module.getImports(), dependencyTree, subModulePropagatedDependencies, newImportDepth, alreadySearchedArtifacts);
        // visible dependency += subModule + subModulePropagatedDependencies
        checkAndAddDependency(visibleDependencies, module, dependencyTree);
        for (Module submodule : subModulePropagatedDependencies) {
            checkAndAddDependency(visibleDependencies, submodule, dependencyTree);
        }
        // propagated dependency += if subModule.export then subModule + subModulePropagatedDependencies
        if (moduleImport.isExport()) {
            checkAndAddDependency(propagatedDependencies, module, dependencyTree);
            for (Module submodule : subModulePropagatedDependencies) {
                checkAndAddDependency(propagatedDependencies, submodule, dependencyTree);
            }
        }
        dependencyTree.pollLast();
    }
}
Also used : ArrayList(java.util.ArrayList) ModuleImport(org.eclipse.ceylon.model.typechecker.model.ModuleImport) ImportModule(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ImportModule) Module(org.eclipse.ceylon.model.typechecker.model.Module)

Example 23 with Module

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

the class ModuleValidator method resolveModuleIfRequired.

private void resolveModuleIfRequired(Module module, boolean forCompiledModule, ModuleImport moduleImport, ImportDepth importDepth, LinkedList<Module> dependencyTree, Map<Module, ArtifactResult> alreadySearchedArtifacts) {
    if (!module.isAvailable()) {
        ArtifactResult artifact = null;
        boolean firstTime;
        if (alreadySearchedArtifacts.containsKey(module)) {
            artifact = alreadySearchedArtifacts.get(module);
            firstTime = false;
        } else {
            // try and load the module from the repository
            RepositoryManager repositoryManager = context.getRepositoryManager();
            if (repositoryManager.isValidNamespace(moduleImport.getNamespace())) {
                Exception exceptionOnGetArtifact = null;
                Iterable<String> searchedArtifactExtensions = moduleManager.getSearchedArtifactExtensions();
                ArtifactContext artifactContext = new ArtifactContext(moduleImport.getNamespace(), module.getNameAsString(), module.getVersion(), getArtifactSuffixes(searchedArtifactExtensions));
                listener.retrievingModuleArtifact(module, artifactContext);
                try {
                    artifact = repositoryManager.getArtifactResult(artifactContext);
                } catch (Exception e) {
                    exceptionOnGetArtifact = catchIfPossible(e);
                }
                if (artifact == null) {
                    boolean error = true;
                    if (ModuleUtil.isMavenModule(module.getNameAsString()) && !dependencyTree.isEmpty() && ModuleUtil.isMavenModule(dependencyTree.peekLast().getNameAsString()))
                        error = false;
                    // not there => error
                    ModuleHelper.buildErrorOnMissingArtifact(artifactContext, module, moduleImport, dependencyTree, exceptionOnGetArtifact, moduleManagerUtil, error);
                    listener.retrievingModuleArtifactFailed(module, artifactContext);
                } else {
                    listener.retrievingModuleArtifactSuccess(module, artifact);
                }
            } else {
                StringBuilder msg = new StringBuilder().append("unknown import namespace: '").append(moduleImport.getNamespace()).append("' should be one of ");
                TreeSet<String> namespaces = new TreeSet<String>();
                for (CmrRepository repo : repositoryManager.getRepositories()) {
                    namespaces.add(repo.getNamespace());
                }
                boolean first = true;
                for (String namespace : namespaces) {
                    if (first) {
                        first = false;
                    } else {
                        msg.append(", ");
                    }
                    msg.append("'").append(namespace).append("'");
                }
                // if (!MavenRepository.NAMESPACE.equals(moduleImport.getNamespace())) {
                // msg += " (if this is a Maven import make sure to add a 'maven:' prefix)";
                // }
                moduleManagerUtil.attachErrorToDependencyDeclaration(moduleImport, dependencyTree, msg.toString(), true);
            }
            alreadySearchedArtifacts.put(module, artifact);
            firstTime = true;
        }
        // a compiled module, then it MUST resolve it and make it available, so do try in this case.
        if (artifact != null && (firstTime || forCompiledModule)) {
            // parse module units and build module dependency and carry on
            listener.resolvingModuleArtifact(module, artifact);
            Module moduleOverride = moduleManager.overridesModule(artifact, module, moduleImport);
            if (moduleOverride != null) {
                if (importDepth.equals(ImportDepth.First)) {
                    moduleManagerUtil.attachErrorToDependencyDeclaration(moduleImport, dependencyTree, "project source module import is overridden in module overrides file: '" + moduleOverride.getNameAsString() + "/" + moduleOverride.getVersion() + "' overrides '" + module.getNameAsString() + "/" + module.getVersion() + "'", false);
                }
                module = moduleOverride;
            }
            moduleManagerUtil.resolveModule(artifact, module, moduleImport, dependencyTree, phasedUnitsOfDependencies, forCompiledModule);
        }
    }
}
Also used : TreeSet(java.util.TreeSet) RepositoryManager(org.eclipse.ceylon.cmr.api.RepositoryManager) ArtifactContext(org.eclipse.ceylon.cmr.api.ArtifactContext) CmrRepository(org.eclipse.ceylon.cmr.api.CmrRepository) ImportModule(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ImportModule) Module(org.eclipse.ceylon.model.typechecker.model.Module) ArtifactResult(org.eclipse.ceylon.model.cmr.ArtifactResult)

Example 24 with Module

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

the class ModuleValidator method verifyModuleDependencyTree.

/**
 *  At this stage we need to
 *  - resolve all non local modules (recursively)
 *  - build the object model of these compiled modules
 *  - declare a missing module as an error
 *  - detect circular dependencies
 *  - detect module version conflicts
 */
public void verifyModuleDependencyTree() {
    TypeCache.doWithoutCaching(new Runnable() {

        @Override
        public void run() {
            phasedUnitsOfDependencies = new ArrayList<PhasedUnits>();
            LinkedList<Module> dependencyTree = new LinkedList<Module>();
            // only verify modules we compile (and default/language), as that makes us traverse their dependencies anyways
            Set<Module> compiledModules = moduleManagerUtil.getCompiledModules();
            moduleManagerUtil.preResolveDependenciesIfRequired(context.getRepositoryManager());
            Module jdkProviderModule = moduleManagerUtil.getJdkProviderModule();
            List<Module> modules = new ArrayList<Module>(compiledModules.size() + 2);
            if (jdkProviderModule != null) {
                ModuleImport synthimp = new ModuleImport(null, jdkProviderModule, false, false);
                resolveModuleIfRequired(jdkProviderModule, true, synthimp, ImportDepth.First, dependencyTree, searchedArtifacts);
            }
            // we must resolve the language module first because it contains definitions that must be in the classpath
            // before any other JVM class is loaded, including the module descriptor annotations themselves
            modules.add(context.getModules().getLanguageModule());
            modules.add(context.getModules().getDefaultModule());
            modules.addAll(compiledModules);
            for (Module module : modules) {
                dependencyTree.addLast(module);
                // we don't care about propagated dependency here as top modules are independent from one another
                verifyModuleDependencyTree(module.getImports(), dependencyTree, new ArrayList<Module>(), ImportDepth.First, searchedArtifacts);
                dependencyTree.pollLast();
            }
            for (Module module : compiledModules) {
                verifyNative(module);
            }
            moduleManager.addImplicitImports();
        }
    });
    executeExternalModulePhases();
}
Also used : TreeSet(java.util.TreeSet) Set(java.util.Set) ArrayList(java.util.ArrayList) ModuleImport(org.eclipse.ceylon.model.typechecker.model.ModuleImport) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) ImportModule(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ImportModule) Module(org.eclipse.ceylon.model.typechecker.model.Module) LinkedList(java.util.LinkedList)

Example 25 with Module

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

the class ModuleValidator method verifyNative.

private void verifyNative(Module module) {
    for (ImportModule imp : moduleManagerUtil.retrieveModuleImportNodes(module)) {
        Module importedModule;
        Node node;
        if (imp.getImportPath() != null) {
            node = imp.getImportPath();
            importedModule = (Module) imp.getImportPath().getModel();
        } else {
            node = imp.getQuotedLiteral();
            importedModule = moduleManagerUtil.getModuleForNode(node);
            if (importedModule == null)
                continue;
        }
        Backends bs = getNativeBackend(imp.getAnnotationList(), imp.getUnit());
        if (bs.none()) {
            if (importedModule.isNative() && !module.isNative()) {
                node.addError(new ModuleSourceMapper.ModuleDependencyAnalysisError(node, "native import for cross-platform module" + " (mark either the module or the import as native)", 20000));
            }
        } else if (importedModule.isNative() && !bs.supports(importedModule.getNativeBackends())) {
            node.addError(new ModuleSourceMapper.ModuleDependencyAnalysisError(node, "native backend name conflicts with imported module: '\"" + bs + "\"' is not '\"" + importedModule.getNativeBackends().names() + "\"'"));
        }
    }
}
Also used : Backends(org.eclipse.ceylon.common.Backends) Node(org.eclipse.ceylon.compiler.typechecker.tree.Node) ImportModule(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ImportModule) Module(org.eclipse.ceylon.model.typechecker.model.Module) ImportModule(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ImportModule)

Aggregations

Module (org.eclipse.ceylon.model.typechecker.model.Module)113 LazyModule (org.eclipse.ceylon.model.loader.model.LazyModule)37 Package (org.eclipse.ceylon.model.typechecker.model.Package)26 ModuleImport (org.eclipse.ceylon.model.typechecker.model.ModuleImport)25 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)20 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)19 ArrayList (java.util.ArrayList)18 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)16 File (java.io.File)14 Type (org.eclipse.ceylon.model.typechecker.model.Type)14 HashMap (java.util.HashMap)9 HashSet (java.util.HashSet)9 FunctionalInterfaceType (org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType)9 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)9 Test (org.junit.Test)9 Value (org.eclipse.ceylon.model.typechecker.model.Value)8 LinkedList (java.util.LinkedList)7 List (java.util.List)7 Backends (org.eclipse.ceylon.common.Backends)7 ClassMirror (org.eclipse.ceylon.model.loader.mirror.ClassMirror)7