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;
import org.objectweb.asm.ClassReader;
import java.io.File;
+import java.io.IOException;
import java.util.*;
/**
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
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;
}
}
}
}
+ 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");
}
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;
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) {
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();
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) {
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 {
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;
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) {
}
}
- 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");
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);