private void compileChunk(ModuleChunk chunk) throws IOException { final String chunkPresentableName = getPresentableNameFor(chunk); myModuleName = chunkPresentableName; // validate encodings if (chunk.getModuleCount() > 1) { validateEncoding(chunk, chunkPresentableName); // todo: validation for bytecode target? } runTransformingCompilers(chunk); final List<OutputDir> outs = new ArrayList<OutputDir>(); File fileToDelete = getOutputDirsToCompileTo(chunk, outs); try { for (final OutputDir outputDir : outs) { chunk.setSourcesFilter(outputDir.getKind()); doCompile(chunk, outputDir.getPath()); } } finally { if (fileToDelete != null) { FileUtil.asyncDelete(fileToDelete); } } }
private void compileFinished(int exitValue, final ModuleChunk chunk, final String outputDir) { if (exitValue != 0 && !myCompileContext.getProgressIndicator().isCanceled() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) { myCompileContext.addMessage( CompilerMessageCategory.ERROR, CompilerBundle.message("error.compiler.internal.error", exitValue), null, -1, -1); } myCompiler.compileFinished(); final List<File> toRefresh = new ArrayList<File>(); final Map<String, Collection<TranslatingCompiler.OutputItem>> results = new HashMap<String, Collection<TranslatingCompiler.OutputItem>>(); try { final FileTypeManager typeManager = FileTypeManager.getInstance(); final String outputDirPath = outputDir.replace(File.separatorChar, '/'); try { for (final Module module : chunk.getModules()) { for (final VirtualFile root : chunk.getSourceRoots(module)) { final String packagePrefix = myProjectFileIndex.getPackageNameByDirectory(root); if (LOG.isDebugEnabled()) { LOG.debug( "Building output items for " + root.getPresentableUrl() + "; output dir = " + outputDirPath + "; packagePrefix = \"" + packagePrefix + "\""); } buildOutputItemsList( outputDirPath, module, root, typeManager, root, packagePrefix, toRefresh, results); } } } catch (CacheCorruptedException e) { myCompileContext.requestRebuildNextTime( CompilerBundle.message("error.compiler.caches.corrupted")); if (LOG.isDebugEnabled()) { LOG.debug(e); } } } finally { CompilerUtil.refreshIOFiles(toRefresh); for (Iterator<Map.Entry<String, Collection<TranslatingCompiler.OutputItem>>> it = results.entrySet().iterator(); it.hasNext(); ) { Map.Entry<String, Collection<TranslatingCompiler.OutputItem>> entry = it.next(); mySink.add(entry.getKey(), entry.getValue(), VirtualFile.EMPTY_ARRAY); it.remove(); // to free memory } } myFileNameToSourceMap.clear(); // clear the map before the next use }
private void validateEncoding(ModuleChunk chunk, String chunkPresentableName) { final CompilerEncodingService es = CompilerEncodingService.getInstance(myProject); Charset charset = null; for (Module module : chunk.getModules()) { final Charset moduleCharset = es.getPreferredModuleEncoding(module); if (charset == null) { charset = moduleCharset; } else { if (!Comparing.equal(charset, moduleCharset)) { // warn user final Charset chunkEncoding = CompilerEncodingService.getPreferredModuleEncoding(chunk); final StringBuilder message = new StringBuilder(); message.append("Modules in chunk ["); message.append(chunkPresentableName); message.append("] configured to use different encodings.\n"); if (chunkEncoding != null) { message .append("\"") .append(chunkEncoding.name()) .append("\" encoding will be used to compile the chunk"); } else { message.append("Default compiler encoding will be used to compile the chunk"); } myCompileContext.addMessage( CompilerMessageCategory.INFORMATION, message.toString(), null, -1, -1); break; } } } }
@Nullable private File getOutputDirsToCompileTo(ModuleChunk chunk, final List<OutputDir> dirs) throws IOException { File fileToDelete = null; if (chunk.getModuleCount() == 1) { // optimization final Module module = chunk.getModules()[0]; ApplicationManager.getApplication() .runReadAction( new Runnable() { public void run() { final String sourcesOutputDir = getOutputDir(module); if (shouldCompileTestsSeparately(module)) { if (sourcesOutputDir != null) { dirs.add(new OutputDir(sourcesOutputDir, ModuleChunk.SOURCES)); } final String testsOutputDir = getTestsOutputDir(module); if (testsOutputDir == null) { LOG.error("Tests output dir is null for module \"" + module.getName() + "\""); } else { dirs.add(new OutputDir(testsOutputDir, ModuleChunk.TEST_SOURCES)); } } else { // both sources and test sources go into the same output if (sourcesOutputDir == null) { LOG.error( "Sources output dir is null for module \"" + module.getName() + "\""); } else { dirs.add(new OutputDir(sourcesOutputDir, ModuleChunk.ALL_SOURCES)); } } } }); } else { // chunk has several modules final File outputDir = FileUtil.createTempDirectory("compile", "output"); fileToDelete = outputDir; dirs.add(new OutputDir(outputDir.getPath(), ModuleChunk.ALL_SOURCES)); } return fileToDelete; }
private void runTransformingCompilers(final ModuleChunk chunk) { final JavaSourceTransformingCompiler[] transformers = CompilerManager.getInstance(myProject).getCompilers(JavaSourceTransformingCompiler.class); if (transformers.length == 0) { return; } if (LOG.isDebugEnabled()) { LOG.debug("Running transforming compilers..."); } final Module[] modules = chunk.getModules(); for (final JavaSourceTransformingCompiler transformer : transformers) { final Map<VirtualFile, VirtualFile> originalToCopyFileMap = new HashMap<VirtualFile, VirtualFile>(); final Application application = ApplicationManager.getApplication(); application.invokeAndWait( new Runnable() { public void run() { for (final Module module : modules) { for (final VirtualFile file : chunk.getFilesToCompile(module)) { final VirtualFile untransformed = chunk.getOriginalFile(file); if (transformer.isTransformable(untransformed)) { application.runWriteAction( new Runnable() { public void run() { try { // if untransformed != file, the file is already a (possibly // transformed) copy of the original 'untransformed' file. // If this is the case, just use already created copy and do not copy // file content once again final VirtualFile fileCopy = untransformed.equals(file) ? createFileCopy(getTempDir(module), file) : file; originalToCopyFileMap.put(file, fileCopy); } catch (IOException e) { // skip it } } }); } } } } }, myCompileContext.getProgressIndicator().getModalityState()); // do actual transform for (final Module module : modules) { final List<VirtualFile> filesToCompile = chunk.getFilesToCompile(module); for (int j = 0; j < filesToCompile.size(); j++) { final VirtualFile file = filesToCompile.get(j); final VirtualFile fileCopy = originalToCopyFileMap.get(file); if (fileCopy != null) { final boolean ok = transformer.transform(myCompileContext, fileCopy, chunk.getOriginalFile(file)); if (ok) { chunk.substituteWithTransformedVersion(module, j, fileCopy); } } } } } }