remove some more duplication
authorpeter <peter@jetbrains.com>
Mon, 30 Jan 2012 14:21:10 +0000 (15:21 +0100)
committerpeter <peter@jetbrains.com>
Mon, 30 Jan 2012 16:07:30 +0000 (17:07 +0100)
jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java
jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovycOSProcessHandler.java
plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java

index 8422fd25fc678134dd3a6af4e918cb80691b8384..f0742ba9bcdbdbef490f0131fb410f03a2071472 100644 (file)
@@ -3,9 +3,10 @@ package org.jetbrains.jps.incremental.groovy;
 
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Consumer;
 import com.intellij.util.SystemProperties;
 import groovy.util.CharsetToolkit;
-import org.jetbrains.annotations.Nullable;
 import org.jetbrains.ether.dependencyView.Callbacks;
 import org.jetbrains.ether.dependencyView.Mappings;
 import org.jetbrains.groovy.compiler.rt.GroovyCompilerWrapper;
@@ -22,6 +23,7 @@ import org.jetbrains.jps.server.ClasspathBootstrap;
 import org.objectweb.asm.ClassReader;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.*;
 
 /**
@@ -44,63 +46,29 @@ public class GroovyBuilder extends ModuleLevelBuilder {
 
   public ModuleLevelBuilder.ExitCode build(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
     ExitCode exitCode = ExitCode.OK;
-    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.add(file);
-          }
-          return true;
-        }
-      });
-
+      final List<File> toCompile = collectChangedFiles(context, chunk);
       if (toCompile.isEmpty()) {
         return exitCode;
       }
 
-      final Set<String> cp = new LinkedHashSet<String>();
-      //groovy_rt.jar
-      // IMPORTANT! must be the first in classpath
-      cp.add(ClasspathBootstrap.getResourcePath(GroovyCompilerWrapper.class).getPath());
-
-      for (File file : context.getProjectPaths().getClasspathFiles(chunk, ClasspathKind.compile(context.isCompilingTests()), false)) {
-        cp.add(FileUtil.toCanonicalPath(file.getPath()));
-      }
-      for (File file : context.getProjectPaths().getClasspathFiles(chunk, ClasspathKind.runtime(context.isCompilingTests()), false)) {
-        cp.add(FileUtil.toCanonicalPath(file.getPath()));
-      }
-
-      final File tempFile = FileUtil.createTempFile("ideaGroovyToCompile", ".txt", true);
-      final Module representativeModule = chunk.getModules().iterator().next();
-      File moduleOutputDir = context.getProjectPaths().getModuleOutputDir(representativeModule, context.isCompilingTests());
-      final File dir = myForStubs ? FileUtil.createTempDirectory(/*new File("/tmp/stubs/"), */"groovyStubs", null) : moduleOutputDir;
-      assert dir != null;
+      String moduleOutput = getModuleOutput(context, chunk);
+      String compilerOutput = getCompilerOutput(context, moduleOutput);
 
       final Set<String> toCompilePaths = new LinkedHashSet<String>();
       for (File file : toCompile) {
         toCompilePaths.add(FileUtil.toSystemIndependentName(file.getPath()));
       }
       
-      String moduleOutputPath = FileUtil.toCanonicalPath(moduleOutputDir.getPath());
-      if (!moduleOutputPath.endsWith("/")) {
-        moduleOutputPath += "/";
-      }
-      Map<String, String> class2Src = buildClassToSourceMap(chunk, context, toCompilePaths, moduleOutputPath);
+      Map<String, String> class2Src = buildClassToSourceMap(chunk, context, toCompilePaths, moduleOutput);
 
       String ideCharset = chunk.getProject().getProjectCharset();
       String encoding = !Comparing.equal(CharsetToolkit.getDefaultSystemCharset().name(), ideCharset) ? ideCharset : null;
       List<String> patchers = Collections.emptyList(); //todo patchers
