Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' of github.com:ceylon/ceylon-spec into sin_natural

  • Loading branch information...
commit 62ddc831666e07feeeb9981b275504c58b4b12fb 2 parents 33dac85 + 01036ae
@gavinking gavinking authored
Showing with 641 additions and 201 deletions.
  1. +3 −1 src/Main.java
  2. +10 −2 src/MainForTest.java
  3. +11 −2 src/com/redhat/ceylon/compiler/typechecker/TypeChecker.java
  4. +124 −31 src/com/redhat/ceylon/compiler/typechecker/analyzer/{ModuleBuilder.java → ModuleManager.java}
  5. +106 −28 src/com/redhat/ceylon/compiler/typechecker/analyzer/ModuleValidator.java
  6. +118 −93 src/com/redhat/ceylon/compiler/typechecker/analyzer/ModuleVisitor.java
  7. +17 −4 src/com/redhat/ceylon/compiler/typechecker/context/Context.java
  8. +22 −11 src/com/redhat/ceylon/compiler/typechecker/context/PhasedUnit.java
  9. +23 −13 src/com/redhat/ceylon/compiler/typechecker/context/PhasedUnits.java
  10. +19 −4 src/com/redhat/ceylon/compiler/typechecker/io/ArtifactProvider.java
  11. +8 −8 src/com/redhat/ceylon/compiler/typechecker/model/Module.java
  12. +41 −0 src/com/redhat/ceylon/compiler/typechecker/model/ModuleImport.java
  13. 0  test/{ → main}/aliases/Aliases.ceylon
  14. 0  test/{ → main}/aliases/Class.ceylon
  15. 0  test/{ → main}/aliases/Interface.ceylon
  16. 0  test/{ → main}/animals/Animals.ceylon
  17. 0  test/{ → main}/annotations/Annotations.ceylon
  18. 0  test/{ → main}/capture/Capture.ceylon
  19. +11 −0 test/main/com/redhat/sample/circularity/c1/module.ceylon
  20. +11 −0 test/main/com/redhat/sample/circularity/c2/module.ceylon
  21. 0  test/{ → main}/com/redhat/sample/multisource/Boo.ceylon
  22. 0  test/{ → main}/com/redhat/sample/multisource/domain/Order.ceylon
  23. +1 −1  test/{ → main}/com/redhat/sample/multisource/module.ceylon
  24. 0  test/{ → main}/com/redhat/sample/multisource/service/OrderService.ceylon
  25. +1 −1  test/{ → main}/com/redhat/sample/nestedmodules/module.ceylon
  26. +1 −1  test/{ → main}/com/redhat/sample/nestedmodules/sub/module.ceylon
  27. 0  test/{ → main}/controlflow/BreakContinue.ceylon
  28. 0  test/{ → main}/controlflow/DefiniteReturn.ceylon
  29. 0  test/{ → main}/declarations/Circularities.ceylon
  30. 0  test/{ → main}/declarations/ClassBodies.ceylon
  31. 0  test/{ → main}/declarations/ClassDeclarations.ceylon
  32. 0  test/{ → main}/declarations/ClassMembers.ceylon
  33. 0  test/{ → main}/declarations/Declarations.ceylon
  34. 0  test/{ → main}/declarations/Formal.ceylon
  35. 0  test/{ → main}/declarations/GettersSetters.ceylon
  36. 0  test/{ → main}/declarations/Hiding.ceylon
  37. 0  test/{ → main}/declarations/InterfaceDeclarations.ceylon
  38. 0  test/{ → main}/declarations/InterfaceMembers.ceylon
  39. 0  test/{ → main}/declarations/ObjectDeclarations.ceylon
  40. 0  test/{ → main}/declarations/ParameterHiding.ceylon
  41. 0  test/{ → main}/declarations/Parameters.ceylon
  42. 0  test/{ → main}/declarations/Toplevel.ceylon
  43. 0  test/{ → main}/declarations/thisSuperOuter.ceylon
  44. 0  test/{ → main}/family/BasicGraph.ceylon
  45. 0  test/{ → main}/family/Graph.ceylon
  46. 0  test/{ → main}/family/OnOffGraph.ceylon
  47. 0  test/{ → main}/family/test.ceylon
  48. 0  test/{ → main}/family2/BasicGraph.ceylon
  49. 0  test/{ → main}/family2/Graph.ceylon
  50. 0  test/{ → main}/family2/OnOffGraph.ceylon
  51. 0  test/{ → main}/family2/test.ceylon
  52. 0  test/{ → main}/function/Comprehensions.ceylon
  53. 0  test/{ → main}/function/FunctionTypes.ceylon
  54. 0  test/{ → main}/function/SequencedTypeArgs.ceylon
  55. 0  test/{ → main}/imports/package/Alias.ceylon
  56. 0  test/{ → main}/imports/package/Class.ceylon
  57. 0  test/{ → main}/imports/package/Dupe.ceylon
  58. 0  test/{ → main}/imports/package/Interface.ceylon
  59. 0  test/{ → main}/imports/package/attribute.ceylon
  60. 0  test/{ → main}/imports/package/method.ceylon
  61. 0  test/{ → main}/imports/test/Dupe.ceylon
  62. 0  test/{ → main}/imports/test/Test.ceylon
  63. 0  test/{ → main}/imports/test/TestAliases.ceylon
  64. 0  test/{ → main}/imports/test/TestWildcard.ceylon
  65. +1 −1  test/{ → main}/module.ceylon
  66. 0  test/{ → main}/observable/Display.ceylon
  67. 0  test/{ → main}/observable/List.ceylon
  68. 0  test/{ → main}/observable/Model.ceylon
  69. 0  test/{ → main}/observable/Observer.ceylon
  70. 0  test/{ → main}/observable/Subject.ceylon
  71. 0  test/{ → main}/observable/callGenericUpdate.ceylon
  72. 0  test/{ → main}/refinement/ActualFormalDefault.ceylon
  73. 0  test/{ → main}/refinement/FormalActual.ceylon
  74. 0  test/{ → main}/refinement/GenericRefinement.ceylon
  75. 0  test/{ → main}/refinement/MultipleInheritance.ceylon
  76. 0  test/{ → main}/refinement/Refinement.ceylon
  77. 0  test/{ → main}/specification/Children.ceylon
  78. 0  test/{ → main}/specification/DefiniteAssignment.ceylon
  79. 0  test/{ → main}/specification/DefiniteSpecification.ceylon
  80. 0  test/{ → main}/specification/SelfReference.ceylon
  81. 0  test/{ → main}/specification/Test.ceylon
  82. 0  test/{ → main}/statements/ControlStructures.ceylon
  83. 0  test/{ → main}/statements/SequencedArguments.ceylon
  84. 0  test/{ → main}/statements/Statements.ceylon
  85. 0  test/{ → main}/typing/Assignability.ceylon
  86. 0  test/{ → main}/typing/Generics.ceylon
  87. 0  test/{ → main}/typing/Hierarchy.ceylon
  88. 0  test/{ → main}/typing/Inheritance.ceylon
  89. 0  test/{ → main}/typing/InheritanceConsistency.ceylon
  90. 0  test/{ → main}/typing/Intersection.ceylon
  91. 0  test/{ → main}/typing/Is.ceylon
  92. 0  test/{ → main}/typing/LanguageModule.ceylon
  93. 0  test/{ → main}/typing/Literals.ceylon
  94. 0  test/{ → main}/typing/NestedCases.ceylon
  95. 0  test/{ → main}/typing/Operators.ceylon
  96. 0  test/{ → main}/typing/Optional.ceylon
  97. 0  test/{ → main}/typing/OuterTypeArgs.ceylon
  98. 0  test/{ → main}/typing/Primaries.ceylon
  99. 0  test/{ → main}/typing/RecursiveVariance.ceylon
  100. 0  test/{ → main}/typing/Restriction.ceylon
  101. 0  test/{ → main}/typing/SelfType.ceylon
  102. 0  test/{ → main}/typing/TypeArgInference.ceylon
  103. 0  test/{ → main}/typing/TypeInference.ceylon
  104. 0  test/{ → main}/typing/Union.ceylon
  105. 0  test/{ → main}/visibility/Hiding.ceylon
  106. 0  test/{ → main}/visibility/Hierarchy.ceylon
  107. 0  test/{ → main}/visibility/TypedVisibility.ceylon
  108. 0  test/{ → main}/visibility/Unit1.ceylon
  109. 0  test/{ → main}/visibility/Unit2.ceylon
  110. 0  test/{ → main}/visibility/package/Unit3.ceylon
  111. 0  test/{ → main}/visibility/package/Unit4.ceylon
  112. 0  test/{ → main}/visibility/package/Unit5.ceylon
  113. 0  test/{ → main}/visibility/package/Unit6.ceylon
  114. +10 −0 test/moduledep1/com/redhat/ceylon/compiler/typechecker/test/module/a/module.ceylon
  115. +6 −0 test/moduledep1/com/redhat/ceylon/compiler/typechecker/test/module/b/module.ceylon
  116. +11 −0 test/moduledep1/com/redhat/ceylon/compiler/typechecker/test/module/c/module.ceylon
  117. +6 −0 test/moduledep1/com/redhat/ceylon/compiler/typechecker/test/module/d/module.ceylon
  118. +10 −0 test/moduledep2/com/redhat/ceylon/compiler/typechecker/test/module/b/module.ceylon
  119. +6 −0 test/moduledep2/com/redhat/ceylon/compiler/typechecker/test/module/c/module.ceylon
  120. +6 −0 test/moduledep2/com/redhat/ceylon/compiler/typechecker/test/module/d/module.ceylon
  121. +15 −0 test/moduletest/com/redhat/ceylon/compiler/typechecker/test/module/testdiffversion/module.ceylon
  122. +15 −0 test/moduletest/com/redhat/ceylon/compiler/typechecker/test/module/testdiffversionexport/module.ceylon
  123. +14 −0 test/moduletest/com/redhat/ceylon/compiler/typechecker/test/module/testexportisolation/module.ceylon
  124. +14 −0 test/moduletest/com/redhat/ceylon/compiler/typechecker/test/module/testsameversionwork/module.ceylon
