private static void doCollectResourceDirs( AndroidFacet facet, boolean collectResCacheDirs, List<String> result, CompileContext context) { final Module module = facet.getModule(); if (collectResCacheDirs) { final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform(); final int platformToolsRevision = platform != null ? platform.getSdk().getPlatformToolsRevision() : -1; if (platformToolsRevision < 0 || platformToolsRevision > 7) { // png cache is supported since platform-tools-r8 final String resCacheDirOsPath = findResourcesCacheDirectory(module, false, context); if (resCacheDirOsPath != null) { result.add(resCacheDirOsPath); } else { LOG.info("PNG cache not found for module " + module.getName()); } } } final VirtualFile resourcesDir = AndroidAptCompiler.getResourceDirForApkCompiler(module, facet); if (resourcesDir != null) { result.add(resourcesDir.getPath()); } }
public static void addMessages( @NotNull Map<CompilerMessageCategory, List<String>> messages, @NotNull Map<CompilerMessageCategory, List<String>> toAdd) { for (Map.Entry<CompilerMessageCategory, List<String>> entry : toAdd.entrySet()) { List<String> list = messages.get(entry.getKey()); if (list == null) { list = new ArrayList<String>(); messages.put(entry.getKey(), list); } list.addAll(entry.getValue()); } }
public void compile() throws CompilerException, CacheCorruptedException { Application application = ApplicationManager.getApplication(); try { if (!myFilesToCompile.isEmpty()) { if (application.isUnitTestMode()) { saveTestData(); } compileModules(buildModuleToFilesMap(myFilesToCompile)); } } catch (SecurityException e) { throw new CompilerException( CompilerBundle.message("error.compiler.process.not.started", e.getMessage()), e); } catch (IllegalArgumentException e) { throw new CompilerException(e.getMessage(), e); } finally { for (final VirtualFile file : myModuleToTempDirMap.values()) { if (file != null) { final File ioFile = new File(file.getPath()); FileUtil.asyncDelete(ioFile); } } myModuleToTempDirMap.clear(); } if (!myFilesToCompile.isEmpty() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) { // package-info.java hack final List<TranslatingCompiler.OutputItem> outputs = new ArrayList<TranslatingCompiler.OutputItem>(); ApplicationManager.getApplication() .runReadAction( new Runnable() { public void run() { for (final VirtualFile file : myFilesToCompile) { if (PACKAGE_ANNOTATION_FILE_NAME.equals(file.getName()) && !myProcessedPackageInfos.contains(file)) { outputs.add(new OutputItemImpl(file)); } } } }); if (!outputs.isEmpty()) { mySink.add(null, outputs, VirtualFile.EMPTY_ARRAY); } } }
private static VirtualFile[] getFilesToCheckReadonlyStatus( GeneratingCompiler.GenerationItem[] items) { List<VirtualFile> filesToCheck = new ArrayList<VirtualFile>(); for (GeneratingCompiler.GenerationItem item : items) { if (item instanceof AndroidAptCompiler.AptGenerationItem) { final Set<File> generatedFiles = ((AndroidAptCompiler.AptGenerationItem) item).getGeneratedFiles().keySet(); for (File generatedFile : generatedFiles) { if (generatedFile.exists()) { VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(generatedFile); if (generatedVFile != null) { filesToCheck.add(generatedVFile); } } } } } return VfsUtil.toVirtualFileArray(filesToCheck); }
private static boolean hasNotNullAnnotations( final Cache cache, final SymbolTable symbolTable, final int className, Project project) throws CacheCorruptedException { final NullableNotNullManager manager = NullableNotNullManager.getInstance(project); final List<String> notNulls = manager.getNotNulls(); for (MethodInfo methodId : cache.getMethods(className)) { for (AnnotationConstantValue annotation : methodId.getRuntimeInvisibleAnnotations()) { if (notNulls.contains(symbolTable.getSymbol(annotation.getAnnotationQName()))) { return true; } } final AnnotationConstantValue[][] paramAnnotations = methodId.getRuntimeInvisibleParameterAnnotations(); for (AnnotationConstantValue[] _singleParamAnnotations : paramAnnotations) { for (AnnotationConstantValue annotation : _singleParamAnnotations) { if (notNulls.contains(symbolTable.getSymbol(annotation.getAnnotationQName()))) { return true; } } } } return false; }
private static void addItem( @NotNull final Collection<VirtualFile> sourceFiles, @NotNull final AndroidFacet facet, @NotNull final String resourceDirPath, @NotNull String sdkLocation, @NotNull final IAndroidTarget target, @NotNull final List<GenerationItem> items) { final String sourceRootPath = AndroidRootUtil.getRenderscriptGenSourceRootPath(facet); if (sourceRootPath == null) { return; } final String rawDirPath = resourceDirPath + '/' + AndroidConstants.FD_RES_RAW; items.add( new MyGenerationItem(facet.getModule(), sourceFiles, rawDirPath, sdkLocation, target)); }
@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; }
@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 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); } } } } } }
private static GenerationItem[] doGenerate( @NotNull final CompileContext context, @NotNull final GenerationItem[] items, VirtualFile outputRootDirectory) { if (context.getProject().isDisposed()) { return EMPTY_GENERATION_ITEM_ARRAY; } // we have one item per module there, so clear output directory final String genRootPath = FileUtil.toSystemDependentName(outputRootDirectory.getPath()); final File genRootDir = new File(genRootPath); if (genRootDir.exists()) { if (!FileUtil.delete(genRootDir)) { context.addMessage( CompilerMessageCategory.ERROR, "Cannot delete directory " + genRootPath, null, -1, -1); return EMPTY_GENERATION_ITEM_ARRAY; } if (!genRootDir.mkdir()) { context.addMessage( CompilerMessageCategory.ERROR, "Cannot create directory " + genRootPath, null, -1, -1); return EMPTY_GENERATION_ITEM_ARRAY; } } final List<GenerationItem> results = new ArrayList<GenerationItem>(items.length); for (final GenerationItem item : items) { if (item instanceof MyGenerationItem) { final MyGenerationItem genItem = (MyGenerationItem) item; if (!AndroidCompileUtil.isModuleAffected(context, genItem.myModule)) { continue; } boolean success = true; for (final VirtualFile sourceFile : genItem.myFiles) { final String depFolderOsPath = getDependencyFolder(context.getProject(), sourceFile, outputRootDirectory); try { final Map<CompilerMessageCategory, List<String>> messages = AndroidCompileUtil.toCompilerMessageCategoryKeys( AndroidRenderscript.execute( genItem.mySdkLocation, genItem.myAndroidTarget, sourceFile.getPath(), genRootPath, depFolderOsPath, genItem.myRawDirPath)); ApplicationManager.getApplication() .runReadAction( new Runnable() { public void run() { if (context.getProject().isDisposed()) { return; } addMessages(context, messages, sourceFile.getUrl()); } }); if (messages.get(CompilerMessageCategory.ERROR).size() > 0) { success = false; } } catch (final IOException e) { ApplicationManager.getApplication() .runReadAction( new Runnable() { public void run() { if (context.getProject().isDisposed()) return; context.addMessage( CompilerMessageCategory.ERROR, e.getMessage(), sourceFile.getUrl(), -1, -1); } }); success = false; } } if (success) { results.add(genItem); } } } outputRootDirectory.refresh(false, true); return results.toArray(new GenerationItem[results.size()]); }
public static void generate(GeneratingCompiler compiler, final CompileContext context) { if (context == null) { return; } final Set<Module> affectedModules = new HashSet<Module>(); Collections.addAll(affectedModules, context.getCompileScope().getAffectedModules()); ApplicationManager.getApplication() .invokeAndWait( new Runnable() { @Override public void run() { for (Module module : affectedModules) { if (module.isDisposed() || module.getProject().isDisposed()) { continue; } final AndroidFacet facet = AndroidFacet.getInstance(module); if (facet != null) { AndroidCompileUtil.createGenModulesAndSourceRoots(facet); } } } }, ModalityState.defaultModalityState()); List<GeneratingCompiler.GenerationItem> itemsToGenerate = new ArrayList<GeneratingCompiler.GenerationItem>(); for (GeneratingCompiler.GenerationItem item : compiler.getGenerationItems(context)) { if (affectedModules.contains(item.getModule())) { itemsToGenerate.add(item); } } GeneratingCompiler.GenerationItem[] items = itemsToGenerate.toArray(new GeneratingCompiler.GenerationItem[itemsToGenerate.size()]); final boolean[] run = {true}; final VirtualFile[] files = getFilesToCheckReadonlyStatus(items); if (files.length > 0) { ApplicationManager.getApplication() .invokeAndWait( new Runnable() { @Override public void run() { ApplicationManager.getApplication() .runReadAction( new Runnable() { @Override public void run() { final Project project = context.getProject(); run[0] = !project.isDisposed() && ReadonlyStatusHandler.ensureFilesWritable(project, files); } }); } }, ModalityState.defaultModalityState()); } if (run[0]) { compiler.generate(context, items, null); } }