-      GroovycOSProcessHandler.fillFileWithGroovycParameters(
-        tempFile, FileUtil.toCanonicalPath(dir.getPath()), toCompilePaths, FileUtil.toSystemDependentName(moduleOutputPath), class2Src, encoding, patchers
+      final File tempFile = GroovycOSProcessHandler.fillFileWithGroovycParameters(
+        compilerOutput, toCompilePaths, FileUtil.toSystemDependentName(moduleOutput), class2Src, encoding, patchers
       );
 
-      if (myForStubs) {
-        JavaBuilder.addTempSourcePathRoot(context, dir);
-      }
-
       // todo CompilerUtil.addLocaleOptions()
       //todo different outputs in a chunk
       //todo xmx
@@ -108,59 +76,30 @@ public class GroovyBuilder extends ModuleLevelBuilder {
       final List<String> cmd = ExternalProcessUtil.buildJavaCommandLine(
         SystemProperties.getJavaHome() + "/bin/java",
         "org.jetbrains.groovy.compiler.rt.GroovycRunner",
-        Collections.<String>emptyList(), new ArrayList<String>(cp),
+        Collections.<String>emptyList(), new ArrayList<String>(generateClasspath(context, chunk)),
         Arrays.asList("-Xmx384m"/*, "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5239"*/),
         Arrays.<String>asList(myForStubs ? "stubs" : "groovyc", tempFile.getPath())
       );
 
       List<GroovycOSProcessHandler.OutputItem> successfullyCompiled = Collections.emptyList();
       try {
-        final Process process = Runtime.getRuntime().exec(cmd.toArray(new String[cmd.size()]));
-        GroovycOSProcessHandler handler = new GroovycOSProcessHandler(process, null) {
+        final Process process = Runtime.getRuntime().exec(ArrayUtil.toStringArray(cmd));
+        GroovycOSProcessHandler handler = GroovycOSProcessHandler.runGroovyc(process, new Consumer<String>() {
           @Override
-          protected void updateStatus(@Nullable String status) {
-            context.processMessage(new ProgressMessage(status == null ? GROOVY_COMPILER_IN_OPERATION : status));
+          public void consume(String s) {
+            context.processMessage(new ProgressMessage(s));
           }
-        };
-        handler.startNotify();
-        handler.waitFor();
+        });
 
         successfullyCompiled = handler.getSuccessfullyCompiled();
 
         for (CompilerMessage message : handler.getCompilerMessages()) {
           context.processMessage(message);
         }
-
       }
       finally {
         if (!myForStubs) {
-          final Mappings delta = context.createDelta();
-          final List<File> successfullyCompiledFiles = new ArrayList<File>();
-          if (!successfullyCompiled.isEmpty()) {
-
-            final Callbacks.Backend callback = delta.getCallback();
-            final FileGeneratedEvent generatedEvent = new FileGeneratedEvent();
-
-            for (GroovycOSProcessHandler.OutputItem item : successfullyCompiled) {
-              final String sourcePath = FileUtil.toSystemIndependentName(item.sourcePath);
-              final String outputPath = FileUtil.toSystemIndependentName(item.outputPath);
-              final RootDescriptor moduleAndRoot = context.getModuleAndRoot(new File(sourcePath));
-              if (moduleAndRoot != null) {
-                final String moduleName = moduleAndRoot.module.getName().toLowerCase(Locale.US);
-                context.getDataManager().getSourceToOutputMap(moduleName, moduleAndRoot.isTestRoot).appendData(sourcePath, outputPath);
-              }
-              callback.associate(outputPath, Callbacks.getDefaultLookup(sourcePath), new ClassReader(FileUtil.loadFileBytes(new File(outputPath))));
-              successfullyCompiledFiles.add(new File(sourcePath));
-
-              generatedEvent.add(moduleOutputPath, FileUtil.getRelativePath(moduleOutputPath, outputPath, '/'));
-            }
-
-            context.processMessage(generatedEvent);
-          }
-
-
-          final boolean needSecondPass = updateMappings(context, delta, chunk, toCompile, successfullyCompiledFiles);
-          if (needSecondPass) {
+          if (updateDependencies(context, chunk, toCompile, moduleOutput, successfullyCompiled)) {
             exitCode = ExitCode.ADDITIONAL_PASS_REQUIRED;
           }
         }
@@ -173,6 +112,85 @@ public class GroovyBuilder extends ModuleLevelBuilder {
     }
   }
 
+  private static String getModuleOutput(CompileContext context, ModuleChunk chunk) {
+    final Module representativeModule = chunk.getModules().iterator().next();
+    File moduleOutputDir = context.getProjectPaths().getModuleOutputDir(representativeModule, context.isCompilingTests());
+    assert moduleOutputDir != null;
+    String moduleOutputPath = FileUtil.toCanonicalPath(moduleOutputDir.getPath());
+    return moduleOutputPath.endsWith("/") ? moduleOutputPath : moduleOutputPath + "/";
+  }
+
+  private String getCompilerOutput(CompileContext context, String moduleOutputDir) throws IOException {
+    final File dir = myForStubs ? FileUtil.createTempDirectory("groovyStubs", null) : new File(moduleOutputDir);
+    if (myForStubs) {
+      JavaBuilder.addTempSourcePathRoot(context, dir);
+    }
+    return FileUtil.toCanonicalPath(dir.getPath());
+  }
+
+  private static List<File> collectChangedFiles(CompileContext context, ModuleChunk chunk) throws Exception {
+    final List<File> toCompile = new ArrayList<File>();
+    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.add(file);
+        }
+        return true;
+      }
+    });
+    return toCompile;
+  }
+
+  private boolean updateDependencies(CompileContext context,
+                                  ModuleChunk chunk,
+                                  List<File> toCompile,
+                                  String moduleOutputPath,
+                                  List<GroovycOSProcessHandler.OutputItem> successfullyCompiled) throws Exception {
+    final Mappings delta = context.createDelta();
+    final List<File> successfullyCompiledFiles = new ArrayList<File>();
+    if (!successfullyCompiled.isEmpty()) {
+
+      final Callbacks.Backend callback = delta.getCallback();
+      final FileGeneratedEvent generatedEvent = new FileGeneratedEvent();
+
+      for (GroovycOSProcessHandler.OutputItem item : successfullyCompiled) {
+        final String sourcePath = FileUtil.toSystemIndependentName(item.sourcePath);
+        final String outputPath = FileUtil.toSystemIndependentName(item.outputPath);
+        final RootDescriptor moduleAndRoot = context.getModuleAndRoot(new File(sourcePath));
+        if (moduleAndRoot != null) {
+          final String moduleName = moduleAndRoot.module.getName().toLowerCase(Locale.US);
+          context.getDataManager().getSourceToOutputMap(moduleName, moduleAndRoot.isTestRoot).appendData(sourcePath, outputPath);
+        }
+        callback.associate(outputPath, Callbacks.getDefaultLookup(sourcePath), new ClassReader(FileUtil.loadFileBytes(new File(outputPath))));
+        successfullyCompiledFiles.add(new File(sourcePath));
+
+        generatedEvent.add(moduleOutputPath, FileUtil.getRelativePath(moduleOutputPath, outputPath, '/'));
+      }
+
+      context.processMessage(generatedEvent);
+    }
+
+
+    return updateMappings(context, delta, chunk, toCompile, successfullyCompiledFiles);
+  }
+
+  private static List<String> generateClasspath(CompileContext context, ModuleChunk chunk) {
+    final Set<String> cp = new LinkedHashSet<String>();
+    //groovy_rt.jar
+    // IMPORTANT! must be the first in classpath
+    cp.add(ClasspathBootstrap.getResourcePath(GroovyCompilerWrapper.class).getPath());
+
+    for (File file : context.getProjectPaths().getClasspathFiles(chunk, ClasspathKind.compile(context.isCompilingTests()), false)) {
+      cp.add(FileUtil.toCanonicalPath(file.getPath()));
+    }
+    for (File file : context.getProjectPaths().getClasspathFiles(chunk, ClasspathKind.runtime(context.isCompilingTests()), false)) {
+      cp.add(FileUtil.toCanonicalPath(file.getPath()));
+    }
+    return new ArrayList<String>(cp);
+  }
+
   private static boolean isGroovyFile(String path) {
     return path.endsWith(".groovy") || path.endsWith(".gpp");
   }