View
4 src/Main.java
@@ -19,7 +19,9 @@
public static void main(String[] args) throws Exception {
String path;
if ( args.length==0 ) {
- path = "corpus";
+ System.err.println("Usage Main <directoryName>");
+ System.exit(-1);
+ return;
}
else {
path = args[0];
View
12 src/MainForTest.java
@@ -19,7 +19,7 @@ public static void main(String[] args) throws Exception {
TypeChecker typeChecker = new TypeCheckerBuilder()
.verbose(false)
- .addSrcDirectory( new File("test") )
+ .addSrcDirectory( new File("test/main") )
.getTypeChecker();
typeChecker.process();
Tree.CompilationUnit compilationUnit = typeChecker.getPhasedUnitFromRelativePath("ceylon/language/Object.ceylon").getCompilationUnit();
@@ -40,7 +40,7 @@ public static void main(String[] args) throws Exception {
}
typeChecker = new TypeCheckerBuilder()
.verbose(false)
- .addSrcDirectory( new File("test/capture") )
+ .addSrcDirectory( new File("test/main/capture") )
.getTypeChecker();
typeChecker.process();
compilationUnit = typeChecker.getPhasedUnitFromRelativePath("Capture.ceylon").getCompilationUnit();
@@ -48,6 +48,14 @@ public static void main(String[] args) throws Exception {
throw new RuntimeException("Failed to pass getCompilationUnitFromRelativePath for top level files (no package) in real src dir");
}
+ typeChecker = new TypeCheckerBuilder()
+ .verbose(false)
+ .addSrcDirectory( new File("test/moduledep1") )
+ .addSrcDirectory( new File("test/moduledep2") )
+ .addSrcDirectory( new File("test/moduletest") )
+ .getTypeChecker();
+ typeChecker.process();
+
ClosableVirtualFile latestZippedLanguageSourceFile = MainHelper.getLatestZippedLanguageSourceFile();
typeChecker = new TypeCheckerBuilder()
.verbose(false)
View
13 src/com/redhat/ceylon/compiler/typechecker/TypeChecker.java
@@ -8,6 +8,7 @@
import com.redhat.ceylon.compiler.typechecker.context.PhasedUnits;
import com.redhat.ceylon.compiler.typechecker.io.VFS;
import com.redhat.ceylon.compiler.typechecker.io.VirtualFile;
+import com.redhat.ceylon.compiler.typechecker.model.Module;
import com.redhat.ceylon.compiler.typechecker.util.AssertionVisitor;
import com.redhat.ceylon.compiler.typechecker.util.StatisticsVisitor;
@@ -19,6 +20,8 @@
//TODO make an interface?
public class TypeChecker {
+ public static final String LANGUAGE_MODULE_VERSION = "0.1";
+
private final boolean verbose;
private final List<VirtualFile> srcDirectories;
private final Context context;
@@ -107,8 +110,14 @@ public void process() throws RuntimeException {
private void executePhases(PhasedUnits phasedUnits, boolean forceSilence) {
final List<PhasedUnit> listOfUnits = phasedUnits.getPhasedUnits();
- for (PhasedUnit pu : listOfUnits) {
- pu.buildModuleImport();
+
+ phasedUnits.visitModules();
+
+ //By now le language module version should be known (as local)
+ //or we should use the default one.
+ Module languageModule = context.getModules().getLanguageModule();
+ if (languageModule.getVersion() == null) {
+ languageModule.setVersion(LANGUAGE_MODULE_VERSION);
}
final ModuleValidator moduleValidator = new ModuleValidator(context, phasedUnits);
View
155 ...r/typechecker/analyzer/ModuleBuilder.java → ...r/typechecker/analyzer/ModuleManager.java
@@ -13,28 +13,32 @@
import java.util.Set;
import com.redhat.ceylon.compiler.typechecker.context.Context;
+import com.redhat.ceylon.compiler.typechecker.context.PhasedUnit;
+import com.redhat.ceylon.compiler.typechecker.context.PhasedUnits;
+import com.redhat.ceylon.compiler.typechecker.io.VirtualFile;
import com.redhat.ceylon.compiler.typechecker.model.Module;
+import com.redhat.ceylon.compiler.typechecker.model.ModuleImport;
import com.redhat.ceylon.compiler.typechecker.model.Modules;
import com.redhat.ceylon.compiler.typechecker.model.Package;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
-import com.redhat.ceylon.compiler.typechecker.tree.Tree;
/**
- * Build modules and packages
+ * Manager modules and packages (build, retrieve, handle errors etc)
*
* @author Emmanuel Bernard <emmanuel@hibernate.org>
*/
-public class ModuleBuilder {
+public class ModuleManager {
public static final String MODULE_FILE = "module.ceylon";
public static final String PACKAGE_FILE = "package.ceylon";
private final Context context;
private final LinkedList<Package> packageStack = new LinkedList<Package>();
private Module currentModule;
private Modules modules;
- private final Map<Module,Set<Node>> missingModuleDependencies = new HashMap<Module, Set<Node>>();
+ private final Map<ModuleImport,Set<Node>> moduleImportToNode = new HashMap<ModuleImport, Set<Node>>();
private Map<List<String>, Set<String>> topLevelErrorsPerModuleName = new HashMap<List<String>,Set<String>>();
+ private Map<Module, Node> moduleToNode = new HashMap<Module, Node>();
- public ModuleBuilder(Context context) {
+ public ModuleManager(Context context) {
this.context = context;
}
@@ -51,6 +55,7 @@ public void initCoreModules() {
final List<String> defaultModuleName = Collections.singletonList("<default module>");
final Module defaultModule = createModule(defaultModuleName);
defaultModule.setAvailable(true);
+ defaultModule.setVersion("<unknown>");
bindPackageToModule(emptyPackage, defaultModule);
modules.getListOfModules().add(defaultModule);
modules.setDefaultModule(defaultModule);
@@ -63,7 +68,7 @@ public void initCoreModules() {
languageModule.setAvailable(false); //not available yet
modules.setLanguageModule(languageModule);
modules.getListOfModules().add(languageModule);
- defaultModule.getDependencies().add(languageModule);
+ defaultModule.getImports().add(new ModuleImport(languageModule, false, false));
defaultModule.setLanguageModule(languageModule);
context.setModules(modules);
}
@@ -91,7 +96,12 @@ public Package getCurrentPackage() {
return packageStack.peekLast();
}
- public Module getOrCreateModule(List<String> moduleName) {
+ /**
+ * Get or create a module.
+ * version == null is considered equal to any version.
+ * Likewise a module with no version will match any version passed
+ */
+ public Module getOrCreateModule(List<String> moduleName, String version) {
if (moduleName.size() == 0) {
return null;
}
@@ -100,24 +110,31 @@ public Module getOrCreateModule(List<String> moduleName) {
for (Module current : moduleList) {
final List<String> names = current.getName();
if ( names.size() == moduleName.size()
- && moduleName.containsAll(names) ) {
+ && moduleName.containsAll(names)
+ && compareVersions(version, current.getVersion())) {
module = current;
break;
}
}
if (module == null) {
module = createModule(moduleName);
+ module.setVersion(version);
module.setLanguageModule(modules.getLanguageModule());
moduleList.add(module);
}
return module;
}
+ private boolean compareVersions(String version, String currentVersion) {
+ return currentVersion == null || version == null || currentVersion.equals(version);
+ }
+
public void visitModuleFile() {
if ( currentModule == null ) {
final Package currentPkg = packageStack.peekLast();
final List<String> moduleName = currentPkg.getName();
- currentModule = getOrCreateModule(moduleName);
+ //we don't know the version at this stage, will be filled later
+ currentModule = getOrCreateModule(moduleName, null);
if ( currentModule != null ) {
currentModule.setAvailable(true); // TODO : not necessary anymore ? the phasedUnit will be added. And the buildModuleImport()
// function (which calls module.setAvailable()) will be called by the typeChecker
@@ -126,7 +143,7 @@ public void visitModuleFile() {
bindPackageToModule(currentPkg, currentModule);
}
else {
- collectError(new ArrayList<String>(), "A module cannot be defined at the top level of the hierarchy");
+ addErrorToModule(new ArrayList<String>(), "A module cannot be defined at the top level of the hierarchy");
}
}
else {
@@ -135,20 +152,11 @@ public void visitModuleFile() {
.append( "' and '" )
.append( formatPath( packageStack.peekLast().getName() ) )
.append("'");
- collectError(currentModule.getName(), error.toString());
- collectError(packageStack.peekLast().getName(), error.toString());
+ addErrorToModule(currentModule.getName(), error.toString());
+ addErrorToModule(packageStack.peekLast().getName(), error.toString());
}
}
- private void collectError(List<String> moduleName, String error) {
- Set<String> errors = topLevelErrorsPerModuleName.get(moduleName);
- if (errors == null) {
- errors = new HashSet<String>();
- topLevelErrorsPerModuleName.put(moduleName, errors);
- }
- errors.add(error);
- }
-
private void createPackageAndAddToModule(String path) {
Package pkg = new Package();
final Package lastPkg = packageStack.peekLast();
@@ -186,33 +194,118 @@ private void bindPackageToModule(Package pkg, Module module) {
pkg.setModule(module);
}
- public void addModuleDependencyDefinition(Module module, Node definition) {
- Set<Node> moduleDepError = missingModuleDependencies.get(module);
- if (moduleDepError == null) {
- moduleDepError = new HashSet<Node>();
- missingModuleDependencies.put(module, moduleDepError);
+ public void addModuleDependencyDefinition(ModuleImport moduleImport, Node definition) {
+ Set<Node> moduleDepDefinition = moduleImportToNode.get(moduleImport);
+ if (moduleDepDefinition == null) {
+ moduleDepDefinition = new HashSet<Node>();
+ moduleImportToNode.put(moduleImport, moduleDepDefinition);
}
- moduleDepError.add(definition);
+ moduleDepDefinition.add(definition);
}
- public void addMissingDependencyError(Module module, String error) {
- Set<Node> moduleDepError = missingModuleDependencies.get(module);
+ public void attachErrorToDependencyDeclaration(ModuleImport moduleImport, String error) {
+ Set<Node> moduleDepError = moduleImportToNode.get(moduleImport);
if (moduleDepError != null) {
for ( Node definition : moduleDepError ) {
definition.addError(error);
}
}
else {
- System.err.println("This is a type checker bug, please report. \nExpecting to add missing dependency error on non present definition: " + error);
+ //This probably can happen if the missing dependency is found deep in the dependency structure (ie the binary version of a module)
+ //TODO find the nearest src module that triggered the issue
+ System.err.println("This might be a type checker bug, please report. \nExpecting to add missing dependency error on non present definition: " + error);
+ }
+ }
+
+ //must be used *after* addLinkBetweenModuleAndNode has been set ie post ModuleVisitor visit
+ public void addErrorToModule(Module module, String error) {
+ Node node = moduleToNode.get(module);
+ if (node != null) {
+ node.addError(error);
+ }
+ else {
+ //might happen if the faulty module is a compiled module
+ System.err.println("This is a type checker bug, please report. " +
+ "\nExpecting to add error on non present module node: " + module.toString() + ". Error " + error);
}
}
- public void addErrorsToModule(Module module, Node unit) {
+ //only used if we really don't know the version
+ private void addErrorToModule(List<String> moduleName, String error) {
+ Set<String> errors = topLevelErrorsPerModuleName.get(moduleName);
+ if (errors == null) {
+ errors = new HashSet<String>();
+ topLevelErrorsPerModuleName.put(moduleName, errors);
+ }
+ errors.add(error);
+ }
+
+ public void addLinkBetweenModuleAndNode(Module module, Node unit) {
+ //keep link and display errors on modules where we don't know the version of
Set<String> errors = topLevelErrorsPerModuleName.get(module.getName());
if (errors != null) {
for(String error : errors) {
unit.addError(error);
}
+ errors.clear();
+ }
+ moduleToNode.put(module,unit);
+ }
+
+ public ModuleImport findImport(Module owner, Module dependency) {
+ for (ModuleImport modImprt : owner.getImports()) {
+ if (equalsForModules(modImprt.getModule(), dependency, true)) return modImprt;
}
+ return null;
+ }
+
+ public boolean equalsForModules(Module left, Module right, boolean exactVersionMatch) {
+ if (left == right) return true;
+ List<String> leftName = left.getName();
+ List<String> rightName = right.getName();
+ if (leftName.size() != rightName.size()) return false;
+ for(int index = 0 ; index < leftName.size(); index++) {
+ if (!leftName.get(index).equals(rightName.get(index))) return false;
+ }
+ if (exactVersionMatch && left.getVersion()!=right.getVersion()) return false;
+ return true;
+ }
+
+ public Module findModule(Module module, List<Module> listOfModules, boolean exactVersionMatch) {
+ for(Module current : listOfModules) {
+ if (equalsForModules(module, current, exactVersionMatch)) return current;
+ }
+ return null;
+ }
+
+ public Module findLoadedModule(String moduleName, String searchedVersion) {
+ return findLoadedModule(moduleName, searchedVersion, modules);
+ }
+
+ public Module findLoadedModule(String moduleName, String searchedVersion, Modules modules) {
+ for(Module module : modules.getListOfModules()){
+ if(module.getNameAsString().equals(moduleName)) {
+ if (searchedVersion != null && searchedVersion.equals(module.getVersion())){
+ return module;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void resolveModule(Module module, VirtualFile artifact, List<PhasedUnits> phasedUnitsOfDependencies) {
+ PhasedUnits modulePhasedUnit = new PhasedUnits(context);
+ phasedUnitsOfDependencies.add(modulePhasedUnit);
+ modulePhasedUnit.parseUnit(artifact);
+ //populate module.getDependencies()
+ modulePhasedUnit.visitModules();
+ }
+
+ public Iterable<String> getSearchedArtifactExtensions() {
+ return Arrays.asList("src");
+ }
+
+ public static List<String> splitModuleName(String moduleName) {
+ return Arrays.asList(moduleName.split("[\\.]"));
}
}
View
134 src/com/redhat/ceylon/compiler/typechecker/analyzer/ModuleValidator.java
@@ -2,6 +2,7 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@@ -12,7 +13,9 @@
import com.redhat.ceylon.compiler.typechecker.exceptions.LanguageModuleNotFoundException;
import com.redhat.ceylon.compiler.typechecker.io.ArtifactProvider;
import com.redhat.ceylon.compiler.typechecker.io.ClosableVirtualFile;
+import com.redhat.ceylon.compiler.typechecker.io.VirtualFile;
import com.redhat.ceylon.compiler.typechecker.model.Module;
+import com.redhat.ceylon.compiler.typechecker.model.ModuleImport;
/**
* Validate module dependency:
@@ -25,11 +28,12 @@
public class ModuleValidator {
private final Context context;
private List<PhasedUnits> phasedUnitsOfDependencies;
- private final ModuleBuilder moduleBuilder;
+ private final ModuleManager moduleManager;
+
public ModuleValidator(Context context, PhasedUnits phasedUnits) {
this.context = context;
- this.moduleBuilder = phasedUnits.getModuleBuilder();
+ this.moduleManager = phasedUnits.getModuleManager();
}
public List<PhasedUnits> getPhasedUnitsOfDependencies() {
@@ -42,6 +46,7 @@ public ModuleValidator(Context context, PhasedUnits phasedUnits) {
* - 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() {
phasedUnitsOfDependencies = new ArrayList<PhasedUnits>();
@@ -50,7 +55,8 @@ public void verifyModuleDependencyTree() {
final HashSet<Module> modulesCopy = new HashSet<Module>( context.getModules().getListOfModules() );
for (Module module : modulesCopy) {
dependencyTree.addLast(module);
- verifyModuleDependencyTree( module.getDependencies(), dependencyTree );
+ //we don't care about propagated dependency here as top modules are independent from one another
+ verifyModuleDependencyTree(module.getImports(), dependencyTree, new ArrayList<Module>());
dependencyTree.pollLast();
}
for (PhasedUnits units : phasedUnitsOfDependencies) {
@@ -59,27 +65,63 @@ public void verifyModuleDependencyTree() {
}
private void verifyModuleDependencyTree(
- Collection<Module> modules,
- LinkedList<Module> dependencyTree) {
- for (Module module : modules) {
- if ( dependencyTree.contains(module) ) {
+ Collection<ModuleImport> moduleImports,
+ LinkedList<Module> dependencyTree,
+ List<Module> propagatedDependencies) {
+ List<Module> visibleDependencies = new ArrayList<Module>();
+ visibleDependencies.add(dependencyTree.getLast()); //first addition => no possible conflict
+ for (ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.getModule();
+ if (moduleManager.findModule(module, dependencyTree, true) != null) {
//circular dependency
StringBuilder error = new StringBuilder("Circular dependency between modules: ");
buildDependencyString(dependencyTree, module, error);
error.append(".");
- System.err.println(error);
+ //TODO is there a better place than the top level module triggering the error?
+ //nested modules might not have representations in the src tree
+ moduleManager.addErrorToModule( dependencyTree.getFirst(), error.toString() );
return;
}
+ List<String> searchedArtifacts = new ArrayList<String>();
+ Iterable<String> searchedArtifactExtensions = moduleManager.getSearchedArtifactExtensions();
+
if ( ! module.isAvailable() ) {
//try and load the module from the repository
- final ArtifactProvider artifactProvider = context.getArtifactProvider();
- final ClosableVirtualFile src = artifactProvider.getArtifact(module.getName(), "0.1", "src");
- if (src == null) {
+ VirtualFile artifact = null;
+ List<ArtifactProvider> artifactProviders = context.getArtifactProviders();
+ for (final ArtifactProvider artifactProvider : artifactProviders) {
+ for (String extension : searchedArtifactExtensions) {
+ searchedArtifacts.add(artifactProvider.getArtifactName(module.getName(),
+ module.getVersion(), extension));
+ }
+ artifact = artifactProvider.getArtifact(module.getName(),
+ module.getVersion(),
+ searchedArtifactExtensions);
+ if (artifact != null) {
+ break;
+ }
+ }
+ if (artifact == null) {
//not there => error
- StringBuilder error = new StringBuilder("Cannot find module artifact ");
- error.append( artifactProvider.getArtifactName(module.getName(), "0.1", "src") )
- .append(" in local repository ('~/.ceylon/repo')")
- .append("\n\tDependency tree: ");
+ StringBuilder error = new StringBuilder("Cannot find module artifact(s) : ");
+ if (searchedArtifacts.size() > 0) {
+ error.append(searchedArtifacts.get(0));
+ }
+ for (String searchedArtifact : searchedArtifacts.subList(1, searchedArtifacts.size())) {
+ error.append(", ");
+ error.append("\n\t");
+ error.append(searchedArtifact);
+ }
+ error.append("\n\t in repositories : ");
+ if (artifactProviders.size() > 0) {
+ error.append(artifactProviders.get(0));
+ }
+ for (ArtifactProvider searchedProvider : artifactProviders.subList(1, artifactProviders.size())) {
+ error.append(", ");
+ error.append("\n\t");
+ error.append(searchedProvider);
+ }
+ error.append("\n\tDependency tree: ");
buildDependencyString(dependencyTree, module, error);
error.append(".");
if ( module.getLanguageModule() == module ) {
@@ -88,30 +130,66 @@ private void verifyModuleDependencyTree(
throw new LanguageModuleNotFoundException(error.toString());
}
else {
- moduleBuilder.addMissingDependencyError(module, error.toString());
+ //today we attach that to the module dependency
+ moduleManager.attachErrorToDependencyDeclaration(moduleImport, error.toString());
}
}
else {
- //parse module units and build module dependency and carry on
- PhasedUnits modulePhasedUnit = new PhasedUnits(context);
- phasedUnitsOfDependencies.add(modulePhasedUnit);
- modulePhasedUnit.parseUnit(src);
- src.close();
- module.setAvailable(true); // TODO : not necessary anymore ? since at least on module.ceylon
- // should have been parsed and should be applied buildModuleImport()
- final List<PhasedUnit> listOfUnits = modulePhasedUnit.getPhasedUnits();
- //populate module.getDependencies()
- for (PhasedUnit pu : listOfUnits) {
- pu.buildModuleImport();
+ try {
+ //parse module units and build module dependency and carry on
+ moduleManager.resolveModule(module, artifact, phasedUnitsOfDependencies);
+ } finally {
+ if (artifact instanceof ClosableVirtualFile) {
+ ((ClosableVirtualFile)artifact).close();
+ }
}
}
}
dependencyTree.addLast(module);
- verifyModuleDependencyTree( module.getDependencies(), dependencyTree );
+ List<Module> subModulePropagatedDependencies = new ArrayList<Module>();
+ verifyModuleDependencyTree( module.getImports(), dependencyTree, subModulePropagatedDependencies );
+ //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();
}
}
+ private void checkAndAddDependency(List<Module> dependencies, Module module, LinkedList<Module> dependencyTree) {
+ Module dupe = moduleManager.findModule(module, dependencies, false);
+ if (dupe != null && !isSameVersion(module, dupe)) {
+ //TODO improve by giving the dependency string leading to these two conflicting modules
+ StringBuilder error = new StringBuilder("Module (transitively) imports conflicting versions of ");
+ error.append(module.getNameAsString())
+ .append(". Version ").append(module.getVersion())
+ .append(" and version ").append(dupe.getVersion())
+ .append(" found and visible at the same time.");
+ moduleManager.addErrorToModule(dependencyTree.getFirst(), error.toString());
+ }
+ else {
+ dependencies.add(module);
+ }
+ }
+
+ private boolean isSameVersion(Module module, Module dupe) {
+ if (module == null || dupe == null) return false;
+ if (dupe.getVersion() == null) {
+ System.err.println("TypeChecker assertion failure: version should not be null in " +
+ "ModuleValidator.isSameVersion. Please report the issue with a test case");
+ return false;
+ }
+ return dupe.getVersion().equals(module.getVersion());
+ }
+
private void executeExternalModulePhases(PhasedUnits phasedUnits) {
//moduleimport phase already done
//Already called from within verifyModuleDependencyTree
View
211 src/com/redhat/ceylon/compiler/typechecker/analyzer/ModuleVisitor.java
@@ -1,10 +1,10 @@
package com.redhat.ceylon.compiler.typechecker.analyzer;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import com.redhat.ceylon.compiler.typechecker.model.Module;
+import com.redhat.ceylon.compiler.typechecker.model.ModuleImport;
import com.redhat.ceylon.compiler.typechecker.model.Package;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.BaseTypeExpression;
@@ -17,7 +17,7 @@
* In theory should only be called on module.ceylon and
* package.ceylon files
*
- * Put retrictions on how module.ceylon files are built today:
+ * Put restrictions on how module.ceylon files are built today:
* - names and versions must be string literals or else the
* visitor cannot extract them
* - imports must be "explicitly" defined, ie not imported as
@@ -35,14 +35,20 @@
* the dependencies declaration
*/
private Module mainModule;
- private final ModuleBuilder moduleBuilder;
+ private final ModuleManager moduleManager;
private final Package pkg;
private Tree.CompilationUnit unit;
+ private Phase phase = Phase.SRC_MODULE;
- public ModuleVisitor(ModuleBuilder moduleBuilder, Package pkg) {
- this.moduleBuilder = moduleBuilder;
+ public ModuleVisitor(ModuleManager moduleManager, Package pkg) {
+ this.moduleManager = moduleManager;
this.pkg = pkg;
}
+
+ public void setPhase(Phase phase) {
+ this.phase = phase;
+ }
+
@Override
public void visit(Tree.CompilationUnit that) {
@@ -56,103 +62,116 @@ public void visit(Tree.InvocationExpression that) {
if (p instanceof Tree.BaseTypeExpression) {
Identifier id = ((BaseTypeExpression) p).getIdentifier();
if (id!=null) {
- if (id.getText().equals("Module")) {
- Tree.SpecifiedArgument nsa = getArgument(that, "name");
- String moduleName = argumentToString(nsa);
- if (moduleName==null) {
- unit.addError("missing module name");
- }
- else {
- //mainModule = pkg.getModule();
- mainModule = moduleBuilder.getOrCreateModule(pkg.getName()); //in compiler the Package has a null Module
- if (mainModule == null) {
- unit.addError("A module cannot be defined at the top level of the hierarchy");
- }
- else {
- if ( !mainModule.getNameAsString().equals(moduleName) ) {
- nsa.addError("module name does not match descriptor location");
- }
- moduleBuilder.addErrorsToModule(mainModule, unit);
- mainModule.setDoc(argumentToString(getArgument(that, "doc")));
- mainModule.setLicense(argumentToString(getArgument(that, "license")));
- Tree.SpecifiedArgument vsa = getArgument(that, "version");
- String version = argumentToString(vsa);
- if (version==null) {
- unit.addError("missing module version");
- }
- else {
- if (version.isEmpty()) {
- vsa.addError("empty version identifier");
- }
- else {
- mainModule.setVersion(version);
- }
- }
- List<String> by = argumentToStrings(getArgument(that, "by"));
- if (by!=null) {
- mainModule.getAuthors().addAll(by);
- }
- mainModule.setAvailable(true);
- }
- }
+ switch (phase) {
+ case SRC_MODULE:
+ visitForSrcModulePhase(that,id);
+ break;
+ case REMAINING:
+ visitForRemainingPhase(that,id);
+ break;
}
- if (id.getText().equals("Import")) {
- Tree.SpecifiedArgument nsa = getArgument(that, "name");
- String moduleName = argumentToString(nsa);
- if (moduleName==null) {
- unit.addError("missing imported module name");
- }
- else {
- //TODO: do something with the specified version number!
- Module importedModule = moduleBuilder.getOrCreateModule(splitModuleName(moduleName));
- if (importedModule == null) {
- nsa.addError("A module cannot be defined at the top level of the hierarchy");
- }
- else {
- if (!mainModule.getDependencies().contains(importedModule)) {
- mainModule.getDependencies().add(importedModule);
- }
- moduleBuilder.addModuleDependencyDefinition(importedModule, nsa);
- Tree.SpecifiedArgument vsa = getArgument(that, "version");
- String version = argumentToString(vsa);
- if (version.isEmpty()) {
- vsa.addError("empty version identifier");
- }
- //TODO: this is wrong and temporary:
- if (importedModule.getVersion() == null) {
- importedModule.setVersion(version);
- }
- }
+ }
+ }
+ super.visit(that);
+ }
+
+ private void visitForSrcModulePhase(Tree.InvocationExpression that, Identifier id) {
+ if (id.getText().equals("Module")) {
+ Tree.SpecifiedArgument nsa = getArgument(that, "name");
+ String moduleName = argumentToString(nsa);
+ if (moduleName==null) {
+ unit.addError("missing module name");
+ }
+ else {
+ Tree.SpecifiedArgument vsa = getArgument(that, "version");
+ String version = argumentToString(vsa);
+ if (version==null) {
+ unit.addError("missing module version");
+ }
+ else {
+ if (version.isEmpty()) {
+ vsa.addError("empty version identifier");
}
}
- if (id.getText().equals("Package")) {
- Tree.SpecifiedArgument nsa = getArgument(that, "name");
- String packageName = argumentToString(nsa);
- if (packageName==null) {
- unit.addError("missing package name");
+ //mainModule = pkg.getModule();
+ mainModule = moduleManager.getOrCreateModule(pkg.getName(),version); //in compiler the Package has a null Module
+ if (mainModule == null) {
+ unit.addError("A module cannot be defined at the top level of the hierarchy");
+ }
+ else {
+ mainModule.setVersion(version);
+ if ( !mainModule.getNameAsString().equals(moduleName) ) {
+ nsa.addError("module name does not match descriptor location");
}
- else {
- if ( !pkg.getNameAsString().equals(packageName) ) {
- nsa.addError("package name does not match descriptor location");
- }
- pkg.setDoc(argumentToString(getArgument(that, "doc")));
- String shared = argumentToString(getArgument(that, "shared"));
- if (shared!=null && shared.equals("true")) {
- pkg.setShared(true);
- }
- List<String> by = argumentToStrings(getArgument(that, "by"));
- if (by!=null) {
- pkg.getAuthors().addAll(by);
- }
+ moduleManager.addLinkBetweenModuleAndNode(mainModule, unit);
+ mainModule.setDoc(argumentToString(getArgument(that, "doc")));
+ mainModule.setLicense(argumentToString(getArgument(that, "license")));
+ List<String> by = argumentToStrings(getArgument(that, "by"));
+ if (by!=null) {
+ mainModule.getAuthors().addAll(by);
}
+ mainModule.setAvailable(true);
}
}
}
- super.visit(that);
}
- private static List<String> splitModuleName(String moduleName) {
- return Arrays.asList(moduleName.split("[\\.]"));
+ private void visitForRemainingPhase(Tree.InvocationExpression that, Identifier id) {
+ if (id.getText().equals("Import")) {
+ Tree.SpecifiedArgument nsa = getArgument(that, "name");
+ String moduleName = argumentToString(nsa);
+ if (moduleName==null) {
+ unit.addError("missing imported module name");
+ }
+ else {
+ Tree.SpecifiedArgument vsa = getArgument(that, "version");
+ String version = argumentToString(vsa);
+ if (version.isEmpty()) {
+ vsa.addError("empty version identifier");
+ }
+ Module importedModule = moduleManager.getOrCreateModule(ModuleManager.splitModuleName(moduleName),version);
+ if (importedModule == null) {
+ nsa.addError("A module cannot be defined at the top level of the hierarchy");
+ }
+ else if (mainModule != null) {
+ if (importedModule.getVersion() == null) {
+ importedModule.setVersion(version);
+ }
+ String optionalString = argumentToString(getArgument(that, "optional"));
+ String exportString = argumentToString(getArgument(that, "export"));
+ ModuleImport moduleImport = moduleManager.findImport(mainModule, importedModule);
+ if (moduleImport == null) {
+ boolean optional = optionalString!=null && optionalString.equals("true");
+ boolean export = exportString!=null && exportString.equals("true");
+ moduleImport = new ModuleImport(importedModule, optional, export);
+ mainModule.getImports().add(moduleImport);
+ }
+ moduleManager.addModuleDependencyDefinition(moduleImport, nsa);
+ }
+ //else we leave it behind unprocessed
+ }
+ }
+ if (id.getText().equals("Package")) {
+ Tree.SpecifiedArgument nsa = getArgument(that, "name");
+ String packageName = argumentToString(nsa);
+ if (packageName==null) {
+ unit.addError("missing package name");
+ }
+ else {
+ if ( !pkg.getNameAsString().equals(packageName) ) {
+ nsa.addError("package name does not match descriptor location");
+ }
+ pkg.setDoc(argumentToString(getArgument(that, "doc")));
+ String shared = argumentToString(getArgument(that, "shared"));
+ if (shared!=null && shared.equals("true")) {
+ pkg.setShared(true);
+ }
+ List<String> by = argumentToStrings(getArgument(that, "by"));
+ if (by!=null) {
+ pkg.getAuthors().addAll(by);
+ }
+ }
+ }
}
private Tree.SpecifiedArgument getArgument(Tree.InvocationExpression that, String name) {
@@ -222,5 +241,11 @@ else if ( term instanceof Tree.BaseMemberExpression) {
return null;
}
}
-
+ public enum Phase {
+ SRC_MODULE,
+ REMAINING
+ }
+ public Module getMainModule() {
+ return mainModule;
+ }
}
View
21 src/com/redhat/ceylon/compiler/typechecker/context/Context.java
@@ -1,7 +1,12 @@
package com.redhat.ceylon.compiler.typechecker.context;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import com.redhat.ceylon.compiler.typechecker.io.ArtifactProvider;
import com.redhat.ceylon.compiler.typechecker.io.VFS;
+import com.redhat.ceylon.compiler.typechecker.io.VirtualFile;
import com.redhat.ceylon.compiler.typechecker.model.Modules;
/**
@@ -11,13 +16,21 @@
*/
public class Context {
- private ArtifactProvider artifactProvider;
+ private List<ArtifactProvider> artifactProviders;
private Modules modules;
private VFS vfs;
public Context(VFS vfs) {
this.vfs = vfs;
- this.artifactProvider = new ArtifactProvider(vfs);
+ this.artifactProviders = Arrays.asList(new ArtifactProvider(vfs));
+ }
+
+ public Context(Iterable<VirtualFile> repos, VFS vfs) {
+ this.vfs = vfs;
+ this.artifactProviders = new ArrayList<ArtifactProvider>();
+ for (VirtualFile repo : repos) {
+ artifactProviders.add(new ArtifactProvider(repo, vfs));
+ }
}
public Modules getModules() {
@@ -28,8 +41,8 @@ public void setModules(Modules modules) {
this.modules = modules;
}
- public ArtifactProvider getArtifactProvider() {
- return artifactProvider;
+ public List<ArtifactProvider> getArtifactProviders() {
+ return artifactProviders;
}
public VFS getVfs() {
View
33 src/com/redhat/ceylon/compiler/typechecker/context/PhasedUnit.java
@@ -10,7 +10,7 @@
import com.redhat.ceylon.compiler.typechecker.analyzer.DeclarationVisitor;
import com.redhat.ceylon.compiler.typechecker.analyzer.DependedUponVisitor;
import com.redhat.ceylon.compiler.typechecker.analyzer.ExpressionVisitor;
-import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleBuilder;
+import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleManager;
import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleVisitor;
import com.redhat.ceylon.compiler.typechecker.analyzer.RefinementVisitor;
import com.redhat.ceylon.compiler.typechecker.analyzer.SelfReferenceVisitor;
@@ -21,6 +21,7 @@
import com.redhat.ceylon.compiler.typechecker.analyzer.ValueVisitor;
import com.redhat.ceylon.compiler.typechecker.io.VirtualFile;
import com.redhat.ceylon.compiler.typechecker.model.Declaration;
+import com.redhat.ceylon.compiler.typechecker.model.Module;
import com.redhat.ceylon.compiler.typechecker.model.Package;
import com.redhat.ceylon.compiler.typechecker.model.Setter;
import com.redhat.ceylon.compiler.typechecker.model.TypeDeclaration;
@@ -43,28 +44,29 @@
private Unit unit;
//must be the non qualified file name
private String fileName;
- private final ModuleBuilder moduleBuilder;
+ private final ModuleManager moduleManager;
private final String pathRelativeToSrcDir;
private VirtualFile unitFile;
private final Set<PhasedUnit> dependentsOf = new HashSet<PhasedUnit>();
private List<CommonToken> tokens;
private boolean fullyTyped;
+ private ModuleVisitor moduleVisitor;
public PhasedUnit(VirtualFile unitFile, VirtualFile srcDir, Tree.CompilationUnit cu,
- Package p, ModuleBuilder moduleBuilder, Context context, List<CommonToken> tokenStream) {
+ Package p, ModuleManager moduleManager, Context context, List<CommonToken> tokenStream) {
this.compilationUnit = cu;
this.pkg = p;
this.unitFile = unitFile;
this.fileName = unitFile.getName();
this.pathRelativeToSrcDir = computeRelativePath(unitFile, srcDir);
- this.moduleBuilder = moduleBuilder;
+ this.moduleManager = moduleManager;
this.tokens = tokenStream;
}
@Deprecated
protected PhasedUnit(VirtualFile unitFile, VirtualFile srcDir, Tree.CompilationUnit cu,
- Package p, ModuleBuilder moduleBuilder, Context context) {
- this(unitFile, srcDir, cu, p, moduleBuilder, context, null);
+ Package p, ModuleManager moduleManager, Context context) {
+ this(unitFile, srcDir, cu, p, moduleManager, context, null);
}
private String computeRelativePath(VirtualFile unitFile, VirtualFile srcDir) {
@@ -80,11 +82,20 @@ else if ( rawRelativePath.startsWith("!/") ) {
}
}
- public void buildModuleImport() {
- if ( ModuleBuilder.MODULE_FILE.equals(fileName) ||
- ModuleBuilder.PACKAGE_FILE.equals(fileName) ) {
- final ModuleVisitor v = new ModuleVisitor(moduleBuilder, pkg);
- compilationUnit.visit(v);
+ public Module visitSrcModulePhase() {
+ if ( ModuleManager.MODULE_FILE.equals(fileName) ||
+ ModuleManager.PACKAGE_FILE.equals(fileName) ) {
+ moduleVisitor = new ModuleVisitor(moduleManager, pkg);
+ compilationUnit.visit(moduleVisitor);
+ return moduleVisitor.getMainModule();
+ }
+ return null;
+ }
+
+ public void visitRemainingModulePhase() {
+ if ( moduleVisitor != null ) {
+ moduleVisitor.setPhase(ModuleVisitor.Phase.REMAINING);
+ compilationUnit.visit(moduleVisitor);
}
}
View
36 src/com/redhat/ceylon/compiler/typechecker/context/PhasedUnits.java
@@ -10,7 +10,7 @@
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.CommonTokenStream;
-import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleBuilder;
+import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleManager;
import com.redhat.ceylon.compiler.typechecker.io.VirtualFile;
import com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer;
import com.redhat.ceylon.compiler.typechecker.parser.CeylonParser;
@@ -27,17 +27,17 @@
private Map<VirtualFile, PhasedUnit> phasedUnitPerFile = new LinkedHashMap<VirtualFile, PhasedUnit>();
private Map<String, PhasedUnit> phasedUnitPerRelativePath = new HashMap<String, PhasedUnit>();
private final Context context;
- private final ModuleBuilder moduleBuilder;
+ private final ModuleManager moduleManager;
public PhasedUnits(Context context) {
this.context = context;
- this.moduleBuilder = new ModuleBuilder(context);
- this.moduleBuilder.initCoreModules();
+ this.moduleManager = new ModuleManager(context);
+ this.moduleManager.initCoreModules();
}
- public PhasedUnits(Context context, ModuleBuilder moduleBuilder) {
+ public PhasedUnits(Context context, ModuleManager moduleManager) {
this.context = context;
- this.moduleBuilder = moduleBuilder;
+ this.moduleManager = moduleManager;
}
public void addPhasedUnit(VirtualFile unitFile, PhasedUnit phasedUnit) {
@@ -51,8 +51,8 @@ public void removePhasedUnitForRelativePath(String relativePath) {
this.phasedUnitPerFile.remove(phasedUnit.getUnitFile());
}
- public ModuleBuilder getModuleBuilder() {
- return moduleBuilder;
+ public ModuleManager getModuleManager() {
+ return moduleManager;
}
public List<PhasedUnit> getPhasedUnits() {
@@ -116,7 +116,7 @@ private void parseFile(VirtualFile file, VirtualFile srcDir) throws Exception {
List<CommonToken> tokens = new ArrayList<CommonToken>(tokenStream.getTokens().size());
tokens.addAll(tokenStream.getTokens());
PhasedUnit phasedUnit = new PhasedUnit(file, srcDir, cu,
- moduleBuilder.getCurrentPackage(), moduleBuilder,
+ moduleManager.getCurrentPackage(), moduleManager,
context, tokens);
addPhasedUnit(file, phasedUnit);
@@ -147,16 +147,26 @@ private void parseFileOrDirectory(VirtualFile file, VirtualFile srcDir) throws E
}
private void processDirectory(VirtualFile dir, VirtualFile srcDir) throws Exception {
- moduleBuilder.push(dir.getName());
+ moduleManager.push(dir.getName());
final List<VirtualFile> files = dir.getChildren();
for (VirtualFile file : files) {
- if (ModuleBuilder.MODULE_FILE.equals(file.getName())) {
- moduleBuilder.visitModuleFile();
+ if (ModuleManager.MODULE_FILE.equals(file.getName())) {
+ moduleManager.visitModuleFile();
}
}
for (VirtualFile file : files) {
parseFileOrDirectory(file, srcDir);
}
- moduleBuilder.pop();
+ moduleManager.pop();
+ }
+
+ public void visitModules() {
+ List<PhasedUnit> listOfUnits = getPhasedUnits();
+ for (PhasedUnit pu : listOfUnits) {
+ pu.visitSrcModulePhase();
+ }
+ for (PhasedUnit pu : listOfUnits) {
+ pu.visitRemainingModulePhase();
+ }
}
}
View
23 src/com/redhat/ceylon/compiler/typechecker/io/ArtifactProvider.java
@@ -19,18 +19,28 @@ public ArtifactProvider(VFS vfs) {
this.vfs = vfs;
}
+ public ArtifactProvider(VirtualFile homeRepo, VFS vfs) {
+ this.homeRepo = homeRepo;
+ this.vfs = vfs;
+ }
+
/**
* Return the artifact or null if not present
* Must be closed when done with it
*/
- public ClosableVirtualFile getArtifact(List<String> moduleName, String version, String extension) {
+ public ClosableVirtualFile getArtifact(List<String> moduleName, String version, Iterable<String> extensions) {
VirtualFile moduleDirectory = getModuleDirectory(moduleName, version);
if (moduleDirectory == null) {
return null;
}
- final VirtualFile child = getChild(moduleDirectory, getArtifactName(moduleName, version, extension) );
- //build sha1 and compare it
- return child == null ? null : vfs.openAsContainer(child);
+ for (String extension : extensions) {
+ final VirtualFile child = getChild(moduleDirectory, getArtifactName(moduleName, version, extension) );
+ if (child != null) {
+ //build sha1 and compare it
+ return vfs.openAsContainer(child);
+ }
+ }
+ return null;
}
/**
@@ -70,4 +80,9 @@ private VirtualFile getChild(VirtualFile parent, String name) {
}
return null;
}
+
+ @Override
+ public String toString() {
+ return homeRepo.getPath();
+ }
}
View
16 src/com/redhat/ceylon/compiler/typechecker/model/Module.java
@@ -8,7 +8,7 @@
private List<String> name;
private String version;
private List<Package> packages = new ArrayList<Package>();
- private List<Module> dependencies = new ArrayList<Module>();
+ private List<ModuleImport> imports = new ArrayList<ModuleImport>();
private Module languageModule;
private boolean available;
private String license;
@@ -49,8 +49,8 @@ public void setName(List<String> name) {
return list;
}
- public List<Module> getDependencies() {
- return dependencies;
+ public List<ModuleImport> getImports() {
+ return imports;
}
public Module getLanguageModule() {
@@ -72,8 +72,8 @@ public void setVersion(String version) {
public List<Package> getAllPackages() {
List<Package> list = new ArrayList<Package>();
list.addAll(packages);
- for (Module m: dependencies) {
- list.addAll(m.getSharedPackages());
+ for (ModuleImport mi: imports) {
+ list.addAll(mi.getModule().getSharedPackages());
}
return list;
}
@@ -81,8 +81,8 @@ public void setVersion(String version) {
List<Package> getAllKnownPackages() {
List<Package> list = new ArrayList<Package>();
list.addAll(packages);
- for (Module m: dependencies) {
- list.addAll(m.getPackages());
+ for (ModuleImport mi: imports) {
+ list.addAll(mi.getModule().getPackages());
}
return list;
}
@@ -109,7 +109,7 @@ public String getNameAsString() {
@Override
public String toString() {
- return "Module[" + getNameAsString() + "]";
+ return "Module[" + getNameAsString() + ", " + getVersion() + "]";
}
public String getDoc() {
View
41 src/com/redhat/ceylon/compiler/typechecker/model/ModuleImport.java
@@ -0,0 +1,41 @@
+package com.redhat.ceylon.compiler.typechecker.model;
+
+/**
+ * Describes data specific to module imports
+ *
+ * @author Emmanuel Bernard <emmanuel@hibernate.org>
+ */
+public class ModuleImport {
+ private final boolean optional;
+ private final boolean export;
+ private final Module module;
+
+ public ModuleImport(Module module, boolean optional, boolean export) {
+ this.module = module;
+ this.optional = optional;
+ this.export = export;
+ }
+
+ public boolean isOptional() {
+ return optional;
+ }
+
+ public boolean isExport() {
+ return export;
+ }
+
+ public Module getModule() {
+ return module;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("ModuleImport");
+ sb.append("{module=").append(module.getNameAsString()).append(", ").append(module.getVersion());
+ sb.append(", optional=").append(optional);
+ sb.append(", export=").append(export);
+ sb.append('}');
+ return sb.toString();
+ }
+}
View
0  test/aliases/Aliases.ceylon → test/main/aliases/Aliases.ceylon
File renamed without changes
View
0  test/aliases/Class.ceylon → test/main/aliases/Class.ceylon
File renamed without changes
View
0  test/aliases/Interface.ceylon → test/main/aliases/Interface.ceylon
File renamed without changes
View
0  test/animals/Animals.ceylon → test/main/animals/Animals.ceylon
File renamed without changes
View
0  test/annotations/Annotations.ceylon → test/main/annotations/Annotations.ceylon
File renamed without changes
View
0  test/capture/Capture.ceylon → test/main/capture/Capture.ceylon
File renamed without changes
View
11 test/main/com/redhat/sample/circularity/c1/module.ceylon
@@ -0,0 +1,11 @@
+@error; //circularity
+Module module {
+ name = 'com.redhat.sample.circularity.c1';
+ version = '0.2';
+ doc = "Test circularity in module dependency";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.sample.circularity.c2';
+ version = '0.1';
+ }
+}
View
11 test/main/com/redhat/sample/circularity/c2/module.ceylon
@@ -0,0 +1,11 @@
+@error; //curcilar dependency
+Module module {
+ name = 'com.redhat.sample.circularity.c2';
+ version = '0.1';
+ doc = "Test circularity in module dependency";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.sample.circularity.c1';
+ version = '0.2';
+ }
+}
View
0  .../com/redhat/sample/multisource/Boo.ceylon → .../com/redhat/sample/multisource/Boo.ceylon
File renamed without changes
View
0  ...at/sample/multisource/domain/Order.ceylon → ...at/sample/multisource/domain/Order.ceylon
File renamed without changes
View
2  ...m/redhat/sample/multisource/module.ceylon → ...m/redhat/sample/multisource/module.ceylon
@@ -2,7 +2,7 @@ Module module {
name = 'com.redhat.sample.multisource';
version = '0.2';
doc = "Test multi source file compilation";
- license = 'http://www.gnu.org/licenses/lgpl.html';
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
Import {
name = 'ceylon.language';
version = '0.1';
View
0  ...e/multisource/service/OrderService.ceylon → ...e/multisource/service/OrderService.ceylon
File renamed without changes
View
2  ...redhat/sample/nestedmodules/module.ceylon → ...redhat/sample/nestedmodules/module.ceylon
@@ -3,5 +3,5 @@ Module module {
name = 'com.redhat.sample.nestedmodules';
version = '0.2';
doc = "Test modules within modules";
- license = 'http://www.gnu.org/licenses/lgpl.html';
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
}
View
2  ...at/sample/nestedmodules/sub/module.ceylon → ...at/sample/nestedmodules/sub/module.ceylon
@@ -3,5 +3,5 @@ Module module {
name = 'com.redhat.sample.nestedmodules.sub';
version = '0.2';
doc = "Test modules within modules";
- license = 'http://www.gnu.org/licenses/lgpl.html';
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
}
View
0  test/controlflow/BreakContinue.ceylon → test/main/controlflow/BreakContinue.ceylon
File renamed without changes
View
0  test/controlflow/DefiniteReturn.ceylon → test/main/controlflow/DefiniteReturn.ceylon
File renamed without changes
View
0  test/declarations/Circularities.ceylon → test/main/declarations/Circularities.ceylon
File renamed without changes
View
0  test/declarations/ClassBodies.ceylon → test/main/declarations/ClassBodies.ceylon
File renamed without changes
View
0  test/declarations/ClassDeclarations.ceylon → ...ain/declarations/ClassDeclarations.ceylon
File renamed without changes
View
0  test/declarations/ClassMembers.ceylon → test/main/declarations/ClassMembers.ceylon
File renamed without changes
View
0  test/declarations/Declarations.ceylon → test/main/declarations/Declarations.ceylon
File renamed without changes
View
0  test/declarations/Formal.ceylon → test/main/declarations/Formal.ceylon
File renamed without changes
View
0  test/declarations/GettersSetters.ceylon → test/main/declarations/GettersSetters.ceylon
File renamed without changes
View
0  test/declarations/Hiding.ceylon → test/main/declarations/Hiding.ceylon
File renamed without changes
View
0  ...declarations/InterfaceDeclarations.ceylon → ...declarations/InterfaceDeclarations.ceylon
File renamed without changes
View
0  test/declarations/InterfaceMembers.ceylon → ...main/declarations/InterfaceMembers.ceylon
File renamed without changes
View
0  test/declarations/ObjectDeclarations.ceylon → ...in/declarations/ObjectDeclarations.ceylon
File renamed without changes
View
0  test/declarations/ParameterHiding.ceylon → .../main/declarations/ParameterHiding.ceylon
File renamed without changes
View
0  test/declarations/Parameters.ceylon → test/main/declarations/Parameters.ceylon
File renamed without changes
View
0  test/declarations/Toplevel.ceylon → test/main/declarations/Toplevel.ceylon
File renamed without changes
View
0  test/declarations/thisSuperOuter.ceylon → test/main/declarations/thisSuperOuter.ceylon
File renamed without changes
View
0  test/family/BasicGraph.ceylon → test/main/family/BasicGraph.ceylon
File renamed without changes
View
0  test/family/Graph.ceylon → test/main/family/Graph.ceylon
File renamed without changes
View
0  test/family/OnOffGraph.ceylon → test/main/family/OnOffGraph.ceylon
File renamed without changes
View
0  test/family/test.ceylon → test/main/family/test.ceylon
File renamed without changes
View
0  test/family2/BasicGraph.ceylon → test/main/family2/BasicGraph.ceylon
File renamed without changes
View
0  test/family2/Graph.ceylon → test/main/family2/Graph.ceylon
File renamed without changes
View
0  test/family2/OnOffGraph.ceylon → test/main/family2/OnOffGraph.ceylon
File renamed without changes
View
0  test/family2/test.ceylon → test/main/family2/test.ceylon
File renamed without changes
View
0  test/function/Comprehensions.ceylon → test/main/function/Comprehensions.ceylon
File renamed without changes
View
0  test/function/FunctionTypes.ceylon → test/main/function/FunctionTypes.ceylon
File renamed without changes
View
0  test/function/SequencedTypeArgs.ceylon → test/main/function/SequencedTypeArgs.ceylon
File renamed without changes
View
0  test/imports/package/Alias.ceylon → test/main/imports/package/Alias.ceylon
File renamed without changes
View
0  test/imports/package/Class.ceylon → test/main/imports/package/Class.ceylon
File renamed without changes
View
0  test/imports/package/Dupe.ceylon → test/main/imports/package/Dupe.ceylon
File renamed without changes
View
0  test/imports/package/Interface.ceylon → test/main/imports/package/Interface.ceylon
File renamed without changes
View
0  test/imports/package/attribute.ceylon → test/main/imports/package/attribute.ceylon
File renamed without changes
View
0  test/imports/package/method.ceylon → test/main/imports/package/method.ceylon
File renamed without changes
View
0  test/imports/test/Dupe.ceylon → test/main/imports/test/Dupe.ceylon
File renamed without changes
View
0  test/imports/test/Test.ceylon → test/main/imports/test/Test.ceylon
File renamed without changes
View
0  test/imports/test/TestAliases.ceylon → test/main/imports/test/TestAliases.ceylon
File renamed without changes
View
0  test/imports/test/TestWildcard.ceylon → test/main/imports/test/TestWildcard.ceylon
File renamed without changes
View
2  test/module.ceylon → test/main/module.ceylon
@@ -3,5 +3,5 @@ Module module {
name = '';
version = '0.2';
doc = "Test for illegal top level module";
- license = 'http://www.gnu.org/licenses/lgpl.html';
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
}
View
0  test/observable/Display.ceylon → test/main/observable/Display.ceylon
File renamed without changes
View
0  test/observable/List.ceylon → test/main/observable/List.ceylon
File renamed without changes
View
0  test/observable/Model.ceylon → test/main/observable/Model.ceylon
File renamed without changes
View
0  test/observable/Observer.ceylon → test/main/observable/Observer.ceylon
File renamed without changes
View
0  test/observable/Subject.ceylon → test/main/observable/Subject.ceylon
File renamed without changes
View
0  test/observable/callGenericUpdate.ceylon → .../main/observable/callGenericUpdate.ceylon
File renamed without changes
View
0  test/refinement/ActualFormalDefault.ceylon → ...ain/refinement/ActualFormalDefault.ceylon
File renamed without changes
View
0  test/refinement/FormalActual.ceylon → test/main/refinement/FormalActual.ceylon
File renamed without changes
View
0  test/refinement/GenericRefinement.ceylon → .../main/refinement/GenericRefinement.ceylon
File renamed without changes
View
0  test/refinement/MultipleInheritance.ceylon → ...ain/refinement/MultipleInheritance.ceylon
File renamed without changes
View
0  test/refinement/Refinement.ceylon → test/main/refinement/Refinement.ceylon
File renamed without changes
View
0  test/specification/Children.ceylon → test/main/specification/Children.ceylon
File renamed without changes
View
0  test/specification/DefiniteAssignment.ceylon → ...n/specification/DefiniteAssignment.ceylon
File renamed without changes
View
0  ...pecification/DefiniteSpecification.ceylon → ...pecification/DefiniteSpecification.ceylon
File renamed without changes
View
0  test/specification/SelfReference.ceylon → test/main/specification/SelfReference.ceylon
File renamed without changes
View
0  test/specification/Test.ceylon → test/main/specification/Test.ceylon
File renamed without changes
View
0  test/statements/ControlStructures.ceylon → .../main/statements/ControlStructures.ceylon
File renamed without changes
View
0  test/statements/SequencedArguments.ceylon → ...main/statements/SequencedArguments.ceylon
File renamed without changes
View
0  test/statements/Statements.ceylon → test/main/statements/Statements.ceylon
File renamed without changes
View
0  test/typing/Assignability.ceylon → test/main/typing/Assignability.ceylon
File renamed without changes
View
0  test/typing/Generics.ceylon → test/main/typing/Generics.ceylon
File renamed without changes
View
0  test/typing/Hierarchy.ceylon → test/main/typing/Hierarchy.ceylon
File renamed without changes
View
0  test/typing/Inheritance.ceylon → test/main/typing/Inheritance.ceylon
File renamed without changes
View
0  test/typing/InheritanceConsistency.ceylon → ...main/typing/InheritanceConsistency.ceylon
File renamed without changes
View
0  test/typing/Intersection.ceylon → test/main/typing/Intersection.ceylon
File renamed without changes
View
0  test/typing/Is.ceylon → test/main/typing/Is.ceylon
File renamed without changes
View
0  test/typing/LanguageModule.ceylon → test/main/typing/LanguageModule.ceylon
File renamed without changes
View
0  test/typing/Literals.ceylon → test/main/typing/Literals.ceylon
File renamed without changes
View
0  test/typing/NestedCases.ceylon → test/main/typing/NestedCases.ceylon
File renamed without changes
View
0  test/typing/Operators.ceylon → test/main/typing/Operators.ceylon
File renamed without changes
View
0  test/typing/Optional.ceylon → test/main/typing/Optional.ceylon
File renamed without changes
View
0  test/typing/OuterTypeArgs.ceylon → test/main/typing/OuterTypeArgs.ceylon
File renamed without changes
View
0  test/typing/Primaries.ceylon → test/main/typing/Primaries.ceylon
File renamed without changes
View
0  test/typing/RecursiveVariance.ceylon → test/main/typing/RecursiveVariance.ceylon
File renamed without changes
View
0  test/typing/Restriction.ceylon → test/main/typing/Restriction.ceylon
File renamed without changes
View
0  test/typing/SelfType.ceylon → test/main/typing/SelfType.ceylon
File renamed without changes
View
0  test/typing/TypeArgInference.ceylon → test/main/typing/TypeArgInference.ceylon
File renamed without changes
View
0  test/typing/TypeInference.ceylon → test/main/typing/TypeInference.ceylon
File renamed without changes
View
0  test/typing/Union.ceylon → test/main/typing/Union.ceylon
File renamed without changes
View
0  test/visibility/Hiding.ceylon → test/main/visibility/Hiding.ceylon
File renamed without changes
View
0  test/visibility/Hierarchy.ceylon → test/main/visibility/Hierarchy.ceylon
File renamed without changes
View
0  test/visibility/TypedVisibility.ceylon → test/main/visibility/TypedVisibility.ceylon
File renamed without changes
View
0  test/visibility/Unit1.ceylon → test/main/visibility/Unit1.ceylon
File renamed without changes
View
0  test/visibility/Unit2.ceylon → test/main/visibility/Unit2.ceylon
File renamed without changes
View
0  test/visibility/package/Unit3.ceylon → test/main/visibility/package/Unit3.ceylon
File renamed without changes
View
0  test/visibility/package/Unit4.ceylon → test/main/visibility/package/Unit4.ceylon
File renamed without changes
View
0  test/visibility/package/Unit5.ceylon → test/main/visibility/package/Unit5.ceylon
File renamed without changes
View
0  test/visibility/package/Unit6.ceylon → test/main/visibility/package/Unit6.ceylon
File renamed without changes
View
10 test/moduledep1/com/redhat/ceylon/compiler/typechecker/test/module/a/module.ceylon
@@ -0,0 +1,10 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.a';
+ version = '1';
+ doc = "Some module";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.b';
+ version = '1';
+ }
+}
View
6 test/moduledep1/com/redhat/ceylon/compiler/typechecker/test/module/b/module.ceylon
@@ -0,0 +1,6 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.b';
+ version = '1';
+ doc = "Some module";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+}
View
11 test/moduledep1/com/redhat/ceylon/compiler/typechecker/test/module/c/module.ceylon
@@ -0,0 +1,11 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.c';
+ version = '1';
+ doc = "Some module";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.d';
+ version = '1';
+ export = true;
+ }
+}
View
6 test/moduledep1/com/redhat/ceylon/compiler/typechecker/test/module/d/module.ceylon
@@ -0,0 +1,6 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.d';
+ version = '1';
+ doc = "Some module";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+}
View
10 test/moduledep2/com/redhat/ceylon/compiler/typechecker/test/module/b/module.ceylon
@@ -0,0 +1,10 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.b';
+ version = '2';
+ doc = "Some module";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.a';
+ version = '1';
+ }
+}
View
6 test/moduledep2/com/redhat/ceylon/compiler/typechecker/test/module/c/module.ceylon
@@ -0,0 +1,6 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.c';
+ version = '2';
+ doc = "Some module";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+}
View
6 test/moduledep2/com/redhat/ceylon/compiler/typechecker/test/module/d/module.ceylon
@@ -0,0 +1,6 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.d';
+ version = '2';
+ doc = "Some module";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+}
View
15 ...duletest/com/redhat/ceylon/compiler/typechecker/test/module/testdiffversion/module.ceylon
@@ -0,0 +1,15 @@
+@error;
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.testdiffversion';
+ version = '1';
+ doc = "Test that multiple imports from different versions at the same level fail";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.c';
+ version = '1';
+ },
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.c';
+ version = '2';
+ }
+}
View
15 ...st/com/redhat/ceylon/compiler/typechecker/test/module/testdiffversionexport/module.ceylon
@@ -0,0 +1,15 @@
+@error;
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.testdiffversionexport';
+ version = '1';
+ doc = "Test imports from different versions fails if visible in the same scope (via export)";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.c';
+ version = '1';
+ },
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.d';
+ version = '2';
+ }
+}
View
14 ...test/com/redhat/ceylon/compiler/typechecker/test/module/testexportisolation/module.ceylon
@@ -0,0 +1,14 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.testexportisolation';
+ version = '1';
+ doc = "Test that different versions can coexist if they are not visible at the same time";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.a';
+ version = '1';
+ },
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.b';
+ version = '2';
+ }
+}
View
14 ...test/com/redhat/ceylon/compiler/typechecker/test/module/testsameversionwork/module.ceylon
@@ -0,0 +1,14 @@
+Module module {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.testsameversionwork';
+ version = '1';
+ doc = "Test that multiple imports from the same version even when visible to each other works";
+ license = 'http://www.apache.org/licenses/LICENSE-2.0.html';
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.c';
+ version = '1';
+ },
+ Import {
+ name = 'com.redhat.ceylon.compiler.typechecker.test.module.d';
+ version = '1';
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.