Flex compiler: support 'clear output directories on rebuild' setting (IDEA-81612)

This commit is contained in:
kirill.safonov
2012-03-13 23:34:08 +04:00
parent 41c9f128f4
commit 3b6da2c96d
2 changed files with 77 additions and 57 deletions
@@ -1092,7 +1092,7 @@ public class CompileDriver {
if (scopeOutputs.size() > 0) {
CompilerUtil.runInContext(context, CompilerBundle.message("progress.clearing.output"), new ThrowableRunnable<RuntimeException>() {
public void run() {
clearOutputDirectories(scopeOutputs);
CompilerUtil.clearOutputDirectories(scopeOutputs);
}
});
}
@@ -1515,7 +1515,7 @@ public class CompileDriver {
final boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode();
final VirtualFile[] allSources = context.getProjectCompileScope().getFiles(null, true);
if (myShouldClearOutputDirectory) {
clearOutputDirectories(myAllOutputDirectories);
CompilerUtil.clearOutputDirectories(myAllOutputDirectories);
}
else { // refresh is still required
try {
@@ -1641,34 +1641,6 @@ public class CompileDriver {
return outputDirs;
}
private static void clearOutputDirectories(final Collection<File> outputDirectories) {
final long start = System.currentTimeMillis();
// do not delete directories themselves, or we'll get rootsChanged() otherwise
final Collection<File> filesToDelete = new ArrayList<File>(outputDirectories.size() * 2);
for (File outputDirectory : outputDirectories) {
File[] files = outputDirectory.listFiles();
if (files != null) {
ContainerUtil.addAll(filesToDelete, files);
}
}
if (filesToDelete.size() > 0) {
FileUtil.asyncDelete(filesToDelete);
// ensure output directories exist
for (final File file : outputDirectories) {
file.mkdirs();
}
final long clearStop = System.currentTimeMillis();
CompilerUtil.refreshIODirectories(outputDirectories);
final long refreshStop = System.currentTimeMillis();
CompilerUtil.logDuration("Clearing output dirs", clearStop - start);
CompilerUtil.logDuration("Refreshing output directories", refreshStop - clearStop);
}
}
private void clearCompilerSystemDirectory(final CompileContextEx context) {
CompilerCacheManager.getInstance(myProject).clearCaches(context);
FileUtil.delete(CompilerPathsEx.getZipStoreDirectory(myProject));
@@ -2373,10 +2345,11 @@ public class CompileDriver {
}
if (checkOutputAndSourceIntersection && myShouldClearOutputDirectory) {
CompilerPathsEx.CLEAR_ALL_OUTPUTS_KEY.set(scope, true);
if (!validateOutputAndSourcePathsIntersection()) {
return false;
}
// myShouldClearOutputDirectory may change in validateOutputAndSourcePathsIntersection()
CompilerPathsEx.CLEAR_ALL_OUTPUTS_KEY.set(scope, myShouldClearOutputDirectory);
}
else {
CompilerPathsEx.CLEAR_ALL_OUTPUTS_KEY.set(scope, false);
@@ -2547,31 +2520,11 @@ public class CompileDriver {
ContainerUtil.addIfNotNull(artifact.getOutputFile(), allOutputs);
}
final Set<VirtualFile> affectedOutputPaths = new HashSet<VirtualFile>();
for (Module module : allModules) {
final ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
final VirtualFile[] sourceRoots = rootManager.getSourceRoots();
for (final VirtualFile outputPath : allOutputs) {
for (VirtualFile sourceRoot : sourceRoots) {
if (VfsUtil.isAncestor(outputPath, sourceRoot, true) || VfsUtil.isAncestor(sourceRoot, outputPath, false)) {
affectedOutputPaths.add(outputPath);
}
}
}
}
CompilerUtil.computeIntersectingPaths(myProject, allOutputs, affectedOutputPaths);
affectedOutputPaths.addAll(ArtifactCompilerUtil.getArtifactOutputsContainingSourceFiles(myProject));
if (!affectedOutputPaths.isEmpty()) {
final StringBuilder paths = new StringBuilder();
for (final VirtualFile affectedOutputPath : affectedOutputPaths) {
if (paths.length() > 0) {
paths.append(",\n");
}
paths.append(affectedOutputPath.getPath().replace('/', File.separatorChar));
}
final int answer = Messages.showOkCancelDialog(myProject,
CompilerBundle.message("warning.sources.under.output.paths", paths.toString()),
CommonBundle.getErrorTitle(), Messages.getWarningIcon());
if (answer == 0) { // ok
if (CompilerUtil.askUserToContinueWithNoClearing(myProject, affectedOutputPaths)) {
myShouldClearOutputDirectory = false;
return true;
}
@@ -20,20 +20,24 @@
*/
package com.intellij.compiler.impl;
import com.intellij.CommonBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -247,4 +251,67 @@ public class CompilerUtil {
public static void logDuration(final String activityName, long duration) {
LOG.info(activityName + " took " + duration + " ms: " + duration /60000 + " min " +(duration %60000)/1000 + "sec");
}
public static void clearOutputDirectories(final Collection<File> outputDirectories) {
final long start = System.currentTimeMillis();
// do not delete directories themselves, or we'll get rootsChanged() otherwise
final Collection<File> filesToDelete = new ArrayList<File>(outputDirectories.size() * 2);
for (File outputDirectory : outputDirectories) {
File[] files = outputDirectory.listFiles();
if (files != null) {
ContainerUtil.addAll(filesToDelete, files);
}
}
if (filesToDelete.size() > 0) {
FileUtil.asyncDelete(filesToDelete);
// ensure output directories exist
for (final File file : outputDirectories) {
file.mkdirs();
}
final long clearStop = System.currentTimeMillis();
refreshIODirectories(outputDirectories);
final long refreshStop = System.currentTimeMillis();
logDuration("Clearing output dirs", clearStop - start);
logDuration("Refreshing output directories", refreshStop - clearStop);
}
}
public static void computeIntersectingPaths(final Project project,
final Collection<VirtualFile> outputPaths,
final Collection<VirtualFile> result) {
for (Module module : ModuleManager.getInstance(project).getModules()) {
final ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
final VirtualFile[] sourceRoots = rootManager.getSourceRoots();
for (final VirtualFile outputPath : outputPaths) {
for (VirtualFile sourceRoot : sourceRoots) {
if (VfsUtilCore.isAncestor(outputPath, sourceRoot, true) || VfsUtilCore.isAncestor(sourceRoot, outputPath, false)) {
result.add(outputPath);
}
}
}
}
}
public static boolean askUserToContinueWithNoClearing(Project project, Collection<VirtualFile> affectedOutputPaths) {
final StringBuilder paths = new StringBuilder();
for (final VirtualFile affectedOutputPath : affectedOutputPaths) {
if (paths.length() > 0) {
paths.append(",\n");
}
paths.append(affectedOutputPath.getPath().replace('/', File.separatorChar));
}
final int answer = Messages.showOkCancelDialog(project,
CompilerBundle.message("warning.sources.under.output.paths", paths.toString()),
CommonBundle.getErrorTitle(), Messages.getWarningIcon());
if (answer == Messages.OK) { // ok
return true;
}
else {
return false;
}
}
}