index aa6b4bcc2c114ac3c553c03af8610e8374356da9..9afc7e4f2f3aa79f8c305480192b77372de90db1 100644 (file)
@@ -20,7 +20,9 @@ import com.intellij.execution.process.BaseOSProcessHandler;
 import com.intellij.execution.process.ProcessOutputTypes;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Consumer;
 import com.intellij.util.containers.ContainerUtil;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.groovy.compiler.rt.GroovycRunner;
@@ -42,9 +44,11 @@ public class GroovycOSProcessHandler extends BaseOSProcessHandler {
   private final StringBuffer stdErr = new StringBuffer();
 
   private static final Logger LOG = Logger.getInstance("org.jetbrains.jps.incremental.groovy.GroovycOSProcessHandler");
+  private final Consumer<String> myStatusUpdater;
 
-  public GroovycOSProcessHandler(Process process, String s) {
-    super(process, s, null);
+  private GroovycOSProcessHandler(Process process, Consumer<String> statusUpdater) {
+    super(process, null, null);
+    myStatusUpdater = statusUpdater;
   }
 
   public void notifyTextAvailable(final String text, final Key outputType) {
@@ -69,7 +73,9 @@ public class GroovycOSProcessHandler extends BaseOSProcessHandler {
 
   private final StringBuffer outputBuffer = new StringBuffer();
 
-  protected void updateStatus(@Nullable String status) { }
+  protected void updateStatus(@Nullable String status) {
+    myStatusUpdater.consume(status == null ? GROOVY_COMPILER_IN_OPERATION : status);
+  }
 
   private void parseOutput(String text) {
     final String trimmed = text.trim();
@@ -194,11 +200,12 @@ public class GroovycOSProcessHandler extends BaseOSProcessHandler {
     return stdErr;
   }
 
-  public static void fillFileWithGroovycParameters(File tempFile,
-                                                   final String outputDir,
+  public static File fillFileWithGroovycParameters(final String outputDir,
                                                    final Collection<String> changedSources,
                                                    String finalOutput,
                                                    Map<String, String> class2Src, @Nullable final String encoding, List<String> patchers) throws IOException {
+    File tempFile = FileUtil.createTempFile("ideaGroovyToCompile", ".txt", true);
+
     final Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(tempFile)));
     try {
       for (String file : changedSources) {
@@ -233,6 +240,15 @@ public class GroovycOSProcessHandler extends BaseOSProcessHandler {
     finally {
       writer.close();
     }
+    return tempFile;
+  }
+
+  public static GroovycOSProcessHandler runGroovyc(Process process, Consumer<String> updater) {
+    GroovycOSProcessHandler processHandler = new GroovycOSProcessHandler(process, updater);
+
+    processHandler.startNotify();
+    processHandler.waitFor();
+    return processHandler;
   }
 
   public static class OutputItem {
index 73305880438ed4dcc294abbc5abd4e1fdd5daaf7..322cdfef217f1d6902144a31c46b1dde38a9e2e0 100644 (file)
@@ -25,7 +25,6 @@ import com.intellij.compiler.impl.javaCompiler.OutputItemImpl;
 import com.intellij.compiler.make.CacheCorruptedException;
 import com.intellij.compiler.make.DependencyCache;
 import com.intellij.execution.ExecutionException;
-import com.intellij.execution.configurations.GeneralCommandLine;
 import com.intellij.execution.configurations.JavaParameters;
 import com.intellij.openapi.application.AccessToken;
 import com.intellij.openapi.application.ApplicationManager;
@@ -165,11 +164,10 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
     parameters.setMainClass(GroovycRunner.class.getName());
 
     try {
-      File fileWithParameters = FileUtil.createTempFile("toCompile", "");
       final VirtualFile finalOutputDir = getMainOutput(compileContext, module, tests);
       LOG.assertTrue(finalOutputDir != null, "No output directory for module " + module.getName() + (tests ? " tests" : " production"));
       final Charset ideCharset = EncodingProjectManager.getInstance(myProject).getDefaultCharset();
-      String encoding = !Comparing.equal(CharsetToolkit.getDefaultSystemCharset(), ideCharset) ? ideCharset.name() : null;
+      String encoding = ideCharset != null && !Comparing.equal(CharsetToolkit.getDefaultSystemCharset(), ideCharset) ? ideCharset.name() : null;
       Set<String> paths2Compile = ContainerUtil.map2Set(toCompile, new Function<VirtualFile, String>() {
         @Override
         public String fun(VirtualFile file) {
@@ -186,8 +184,8 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
         }
       }
 
-      GroovycOSProcessHandler
-        .fillFileWithGroovycParameters(fileWithParameters, outputDir.getPath(), paths2Compile, FileUtil.toSystemDependentName(finalOutputDir.getPath()),
+      File fileWithParameters = GroovycOSProcessHandler
+        .fillFileWithGroovycParameters(outputDir.getPath(), paths2Compile, FileUtil.toSystemDependentName(finalOutputDir.getPath()),
                                        class2Src, encoding, patchers);
 
       parameters.getProgramParametersList().add(forStubs ? "stubs" : "groovyc");
@@ -197,23 +195,18 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler {
       LOG.error(e);
     }
 
-    GroovycOSProcessHandler processHandler;
 
     try {
-      final GeneralCommandLine commandLine = JdkUtil.setupJVMCommandLine(exePath, parameters, true);
-      processHandler = new GroovycOSProcessHandler(commandLine.createProcess(), commandLine.getCommandLineString()) {
+      Process process = JdkUtil.setupJVMCommandLine(exePath, parameters, true).createProcess();
+      GroovycOSProcessHandler processHandler = GroovycOSProcessHandler.runGroovyc(process, new Consumer<String>() {
         @Override
-        protected void updateStatus(@Nullable String status) {
-          compileContext.getProgressIndicator().setText(status == null ? GROOVY_COMPILER_IN_OPERATION : status);
+        public void consume(String s) {
+          compileContext.getProgressIndicator().setText(s);
         }
-      };
-
-      processHandler.startNotify();
-      processHandler.waitFor();
+      });
 
       final List<VirtualFile> toRecompile = new ArrayList<VirtualFile>();
-      Set<File> toRecompileFiles = processHandler.getToRecompileFiles();
-      for (File toRecompileFile : toRecompileFiles) {
+      for (File toRecompileFile : processHandler.getToRecompileFiles()) {
         final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(toRecompileFile);
         LOG.assertTrue(vFile != null);
         toRecompile.add(vFile);