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);
}
}
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();
}
}
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);
}
}
}
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();
}
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() + "\"'"));
}
}
}
Aggregations