for each chunk: delete output corresponding to modified sources before running builders
authorEugene Zhuravlev <jeka@intellij.com>
Sat, 28 Jan 2012 12:41:32 +0000 (13:41 +0100)
committerEugene Zhuravlev <jeka@intellij.com>
Sat, 28 Jan 2012 12:41:32 +0000 (13:41 +0100)
java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java
jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java

index 29578d6817e017cb6845b28a1ddb8dee4828604b..d34ce9d92a7bee2e2545bd6aef9a0c3b17cfe82c 100644 (file)
@@ -281,7 +281,10 @@ public class CompileServerManager implements ApplicationComponent{
       processHandler.addProcessListener(new ProcessAdapter() {
         public void onTextAvailable(ProcessEvent event, Key outputType) {
           // re-translate server's output to idea.log
-          LOG.info("COMPILE_SERVER [" +outputType.toString() +"]: "+ event.getText());
+          final String text = event.getText();
+          if (!StringUtil.isEmpty(text)) {
+            LOG.info("COMPILE_SERVER [" +outputType.toString() +"]: "+ text);
+          }
         }
       });
       processHandler.addProcessListener(new ProcessAdapter() {
index de2a9db7a4082e434291f4fc14e6dd3282025b32..55314ebd1cc6c1c700f08269b0cb971971b79280 100644 (file)
@@ -340,7 +340,7 @@ public class IncProjectBuilder {
     }
   }
 
-  private void runBuilders(CompileContext context, ModuleChunk chunk, BuilderCategory category) throws ProjectBuildException {
+  private void runBuilders(final CompileContext context, ModuleChunk chunk, BuilderCategory category) throws ProjectBuildException {
     final List<ModuleLevelBuilder> builders = myBuilderRegistry.getBuilders(category);
     if (builders.isEmpty()) {
       return;
@@ -354,6 +354,11 @@ public class IncProjectBuilder {
     do {
       nextPassRequired = false;
       context.beforeNextCompileRound(chunk);
+
+      if (!context.isProjectRebuild()) {
+        syncOutputFiles(context, chunk);
+      }
+
       for (ModuleLevelBuilder builder : builders) {
         final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk);
 
@@ -380,4 +385,34 @@ public class IncProjectBuilder {
     }
     while (nextPassRequired);
   }
+
+  private static void syncOutputFiles(CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
+    final BuildDataManager dataManager = context.getDataManager();
+    final boolean compilingTests = context.isCompilingTests();
+    try {
+      context.processFilesToRecompile(chunk, new FileProcessor() {
+        private final Map<Module, SourceToOutputMapping> storageMap = new HashMap<Module, SourceToOutputMapping>();
+        @Override
+        public boolean apply(Module module, File file, String sourceRoot) throws Exception {
+          SourceToOutputMapping srcToOut = storageMap.get(module);
+          if (srcToOut == null) {
+            srcToOut = dataManager.getSourceToOutputMap(module.getName().toLowerCase(Locale.US), compilingTests);
+            storageMap.put(module, srcToOut);
+          }
+          final String srcPath = FileUtil.toSystemIndependentName(file.getPath());
+          final Collection<String> outputs = srcToOut.getState(srcPath);
+          if (outputs != null) {
+            for (String output : outputs) {
+              FileUtil.delete(new File(output));
+            }
+            srcToOut.remove(srcPath);
+          }
+          return true;
+        }
+      });
+    }
+    catch (Exception e) {
+      throw new ProjectBuildException(e);
+    }
+  }
 }
index fbd250eaa5bfb1121884e406b2b1a404e5e4d489..c05d6085d356e255e7fb81e0c535c5ac93fcef58 100644 (file)
@@ -2,15 +2,16 @@ package org.jetbrains.jps.incremental;
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.io.FileUtil;
 import org.jetbrains.ether.dependencyView.Mappings;
 import org.jetbrains.jps.Module;
 import org.jetbrains.jps.ModuleChunk;
-import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
 
 import java.io.File;
 import java.io.IOException;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 
 /**
  * @author Eugene Zhuravlev
@@ -114,25 +115,6 @@ public abstract class ModuleLevelBuilder extends Builder {
     }
   }
 
-  // delete all class files that according to mappings correspond to given sources
-  public static void deleteCorrespondingOutputFiles(CompileContext context, Map<File, Module> sources) throws Exception {
-    if (!context.isProjectRebuild() && !sources.isEmpty()) {
-      for (Map.Entry<File, Module> pair : sources.entrySet()) {
-        final File file = pair.getKey();
-        final String srcPath = FileUtil.toSystemIndependentName(file.getPath());
-        final String moduleName = pair.getValue().getName().toLowerCase(Locale.US);
-        final SourceToOutputMapping srcToOut = context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests());
-        final Collection<String> outputs = srcToOut.getState(srcPath);
-        if (outputs != null) {
-          for (String output : outputs) {
-            FileUtil.delete(new File(output));
-          }
-          srcToOut.remove(srcPath);
-        }
-      }
-    }
-  }
-
   private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set<File> affected) throws Exception {
     final Set<Module> chunkModules = new HashSet<Module>(chunk.getModules());
     if (!chunkModules.isEmpty()) {
index 7f8be2cb10a2647cd95f1cde35f1f8e8e151588a..0d3d9a82aac5631987fa8abc4110f98dbba33abe 100644 (file)
@@ -45,14 +45,14 @@ public class GroovyBuilder extends ModuleLevelBuilder {
 
   public ModuleLevelBuilder.ExitCode build(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
     ExitCode exitCode = ExitCode.OK;
-    final Map<File, Module> toCompile = new HashMap<File, Module>();
+    final List<File> toCompile = new ArrayList<File>();
     try {
       context.processFilesToRecompile(chunk, new FileProcessor() {
         @Override
         public boolean apply(Module module, File file, String sourceRoot) throws Exception {
           final String path = file.getPath();
           if (isGroovyFile(path)) { //todo file type check
-            toCompile.put(file, module);
+            toCompile.add(file);
           }
           return true;
         }
@@ -81,7 +81,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
       assert dir != null;
 
       final Set<String> toCompilePaths = new LinkedHashSet<String>();
-      for (File file : toCompile.keySet()) {
+      for (File file : toCompile) {
         toCompilePaths.add(FileUtil.toSystemIndependentName(file.getPath()));
       }
       
@@ -114,8 +114,6 @@ public class GroovyBuilder extends ModuleLevelBuilder {
         Arrays.<String>asList(myForStubs ? "stubs" : "groovyc", tempFile.getPath())
       );
 
-      deleteCorrespondingOutputFiles(context, toCompile);
-
       List<GroovycOSProcessHandler.OutputItem> successfullyCompiled = Collections.emptyList();
       try {
         final Process process = Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));
@@ -174,7 +172,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
           }
 
 
-          final boolean needSecondPass = updateMappings(context, delta, chunk, toCompile.keySet(), successfullyCompiledFiles);
+          final boolean needSecondPass = updateMappings(context, delta, chunk, toCompile, successfullyCompiledFiles);
           if (needSecondPass) {
             exitCode = ExitCode.ADDITIONAL_PASS_REQUIRED;
           }
index 2d1436612939fa9cdedf5759f887065baa097876..bd74b495743ff7d93f160564777382dbb833cea0 100644 (file)
@@ -125,13 +125,13 @@ public class JavaBuilder extends ModuleLevelBuilder {
 
   public ExitCode build(final CompileContext context, final ModuleChunk chunk) throws ProjectBuildException {
     try {
-      final Map<File, Module> filesToCompile = new HashMap<File, Module>();
-      final List<File> formsToCompile = new ArrayList<File>();
+      final Set<File> filesToCompile = new HashSet<File>();
+      final Set<File> formsToCompile = new HashSet<File>();
 
       context.processFilesToRecompile(chunk, new FileProcessor() {
         public boolean apply(Module module, File file, String sourceRoot) throws Exception {
           if (JAVA_SOURCES_FILTER.accept(file)) {
-            filesToCompile.put(file, module);
+            filesToCompile.add(file);
           }
           else if (FORM_SOURCES_FILTER.accept(file)) {
             formsToCompile.add(file);
@@ -141,37 +141,38 @@ public class JavaBuilder extends ModuleLevelBuilder {
       });
 
       // force compilation of bound source file if the form is dirty
-      for (File form : formsToCompile) {
-        final RootDescriptor descriptor = context.getModuleAndRoot(form);
-        if (descriptor != null) {
-          for (RootDescriptor rd : context.getModuleRoots(descriptor.module)) {
-            final File boundSource = getBoundSource(rd.root, form);
-            if (boundSource != null) {
-              filesToCompile.put(boundSource, rd.module);
-              break;
+      if (!context.isProjectRebuild()) {
+        for (File form : formsToCompile) {
+          final RootDescriptor descriptor = context.getModuleAndRoot(form);
+          if (descriptor != null) {
+            for (RootDescriptor rd : context.getModuleRoots(descriptor.module)) {
+              final File boundSource = getBoundSource(rd.root, form);
+              if (boundSource != null) {
+                filesToCompile.add(boundSource);
+                break;
+              }
             }
           }
         }
-      }
 
-      // form should be considered dirty if the class it is bound to is dirty
-      final SourceToFormMapping sourceToFormMap = context.getDataManager().getSourceToFormMap();
-      for (File srcFile : filesToCompile.keySet()) {
-        final String srcPath = srcFile.getPath();
-        final String formPath = sourceToFormMap.getState(srcPath);
-        if (formPath != null) {
-          final File formFile = new File(formPath);
-          if (formFile.exists()) {
-            context.markDirty(formFile);
-            formsToCompile.add(formFile);
+        // form should be considered dirty if the class it is bound to is dirty
+        final SourceToFormMapping sourceToFormMap = context.getDataManager().getSourceToFormMap();
+        for (File srcFile : filesToCompile) {
+          final String srcPath = srcFile.getPath();
+          final String formPath = sourceToFormMap.getState(srcPath);
+          if (formPath != null) {
+            final File formFile = new File(formPath);
+            if (formFile.exists()) {
+              context.markDirty(formFile);
+              formsToCompile.add(formFile);
+            }
+            sourceToFormMap.remove(srcPath);
           }
-          sourceToFormMap.remove(srcPath);
         }
       }
 
-      deleteCorrespondingOutputFiles(context, filesToCompile);
 
-      return compile(context, chunk, filesToCompile.keySet(), formsToCompile);
+      return compile(context, chunk, filesToCompile, formsToCompile);
     }
     catch (ProjectBuildException e) {
       throw e;