diff --git a/.classpath b/.classpath
index 16d067f..640b871 100644
--- a/.classpath
+++ b/.classpath
@@ -2,6 +2,7 @@
+
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
index b478fe5..a2c0561 100644
--- a/META-INF/MANIFEST.MF
+++ b/META-INF/MANIFEST.MF
@@ -9,7 +9,8 @@ Require-Bundle: org.eclipse.ui,
org.strategoxt.strj,
org.spoofax.jsglr,
org.eclipse.jdt.core,
- org.spoofax.terms
+ org.spoofax.terms,
+ org.junit
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Export-Package: org.sugarj.common,
diff --git a/build.properties b/build.properties
index 34d2e4d..237d94f 100644
--- a/build.properties
+++ b/build.properties
@@ -1,4 +1,5 @@
-source.. = src/
+source.. = src/,\
+ test/
output.. = bin/
bin.includes = META-INF/,\
.
diff --git a/src/org/sugarj/common/cleardep/CompilationUnit.java b/src/org/sugarj/common/cleardep/CompilationUnit.java
index 4d1963a..8a4e4be 100644
--- a/src/org/sugarj/common/cleardep/CompilationUnit.java
+++ b/src/org/sugarj/common/cleardep/CompilationUnit.java
@@ -21,7 +21,11 @@
import org.sugarj.util.Pair;
/**
- * Dependency management for modules.
+ * Dependency management for modules.
+ *
+ * For each module there are two CompilationUnits. One for automatic
+ * compilations (generates only temporary files) and one for "real" compilation
+ * that may use already generated files (if valid)
*
* @author Sebastian Erdweg
*/
@@ -37,17 +41,55 @@ public CompilationUnit() { /* for deserialization only */ }
protected Synthesizer syn;
+ /**
+ * if this == compiledCompilationUnit -> temporary directory
+ * if this == editedCompilationUnit -> i.e. /bin folder
+ */
protected Path targetDir;
+
+ /**
+ * source files
+ */
protected Map sourceArtifacts;
+
protected Set moduleDependencies;
- protected Set circularModuleDependencies;
+ protected Set circularModuleDependencies;
+
protected Map externalFileDependencies;
+
protected Map generatedFiles;
// **************************
// Methods for initialization
// **************************
+ /**
+ *
+ * @param cl
+ * @param stamper
+ * @param compileDep
+ * path to the persisted compiledCompilationUnit (.dep file)
+ * @param compileTarget
+ * i.e.: /bin folder
+ * @param editedDep
+ * path to the persisted editedCompilationUnit (.dep file)
+ * @param editedTarget
+ * i.e.: some temporary folder
+ * @param sourceFiles
+ * @param editedSourceFiles
+ * is empty or null, except source has been edited
+ * @param mode
+ *
+ * @param syn
+ * == null, except for generated modules (which are a product of a
+ * transformation on another module)
+ * @return
+ *
+ * - edited mode -> editedCompilationUnit
+ *
- compiled mode -> compiledCompilationUnit
+ *
+ * @throws IOException
+ */
@SuppressWarnings("unchecked")
final protected static E create(Class cl, Stamper stamper, Path compileDep, Path compileTarget, Path editedDep, Path editedTarget, Set sourceFiles, Map editedSourceFiles, Mode mode, Synthesizer syn) throws IOException {
E compileE;
@@ -90,6 +132,22 @@ final protected static E create(Class cl, Stamper
return e;
}
+ /**
+ * a) mode == DoCompileMode (true) checks all files in the compileTarget
+ * folder (i.e. /bin) and all other dependent modules for consistency
+ *
+ * @param cl
+ * @param stamper
+ * @param compileDep
+ * path to the persisted compiledCompilationUnit (.dep file)
+ * @param editedDep
+ * path to the persisted editedCompilationUnit (.dep file)
+ * @param editedSourceFiles
+ * is empty / null, except source has been edited
+ * @param mode
+ * @return
+ * @throws IOException
+ */
@SuppressWarnings("unchecked")
final protected static Pair read(Class cl, Stamper stamper, Path compileDep, Path editedDep, Map editedSourceFiles, Mode mode) throws IOException {
E compileE = PersistableEntity.read(cl, stamper, compileDep);
@@ -116,9 +174,15 @@ final protected static Pair read(ClasseditedCompilationUnit to a compiledCompilationUnit
+ * @param compiled
+ */
protected void copyContentTo(CompilationUnit compiled) {
compiled.sourceArtifacts.putAll(sourceArtifacts);
+ // TODO: shouldn't the synthesizer also be copied?
+
for (CompilationUnit dep : moduleDependencies)
if (dep.compiledCompilationUnit == null)
compiled.addModuleDependency(dep);
@@ -138,6 +202,10 @@ protected void copyContentTo(CompilationUnit compiled) {
compiled.addGeneratedFile(FileCommands.tryCopyFile(targetDir, compiled.targetDir, p));
}
+ /**
+ * Copies contents of all dependent (consistent) editedCompilationUnits to compiledCompilationUnits
+ * @throws IOException
+ */
protected void liftEditedToCompiled() throws IOException {
ModuleVisitor liftVisitor = new ModuleVisitor() {
@Override public Void visit(CompilationUnit mod, Mode mode) {
@@ -207,12 +275,29 @@ public void addGeneratedFile(Path file, int stampOfFile) {
generatedFiles.put(file, stampOfFile);
}
+ /**
+ * use addModuleDependency(...) instead
+ */
+ @Deprecated
public void addCircularModuleDependency(CompilationUnit mod) {
circularModuleDependencies.add(mod);
}
- public void addModuleDependency(CompilationUnit mod) {
+ /**
+ * @return true if mod was added to moduleDependencies
+ * false if mod was added to circularModuleDependencies
+ */
+ public boolean addModuleDependency(final CompilationUnit mod) {
+
+ if (mod.dependsOnTransitively(this) || this.dependsOnTransitively(mod)) {
+
+ circularModuleDependencies.add(mod);
+ return false;
+ }
+
moduleDependencies.add(mod);
+ return true;
+
}
@@ -220,6 +305,10 @@ public void addModuleDependency(CompilationUnit mod) {
// Methods for querying dependencies
// *********************************
+ /**
+ * is edited ...
+ * @return
+ */
public boolean isParsedCompilationUnit() {
return compiledCompilationUnit != null;
}
@@ -237,16 +326,23 @@ public boolean dependsOnTransitivelyNoncircularly(CompilationUnit other) {
return false;
}
+ /**
+ * Depends on directly
+ * @param other
+ * @return
+ */
public boolean dependsOn(CompilationUnit other) {
return moduleDependencies.contains(other) || circularModuleDependencies.contains(other);
}
public boolean dependsOnTransitively(CompilationUnit other) {
+
if (dependsOn(other))
return true;
for (CompilationUnit mod : moduleDependencies)
if (mod.dependsOnTransitively(other))
return true;
+
return false;
}
@@ -309,6 +405,12 @@ public Synthesizer getSynthesizer() {
protected abstract boolean isConsistentExtend(Mode mode);
+ /**
+ * @param editedSourceFiles
+ * @param mode
+ * TODO: unused?
+ * @return
+ */
protected boolean isConsistentWithSourceArtifacts(Map editedSourceFiles, Mode mode) {
if (sourceArtifacts.isEmpty())
return false;
@@ -325,6 +427,19 @@ else if (stamp == null && (!FileCommands.exists(e.getKey()) || e.getValue() != s
return true;
}
+ /**
+ * Checks consistency only for this module's ...
+ *
+ * - source files
+ *
- generated files
+ *
- external file dependencies
+ *
+ *
+ * @param editedSourceFiles
+ * @param mode
+ * (compiled / edited / ... )
+ * @return
+ */
public boolean isConsistentShallow(Map editedSourceFiles, Mode mode) {
if (hasPersistentVersionChanged())
return false;
@@ -346,6 +461,14 @@ public boolean isConsistentShallow(Map editedSourceFiles,
return true;
}
+ /**
+ * Checks consistency of this module including its module dependencies
+ *
+ * @param editedSourceFiles
+ * @param mode
+ * (compiled / edited / ... )
+ * @return
+ */
public boolean isConsistent(final Map editedSourceFiles, Mode mode) {
ModuleVisitor isConsistentVisitor = new ModuleVisitor() {
@Override public Boolean visit(CompilationUnit mod, Mode mode) { return mod.isConsistentShallow(editedSourceFiles, mode); }
@@ -411,12 +534,16 @@ private Pair