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; } } } }
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 registerParsingException(final CompilerParsingThread outputParsingThread) { Throwable error = outputParsingThread == null ? null : outputParsingThread.getError(); if (error != null) { String message = error.getMessage(); if (error instanceof CacheCorruptedException) { myCompileContext.requestRebuildNextTime(message); } else { myCompileContext.addMessage(CompilerMessageCategory.ERROR, message, null, -1, -1); } } }
@Nullable private Pair<String, String> moveToRealLocation( String tempOutputDir, String pathToClass, VirtualFile sourceFile, final List<File> filesToRefresh) { final Module module = myCompileContext.getModuleByFile(sourceFile); if (module == null) { final String message = "Cannot determine module for source file: " + sourceFile.getPresentableUrl() + ";\nCorresponding output file: " + pathToClass; LOG.info(message); myCompileContext.addMessage( CompilerMessageCategory.WARNING, message, sourceFile.getUrl(), -1, -1); // do not move: looks like source file has been invalidated, need recompilation return new Pair<String, String>(tempOutputDir, pathToClass); } final String realOutputDir; if (myCompileContext.isInTestSourceContent(sourceFile)) { realOutputDir = getTestsOutputDir(module); LOG.assertTrue(realOutputDir != null); } else { realOutputDir = getOutputDir(module); LOG.assertTrue(realOutputDir != null); } if (FileUtil.pathsEqual(tempOutputDir, realOutputDir)) { // no need to move filesToRefresh.add(new File(pathToClass)); return new Pair<String, String>(realOutputDir, pathToClass); } final String realPathToClass = realOutputDir + pathToClass.substring(tempOutputDir.length()); final File fromFile = new File(pathToClass); final File toFile = new File(realPathToClass); boolean success = fromFile.renameTo(toFile); if (!success) { // assuming cause of the fail: intermediate dirs do not exist FileUtil.createParentDirs(toFile); // retry after making non-existent dirs success = fromFile.renameTo(toFile); } if (!success) { // failed to move the file: e.g. because source and destination reside on // different mountpoints. try { FileUtil.copy(fromFile, toFile); FileUtil.delete(fromFile); success = true; } catch (IOException e) { LOG.info(e); success = false; } } if (success) { filesToRefresh.add(toFile); return new Pair<String, String>(realOutputDir, realPathToClass); } return null; }
private void updateOutputItemsList( final String outputDir, final VirtualFile srcFile, VirtualFile sourceRoot, final String packagePrefix, final List<File> filesToRefresh, Map<String, Collection<TranslatingCompiler.OutputItem>> results, final GlobalSearchScope srcRootScope) throws CacheCorruptedException { CompositeDependencyCache dependencyCache = myCompileContext.getDependencyCache(); JavaDependencyCache child = dependencyCache.findChild(JavaDependencyCache.class); final Cache newCache = child.getNewClassesCache(); final Set<CompiledClass> paths = myFileNameToSourceMap.get(srcFile.getName()); if (paths == null || paths.isEmpty()) { return; } final String filePath = "/" + calcPackagePath(srcFile, sourceRoot, packagePrefix); for (final CompiledClass cc : paths) { myCompileContext.getProgressIndicator().checkCanceled(); if (LOG.isDebugEnabled()) { LOG.debug("Checking [pathToClass; relPathToSource] = " + cc); } boolean pathsEquals = FileUtil.pathsEqual(filePath, cc.relativePathToSource); if (!pathsEquals) { final String qName = child.resolve(cc.qName); if (qName != null) { pathsEquals = ApplicationManager.getApplication() .runReadAction( new Computable<Boolean>() { public Boolean compute() { final JavaPsiFacade facade = JavaPsiFacade.getInstance(myProject); PsiClass psiClass = facade.findClass(qName, srcRootScope); if (psiClass == null) { final int dollarIndex = qName.indexOf("$"); if (dollarIndex >= 0) { final String topLevelClassName = qName.substring(0, dollarIndex); psiClass = facade.findClass(topLevelClassName, srcRootScope); } } if (psiClass != null) { final VirtualFile vFile = psiClass.getContainingFile().getVirtualFile(); return vFile != null && vFile.equals(srcFile); } return false; } }); } } if (pathsEquals) { final String outputPath = cc.pathToClass.replace(File.separatorChar, '/'); final Pair<String, String> realLocation = moveToRealLocation(outputDir, outputPath, srcFile, filesToRefresh); if (realLocation != null) { Collection<TranslatingCompiler.OutputItem> outputs = results.get(realLocation.getFirst()); if (outputs == null) { outputs = new ArrayList<TranslatingCompiler.OutputItem>(); results.put(realLocation.getFirst(), outputs); } outputs.add(new OutputItemImpl(realLocation.getSecond(), srcFile)); if (PACKAGE_ANNOTATION_FILE_NAME.equals(srcFile.getName())) { myProcessedPackageInfos.add(srcFile); } if (CompilerManager.MAKE_ENABLED) { newCache.setPath(cc.qName, realLocation.getSecond()); } if (LOG.isDebugEnabled()) { LOG.debug( "Added output item: [outputDir; outputPath; sourceFile] = [" + realLocation.getFirst() + "; " + realLocation.getSecond() + "; " + srcFile.getPresentableUrl() + "]"); } } else { myCompileContext.addMessage( CompilerMessageCategory.ERROR, "Failed to copy from temporary location to output directory: " + outputPath + " (see idea.log for details)", null, -1, -1); if (LOG.isDebugEnabled()) { LOG.debug("Failed to move to real location: " + outputPath + "; from " + outputDir); } } } } }