diff --git a/compiler/compiler-impl.iml b/compiler/compiler-impl.iml
index 4223c594a53d..72515d9328d5 100644
--- a/compiler/compiler-impl.iml
+++ b/compiler/compiler-impl.iml
@@ -24,6 +24,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/compiler/impl/com/intellij/compiler/CompilerConfigurationImpl.java b/compiler/impl/com/intellij/compiler/CompilerConfigurationImpl.java
index 17fa63f63de5..ec871d96948e 100644
--- a/compiler/impl/com/intellij/compiler/CompilerConfigurationImpl.java
+++ b/compiler/impl/com/intellij/compiler/CompilerConfigurationImpl.java
@@ -10,13 +10,15 @@ package com.intellij.compiler;
import com.intellij.CommonBundle;
import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
+import com.intellij.compiler.impl.javaCompiler.api.CompilerAPICompiler;
import com.intellij.compiler.impl.javaCompiler.eclipse.EclipseCompiler;
+import com.intellij.compiler.impl.javaCompiler.eclipse.EclipseEmbeddedCompiler;
import com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler;
-import com.intellij.compiler.impl.javaCompiler.javac.JavacEmbeddedCompiler;
import com.intellij.compiler.impl.javaCompiler.javac.JavacSettings;
import com.intellij.compiler.impl.javaCompiler.jikes.JikesCompiler;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration;
import com.intellij.openapi.components.*;
@@ -65,7 +67,6 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
private final Collection myRegisteredCompilers = new ArrayList();
private BackendCompiler JAVAC_EXTERNAL_BACKEND;
- private BackendCompiler JAVAC_EMBEDDED_BACKEND;
private final Perl5Matcher myPatternMatcher = new Perl5Matcher();
{
@@ -178,8 +179,6 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
private void createCompilers() {
JAVAC_EXTERNAL_BACKEND = new JavacCompiler(myProject);
myRegisteredCompilers.add(JAVAC_EXTERNAL_BACKEND);
- JAVAC_EMBEDDED_BACKEND = new JavacEmbeddedCompiler(myProject);
- //myRegisteredCompilers.add(JAVAC_EMBEDDED_BACKEND);
if (!ApplicationManager.getApplication().isUnitTestMode()) {
final BackendCompiler JIKES_BACKEND = new JikesCompiler(myProject);
@@ -189,13 +188,26 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
final EclipseCompiler eclipse = new EclipseCompiler(myProject);
myRegisteredCompilers.add(eclipse);
}
- //try {
- // final EclipseEmbeddedCompiler eclipseEmbedded = new EclipseEmbeddedCompiler(myProject);
- // myRegisteredCompilers.add(eclipseEmbedded);
- //}
- //catch (NoClassDefFoundError e) {
- // // eclipse jar must be not in the classpath
- //}
+
+ if (ApplicationManagerEx.getApplicationEx().isInternal()) {
+ try {
+ final EclipseEmbeddedCompiler eclipseEmbedded = new EclipseEmbeddedCompiler(myProject);
+ myRegisteredCompilers.add(eclipseEmbedded);
+ }
+ catch (NoClassDefFoundError e) {
+ // eclipse jar must be not in the classpath
+ }
+ }
+
+ if (ApplicationManagerEx.getApplicationEx().isInternal()) {
+ try {
+ CompilerAPICompiler compiler = new CompilerAPICompiler(myProject);
+ myRegisteredCompilers.add(compiler);
+ }
+ catch (NoClassDefFoundError e) {
+ // wrong JDK
+ }
+ }
}
myDefaultJavaCompiler = JAVAC_EXTERNAL_BACKEND;
@@ -394,11 +406,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
if (JAVAC_EXTERNAL_BACKEND == null) {
createCompilers();
}
- if (myDefaultJavaCompiler != JAVAC_EXTERNAL_BACKEND) return myDefaultJavaCompiler;
- boolean runEmbedded = ApplicationManager.getApplication().isUnitTestMode()
- ? !JavacSettings.getInstance(myProject).isTestsUseExternalCompiler()
- : Boolean.parseBoolean(System.getProperty(PROPERTY_IDEA_USE_EMBEDDED_JAVAC));
- return runEmbedded ? JAVAC_EMBEDDED_BACKEND : JAVAC_EXTERNAL_BACKEND;
+ return myDefaultJavaCompiler;
}
public void setDefaultCompiler(BackendCompiler defaultCompiler) {
diff --git a/compiler/impl/com/intellij/compiler/OutputParser.java b/compiler/impl/com/intellij/compiler/OutputParser.java
index 4608e90fecaf..6977a5f4f2bc 100644
--- a/compiler/impl/com/intellij/compiler/OutputParser.java
+++ b/compiler/impl/com/intellij/compiler/OutputParser.java
@@ -2,6 +2,7 @@ package com.intellij.compiler;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.compiler.impl.javaCompiler.FileObject;
import org.jetbrains.annotations.NonNls;
import java.util.ArrayList;
@@ -15,7 +16,7 @@ public abstract class OutputParser {
@NonNls String getCurrentLine();
void setProgressText(String text);
void fileProcessed(@NonNls String path);
- void fileGenerated(@NonNls String path);
+ void fileGenerated(@NonNls FileObject path);
void message(CompilerMessageCategory category, String message, @NonNls String url, int lineNum, int columnNum);
}
diff --git a/compiler/impl/com/intellij/compiler/impl/CompileDriver.java b/compiler/impl/com/intellij/compiler/impl/CompileDriver.java
index 50e54d8c1045..62b80a410061 100644
--- a/compiler/impl/com/intellij/compiler/impl/CompileDriver.java
+++ b/compiler/impl/com/intellij/compiler/impl/CompileDriver.java
@@ -58,10 +58,7 @@ import com.intellij.psi.PsiCompiledElement;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
-import com.intellij.util.Chunk;
-import com.intellij.util.LocalTimeCounter;
-import com.intellij.util.ProfilingUtil;
-import com.intellij.util.StringBuilderSpinAllocator;
+import com.intellij.util.*;
import com.intellij.util.containers.HashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
@@ -85,8 +82,16 @@ public class CompileDriver {
@NonNls private static final boolean GENERATE_CLASSPATH_INDEX = "true".equals(System.getProperty("generate.classpath.index"));
- private final FileProcessingCompilerAdapterFactory myProcessingCompilerAdapterFactory;
- private final FileProcessingCompilerAdapterFactory myPackagingCompilerAdapterFactory;
+ private static final FileProcessingCompilerAdapterFactory FILE_PROCESSING_COMPILER_ADAPTER_FACTORY = new FileProcessingCompilerAdapterFactory() {
+ public FileProcessingCompilerAdapter create(CompileContext context, FileProcessingCompiler compiler) {
+ return new FileProcessingCompilerAdapter(context, compiler);
+ }
+ };
+ private static final FileProcessingCompilerAdapterFactory FILE_PACKAGING_COMPILER_ADAPTER_FACTORY = new FileProcessingCompilerAdapterFactory() {
+ public FileProcessingCompilerAdapter create(CompileContext context, FileProcessingCompiler compiler) {
+ return new PackagingCompilerAdapter(context, (PackagingCompiler)compiler);
+ }
+ };
public CompileDriver(Project project) {
myProject = project;
@@ -109,16 +114,6 @@ public class CompileDriver {
}
}
- myProcessingCompilerAdapterFactory = new FileProcessingCompilerAdapterFactory() {
- public FileProcessingCompilerAdapter create(CompileContext context, FileProcessingCompiler compiler) {
- return new FileProcessingCompilerAdapter(context, compiler);
- }
- };
- myPackagingCompilerAdapterFactory = new FileProcessingCompilerAdapterFactory() {
- public FileProcessingCompilerAdapter create(CompileContext context, FileProcessingCompiler compiler) {
- return new PackagingCompilerAdapter(context, (PackagingCompiler)compiler);
- }
- };
}
public void rebuild(CompileStatusNotification callback) {
@@ -150,10 +145,11 @@ public class CompileDriver {
return false;
}
- for (Pair pair : myGenerationCompilerModuleToOutputDirMap.keySet()) {
- final Pair outputs = myGenerationCompilerModuleToOutputDirMap.get(pair);
- compileContext.assignModule(outputs.getFirst(), pair.getSecond(), false);
- compileContext.assignModule(outputs.getSecond(), pair.getSecond(), true);
+ for (Map.Entry, Pair> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) {
+ final Pair outputs = entry.getValue();
+ Module module = entry.getKey().getSecond();
+ compileContext.assignModule(outputs.getFirst(), module, false);
+ compileContext.assignModule(outputs.getSecond(), module, true);
}
final Ref status = new Ref();
@@ -188,7 +184,7 @@ public class CompileDriver {
final int CACHE_FORMAT_VERSION;
final boolean COMPILATION_IN_PROGRESS;
- public CompileStatus(int cacheVersion, boolean isCompilationInProgress) {
+ private CompileStatus(int cacheVersion, boolean isCompilationInProgress) {
CACHE_FORMAT_VERSION = cacheVersion;
COMPILATION_IN_PROGRESS = isCompilationInProgress;
}
@@ -260,10 +256,11 @@ public class CompileDriver {
private CompileScope addAdditionalRoots(CompileScope originalScope) {
CompileScope scope = originalScope;
final Set affected = new HashSet(Arrays.asList(originalScope.getAffectedModules()));
- for (final Pair pair : myGenerationCompilerModuleToOutputDirMap.keySet()) {
- if (affected.contains(pair.getSecond())) {
- final Pair outputs = myGenerationCompilerModuleToOutputDirMap.get(pair);
- scope = new CompositeScope(scope, new FileSetCompileScope(new VirtualFile[]{outputs.getFirst(), outputs.getSecond()}, new Module[]{pair.getSecond()}));
+ for (Map.Entry, Pair> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) {
+ Module module = entry.getKey().getSecond();
+ if (affected.contains(module)) {
+ final Pair outputs = entry.getValue();
+ scope = new CompositeScope(scope, new FileSetCompileScope(new VirtualFile[]{outputs.getFirst(), outputs.getSecond()}, new Module[]{module}));
}
}
@@ -303,10 +300,11 @@ public class CompileDriver {
final CompileContextImpl compileContext =
new CompileContextImpl(myProject, compileTask, scope, dependencyCache, !isRebuild && !forceCompile, isRebuild);
compileContext.putUserData(COMPILATION_START_TIMESTAMP, LocalTimeCounter.currentTime());
- for (Pair pair : myGenerationCompilerModuleToOutputDirMap.keySet()) {
- final Pair outputs = myGenerationCompilerModuleToOutputDirMap.get(pair);
- compileContext.assignModule(outputs.getFirst(), pair.getSecond(), false);
- compileContext.assignModule(outputs.getSecond(), pair.getSecond(), true);
+ for (Map.Entry, Pair> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) {
+ final Pair outputs = entry.getValue();
+ Module module = entry.getKey().getSecond();
+ compileContext.assignModule(outputs.getFirst(), module, false);
+ compileContext.assignModule(outputs.getSecond(), module, true);
}
compileTask.start(new Runnable() {
@@ -355,7 +353,6 @@ public class CompileDriver {
ExitStatus status = ExitStatus.ERRORS;
boolean wereExceptions = false;
try {
- compileContext.getProgressIndicator().pushState();
if (checkCachesVersion) {
checkCachesVersion(compileContext);
if (compileContext.isRebuildRequested()) {
@@ -379,7 +376,6 @@ public class CompileDriver {
}
finally {
dropDependencyCache(compileContext);
- compileContext.getProgressIndicator().popState();
final ExitStatus _status = status;
if (compileContext.isRebuildRequested()) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -464,7 +460,7 @@ public class CompileDriver {
private static class ExitException extends Exception {
private final ExitStatus myStatus;
- public ExitException(ExitStatus status) {
+ private ExitException(ExitStatus status) {
myStatus = status;
}
@@ -473,7 +469,7 @@ public class CompileDriver {
}
}
- private ExitStatus doCompile(CompileContextEx context,
+ private ExitStatus doCompile(final CompileContextEx context,
boolean isRebuild,
final boolean forceCompile,
final boolean trackDependencies,
@@ -491,17 +487,11 @@ public class CompileDriver {
}
if (!onlyCheckStatus) {
- try {
- context.getProgressIndicator().pushState();
- if (!executeCompileTasks(context, true)) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Compilation cancelled");
- }
- return ExitStatus.CANCELLED;
+ if (!executeCompileTasks(context, true)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Compilation cancelled");
}
- }
- finally {
- context.getProgressIndicator().popState();
+ return ExitStatus.CANCELLED;
}
}
@@ -512,42 +502,8 @@ public class CompileDriver {
return ExitStatus.ERRORS;
}
- // need this to make sure the VFS is built
- boolean needRecalcOutputDirs = false;
- final List outputsToRefresh = new ArrayList();
- for (VirtualFile output : context.getAllOutputDirectories()) {
- if (output.isValid()) {
- walkChildren(output, context);
- }
- else {
- needRecalcOutputDirs = true;
- final File file = new File(output.getPath());
- if (!file.exists()) {
- final boolean created = file.mkdirs();
- if (!created) {
- context.addMessage(CompilerMessageCategory.ERROR, "Failed to create output directory " + file.getPath(), null, 0, 0);
- return ExitStatus.ERRORS;
- }
- }
- output = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
- if (output == null) {
- context.addMessage(CompilerMessageCategory.ERROR, "Failed to locate output directory " + file.getPath(), null, 0, 0);
- return ExitStatus.ERRORS;
- }
- }
- outputsToRefresh.add(output);
- }
- for (Pair pair : myGenerationCompilerModuleToOutputDirMap.keySet()) {
- final Pair generated = myGenerationCompilerModuleToOutputDirMap.get(pair);
- walkChildren(generated.getFirst(), context);
- outputsToRefresh.add(generated.getFirst());
- walkChildren(generated.getSecond(), context);
- outputsToRefresh.add(generated.getSecond());
- }
- RefreshQueue.getInstance().refresh(false, true, null, outputsToRefresh.toArray(new VirtualFile[outputsToRefresh.size()]));
- if (needRecalcOutputDirs) {
- context.recalculateOutputDirs();
- }
+ final ExitStatus status = refreshFiles(context);
+ if (status != null) return status;
boolean didSomething = false;
@@ -557,23 +513,24 @@ public class CompileDriver {
didSomething |= generateSources(compilerManager, context, forceCompile, onlyCheckStatus);
didSomething |= invokeFileProcessingCompilers(compilerManager, context, SourceInstrumentingCompiler.class,
- myProcessingCompilerAdapterFactory, forceCompile, true, onlyCheckStatus);
+ FILE_PROCESSING_COMPILER_ADAPTER_FACTORY, forceCompile, true, onlyCheckStatus);
didSomething |= translate(context, compilerManager, forceCompile, isRebuild, trackDependencies, outputDirectories, onlyCheckStatus);
didSomething |= invokeFileProcessingCompilers(compilerManager, context, ClassInstrumentingCompiler.class,
- myProcessingCompilerAdapterFactory, isRebuild, false, onlyCheckStatus);
+ FILE_PROCESSING_COMPILER_ADAPTER_FACTORY, isRebuild, false, onlyCheckStatus);
// explicitly passing forceCompile = false because in scopes that is narrower than ProjectScope it is impossible
// to understand whether the class to be processed is in scope or not. Otherwise compiler may process its items even if
// there were changes in completely independent files.
didSomething |= invokeFileProcessingCompilers(compilerManager, context, ClassPostProcessingCompiler.class,
- myProcessingCompilerAdapterFactory, isRebuild, false, onlyCheckStatus);
+ FILE_PROCESSING_COMPILER_ADAPTER_FACTORY, isRebuild, false, onlyCheckStatus);
- didSomething |= invokeFileProcessingCompilers(compilerManager, context, PackagingCompiler.class, myPackagingCompilerAdapterFactory,
+ didSomething |= invokeFileProcessingCompilers(compilerManager, context, PackagingCompiler.class,
+ FILE_PACKAGING_COMPILER_ADAPTER_FACTORY,
isRebuild, false, onlyCheckStatus);
- didSomething |= invokeFileProcessingCompilers(compilerManager, context, Validator.class, myProcessingCompilerAdapterFactory,
+ didSomething |= invokeFileProcessingCompilers(compilerManager, context, Validator.class, FILE_PROCESSING_COMPILER_ADAPTER_FACTORY,
forceCompile, true, onlyCheckStatus);
}
catch (ExitException e) {
@@ -590,14 +547,15 @@ public class CompileDriver {
final VirtualFile[] allOutputDirs = context.getAllOutputDirectories();
if (didSomething && GENERATE_CLASSPATH_INDEX) {
- context.getProgressIndicator().pushState();
- context.getProgressIndicator().setText("Generating classpath index...");
- int count = 0;
- for (VirtualFile file : allOutputDirs) {
- context.getProgressIndicator().setFraction(((double)++count) / allOutputDirs.length);
- createClasspathIndex(file);
- }
- context.getProgressIndicator().popState();
+ runInContext(context, "Generating classpath index...", new ThrowableRunnable(){
+ public void run() {
+ int count = 0;
+ for (VirtualFile file : allOutputDirs) {
+ context.getProgressIndicator().setFraction((double)++count / allOutputDirs.length);
+ createClasspathIndex(file);
+ }
+ }
+ });
}
if (!context.getProgressIndicator().isCanceled() && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
@@ -610,14 +568,8 @@ public class CompileDriver {
}
if (!onlyCheckStatus) {
- try {
- context.getProgressIndicator().pushState();
- if (!executeCompileTasks(context, false)) {
- return ExitStatus.CANCELLED;
- }
- }
- finally {
- context.getProgressIndicator().popState();
+ if (!executeCompileTasks(context, false)) {
+ return ExitStatus.CANCELLED;
}
}
@@ -637,6 +589,53 @@ public class CompileDriver {
}
}
+ private ExitStatus refreshFiles(final CompileContextEx context) {
+ final ExitStatus[] status = {null};
+ runInContext(context, "Refreshing files...",new ThrowableRunnable(){
+ public void run() {
+ // need this to make sure the VFS is built
+ boolean needRecalcOutputDirs = false;
+ final List outputsToRefresh = new ArrayList();
+ for (VirtualFile output : context.getAllOutputDirectories()) {
+ if (output.isValid()) {
+ walkChildren(output, context);
+ }
+ else {
+ needRecalcOutputDirs = true;
+ final File file = new File(output.getPath());
+ if (!file.exists()) {
+ final boolean created = file.mkdirs();
+ if (!created) {
+ context.addMessage(CompilerMessageCategory.ERROR, "Failed to create output directory " + file.getPath(), null, 0, 0);
+ status[0] = ExitStatus.ERRORS;
+ return;
+ }
+ }
+ output = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+ if (output == null) {
+ context.addMessage(CompilerMessageCategory.ERROR, "Failed to locate output directory " + file.getPath(), null, 0, 0);
+ status[0] = ExitStatus.ERRORS;
+ return;
+ }
+ }
+ outputsToRefresh.add(output);
+ }
+ for (Map.Entry, Pair> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) {
+ final Pair generated = entry.getValue();
+ walkChildren(generated.getFirst(), context);
+ outputsToRefresh.add(generated.getFirst());
+ walkChildren(generated.getSecond(), context);
+ outputsToRefresh.add(generated.getSecond());
+ }
+ RefreshQueue.getInstance().refresh(false, true, null, outputsToRefresh.toArray(new VirtualFile[outputsToRefresh.size()]));
+ if (needRecalcOutputDirs) {
+ context.recalculateOutputDirs();
+ }
+ }
+ });
+ return status[0];
+ }
+
private static void logErrorMessages(final CompileContext context) {
final CompilerMessage[] errors = context.getMessages(CompilerMessageCategory.ERROR);
if (errors.length > 0) {
@@ -700,14 +699,11 @@ public class CompileDriver {
}
private static void dropDependencyCache(final CompileContextEx context) {
- context.getProgressIndicator().pushState();
- try {
- context.getProgressIndicator().setText(CompilerBundle.message("progress.saving.caches"));
- context.getDependencyCache().dispose();
- }
- finally {
- context.getProgressIndicator().popState();
- }
+ runInContext(context, CompilerBundle.message("progress.saving.caches"), new ThrowableRunnable(){
+ public void run() {
+ context.getDependencyCache().dispose();
+ }
+ });
}
private boolean generateSources(final CompilerManager compilerManager,
@@ -867,70 +863,78 @@ public class CompileDriver {
return map;
}
- private void deleteAll(final CompileContextEx context, Set outputDirectories) {
+ private static void runInContext(CompileContext context, String title, ThrowableRunnable action) throws T {
context.getProgressIndicator().pushState();
+ context.getProgressIndicator().setText(title);
try {
- final boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode();
- final VirtualFile[] allSources = context.getProjectCompileScope().getFiles(null, true);
- context.getProgressIndicator().setText(CompilerBundle.message("progress.clearing.output"));
- if (myShouldClearOutputDirectory) {
- clearOutputDirectories(outputDirectories);
- }
- else { // refresh is still required
- try {
- for (final Compiler compiler : CompilerManager.getInstance(myProject).getCompilers(Compiler.class)) {
- try {
- if (compiler instanceof GeneratingCompiler) {
- final StateCache cache = getGeneratingCompilerCache((GeneratingCompiler)compiler);
- final Iterator urlIterator = cache.getUrlsIterator();
- while (urlIterator.hasNext()) {
- context.getProgressIndicator().checkCanceled();
- deleteFile(new File(VirtualFileManager.extractPath(urlIterator.next())));
- }
- }
- else if (compiler instanceof TranslatingCompiler) {
- final ArrayList> toDelete = new ArrayList>();
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- public void run() {
- TranslatingCompilerFilesMonitor.getInstance().collectFiles(
- context,
- (TranslatingCompiler)compiler, Arrays.asList(allSources).iterator(),
- true /*pass true to make sure that every source in scope file is processed*/,
- false /*important! should pass false to enable collection of files to delete*/,
- new ArrayList(),
- toDelete
- );
- }
- });
- for (Trinity trinity : toDelete) {
- context.getProgressIndicator().checkCanceled();
- final File file = trinity.getFirst();
- final boolean deleted = deleteFile(file);
- if (isTestMode && deleted) {
- CompilerManagerImpl.addDeletedPath(FileUtil.toSystemIndependentName(file.getPath()));
- }
- }
- }
- }
- catch (IOException e) {
- LOG.info(e);
- }
- }
- pruneEmptyDirectories(context.getProgressIndicator(), outputDirectories); // to avoid too much files deleted events
- }
- finally {
- CompilerUtil.refreshIODirectories(outputDirectories);
- }
- }
- dropScopesCaches();
-
- clearCompilerSystemDirectory(context);
+ action.run();
}
finally {
context.getProgressIndicator().popState();
}
}
+ private void deleteAll(final CompileContextEx context, final Set outputDirectories) {
+ runInContext(context, CompilerBundle.message("progress.clearing.output"), new ThrowableRunnable(){
+ public void run() {
+ final boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode();
+ final VirtualFile[] allSources = context.getProjectCompileScope().getFiles(null, true);
+ if (myShouldClearOutputDirectory) {
+ clearOutputDirectories(outputDirectories);
+ }
+ else { // refresh is still required
+ try {
+ for (final Compiler compiler : CompilerManager.getInstance(myProject).getCompilers(Compiler.class)) {
+ try {
+ if (compiler instanceof GeneratingCompiler) {
+ final StateCache cache = getGeneratingCompilerCache((GeneratingCompiler)compiler);
+ final Iterator urlIterator = cache.getUrlsIterator();
+ while (urlIterator.hasNext()) {
+ context.getProgressIndicator().checkCanceled();
+ deleteFile(new File(VirtualFileManager.extractPath(urlIterator.next())));
+ }
+ }
+ else if (compiler instanceof TranslatingCompiler) {
+ final ArrayList> toDelete = new ArrayList>();
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ public void run() {
+ TranslatingCompilerFilesMonitor.getInstance().collectFiles(
+ context,
+ (TranslatingCompiler)compiler, Arrays.asList(allSources).iterator(),
+ true /*pass true to make sure that every source in scope file is processed*/,
+ false /*important! should pass false to enable collection of files to delete*/,
+ new ArrayList(),
+ toDelete
+ );
+ }
+ });
+ for (Trinity trinity : toDelete) {
+ context.getProgressIndicator().checkCanceled();
+ final File file = trinity.getFirst();
+ final boolean deleted = deleteFile(file);
+ if (isTestMode && deleted) {
+ CompilerManagerImpl.addDeletedPath(FileUtil.toSystemIndependentName(file.getPath()));
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ }
+ pruneEmptyDirectories(context.getProgressIndicator(), outputDirectories); // to avoid too much files deleted events
+ }
+ finally {
+ CompilerUtil.refreshIODirectories(outputDirectories);
+ }
+ }
+ dropScopesCaches();
+
+ clearCompilerSystemDirectory(context);
+ }
+ });
+ }
+
private void dropScopesCaches() {
// hack to be sure the classpath will include the output directories
ApplicationManager.getApplication().runReadAction(new Runnable() {
@@ -946,23 +950,26 @@ public class CompileDriver {
}
}
- private static boolean doPrune(ProgressIndicator progress, final File directory, final Set outPutDirectories) {
+ private static boolean doPrune(ProgressIndicator progress, final File directory, final Set outputDirectories) {
progress.checkCanceled();
final File[] files = directory.listFiles();
boolean isEmpty = true;
- if (files != null) {
+ if (files == null) {
+ isEmpty = false;
+ }
+ else {
for (File file : files) {
- if (file.isDirectory() && !outPutDirectories.contains(file)) {
- if (doPrune(progress, file, outPutDirectories)) {
+ if (outputDirectories.contains(file)) {
+ isEmpty = false;
+ }
+ else {
+ if (doPrune(progress, file, outputDirectories)) {
deleteFile(file);
}
else {
isEmpty = false;
}
}
- else {
- isEmpty = false;
- }
}
}
@@ -1074,13 +1081,13 @@ public class CompileDriver {
final List toGenerate = new ArrayList();
final List filesToRefresh = new ArrayList();
final List generatedFiles = new ArrayList();
- final List affectedModules = new ArrayList();
+ final Set affectedModules = new THashSet();
try {
final StateCache cache = getGeneratingCompilerCache(compiler);
final Set pathsToRemove = new HashSet(cache.getUrls());
final Map itemToOutputPathMap = new HashMap();
- final IOException[] ex = new IOException[] {null};
+ final IOException[] ex = {null};
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
for (final GeneratingCompiler.GenerationItem item : allItems) {
@@ -1091,7 +1098,7 @@ public class CompileDriver {
try {
final ValidityState savedState = cache.getState(outputPath);
-
+
if (forceGenerate || savedState == null || !savedState.equalsTo(item.getValidityState())) {
final String outputPathUrl = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, outputPath);
if (context.getCompileScope().belongs(outputPathUrl)) {
@@ -1131,20 +1138,21 @@ public class CompileDriver {
}
if (!pathsToRemove.isEmpty()) {
- context.getProgressIndicator().pushState();
- context.getProgressIndicator().setText(CompilerBundle.message("progress.synchronizing.output.directory"));
- for (final String path : pathsToRemove) {
- final File file = new File(path);
- final boolean deleted = deleteFile(file);
- if (deleted) {
- cache.remove(path);
- filesToRefresh.add(file);
+ runInContext(context, CompilerBundle.message("progress.synchronizing.output.directory"), new ThrowableRunnable(){
+ public void run() throws IOException {
+ for (final String path : pathsToRemove) {
+ final File file = new File(path);
+ final boolean deleted = deleteFile(file);
+ if (deleted) {
+ cache.remove(path);
+ filesToRefresh.add(file);
+ }
+ }
}
- }
- context.getProgressIndicator().popState();
+ });
}
- Map> moduleToItemMap =
+ final Map> moduleToItemMap =
buildModuleToGenerationItemMap(toGenerate.toArray(new GeneratingCompiler.GenerationItem[toGenerate.size()]));
List modules = new ArrayList(moduleToItemMap.size());
for (final Module module : moduleToItemMap.keySet()) {
@@ -1153,38 +1161,36 @@ public class CompileDriver {
ModuleCompilerUtil.sortModules(myProject, modules);
for (final Module module : modules) {
- context.getProgressIndicator().pushState();
- try {
- final Set items = moduleToItemMap.get(module);
- if (items != null && !items.isEmpty()) {
- final GeneratingCompiler.GenerationItem[][] productionAndTestItems = splitGenerationItems(items);
- boolean moduleAffected = false;
- for (GeneratingCompiler.GenerationItem[] _items : productionAndTestItems) {
- if (_items.length > 0) {
- final VirtualFile outputDir = getGenerationOutputDir(compiler, module, _items[0].isTestSource());
- final GeneratingCompiler.GenerationItem[] successfullyGenerated = compiler.generate(context, _items, outputDir);
- context.getProgressIndicator().setText(CompilerBundle.message("progress.updating.caches"));
- if (successfullyGenerated.length > 0) {
- moduleAffected = true;
- }
- for (final GeneratingCompiler.GenerationItem item : successfullyGenerated) {
- final String fullOutputPath = itemToOutputPathMap.get(item);
- cache.update(fullOutputPath, item.getValidityState());
- final File file = new File(fullOutputPath);
- filesToRefresh.add(file);
- generatedFiles.add(file);
+ runInContext(context, "Generating output from "+compiler.getDescription(),new ThrowableRunnable(){
+ public void run() throws IOException {
+ final Set items = moduleToItemMap.get(module);
+ if (items != null && !items.isEmpty()) {
+ final GeneratingCompiler.GenerationItem[][] productionAndTestItems = splitGenerationItems(items);
+ for (GeneratingCompiler.GenerationItem[] _items : productionAndTestItems) {
+ if (_items.length > 0) {
+ final VirtualFile outputDir = getGenerationOutputDir(compiler, module, _items[0].isTestSource());
+ final GeneratingCompiler.GenerationItem[] successfullyGenerated = compiler.generate(context, _items, outputDir);
+
+ context.getProgressIndicator().setText(CompilerBundle.message("progress.updating.caches"));
+ runInContext(context, CompilerBundle.message("progress.updating.caches"), new ThrowableRunnable() {
+ public void run() throws IOException {
+ if (successfullyGenerated.length > 0) {
+ affectedModules.add(module);
+ }
+ for (final GeneratingCompiler.GenerationItem item : successfullyGenerated) {
+ final String fullOutputPath = itemToOutputPathMap.get(item);
+ cache.update(fullOutputPath, item.getValidityState());
+ final File file = new File(fullOutputPath);
+ filesToRefresh.add(file);
+ generatedFiles.add(file);
+ }
+ }
+ });
}
}
}
-
- if (moduleAffected) {
- affectedModules.add(module);
- }
}
- }
- finally {
- context.getProgressIndicator().popState();
- }
+ });
}
}
catch (IOException e) {
@@ -1193,7 +1199,6 @@ public class CompileDriver {
throw new ExitException(ExitStatus.ERRORS);
}
finally {
- context.getProgressIndicator().pushState();
CompilerUtil.refreshIOFiles(filesToRefresh);
if (!generatedFiles.isEmpty()) {
List vFiles = ApplicationManager.getApplication().runReadAction(new Computable>() {
@@ -1244,116 +1249,118 @@ public class CompileDriver {
final boolean trackDependencies,
final Set outputDirectories,
final boolean onlyCheckStatus) throws ExitException {
-
-
final Set toCompile = new HashSet();
final List> toDelete = new ArrayList>();
- context.getProgressIndicator().pushState();
- final boolean[] wereFilesDeleted = new boolean[]{false};
- try {
- final TranslatingCompilerFilesMonitor monitor = TranslatingCompilerFilesMonitor.getInstance();
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- public void run() {
-
- TranslatingCompilerFilesMonitor.getInstance().collectFiles(
- context, compiler, Arrays.asList(snapshot).iterator(), forceCompile, isRebuild, toCompile, toDelete
- );
- if (trackDependencies && !toCompile.isEmpty()) { // should add dependent files
- final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
- final PsiManager psiManager = PsiManager.getInstance(myProject);
- final VirtualFile[] filesToCompile = toCompile.toArray(new VirtualFile[toCompile.size()]);
- for (final VirtualFile file : filesToCompile) {
- if (fileTypeManager.getFileTypeByFile(file) == StdFileTypes.JAVA) {
- final PsiFile psiFile = psiManager.findFile(file);
- if (psiFile != null) {
- addDependentFiles(psiFile, toCompile, compiler, context);
+ final boolean[] wereFilesDeleted = {false};
+ runInContext(context, "Compiling using "+compiler.getDescription(), new ThrowableRunnable(){
+ public void run() throws ExitException {
+ try {
+ final TranslatingCompilerFilesMonitor monitor = TranslatingCompilerFilesMonitor.getInstance();
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ public void run() {
+ TranslatingCompilerFilesMonitor.getInstance().collectFiles(
+ context, compiler, Arrays.asList(snapshot).iterator(), forceCompile, isRebuild, toCompile, toDelete
+ );
+ if (trackDependencies && !toCompile.isEmpty()) { // should add dependent files
+ final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
+ final PsiManager psiManager = PsiManager.getInstance(myProject);
+ final VirtualFile[] filesToCompile = toCompile.toArray(new VirtualFile[toCompile.size()]);
+ for (final VirtualFile file : filesToCompile) {
+ if (fileTypeManager.getFileTypeByFile(file) == StdFileTypes.JAVA) {
+ final PsiFile psiFile = psiManager.findFile(file);
+ if (psiFile != null) {
+ addDependentFiles(psiFile, toCompile, compiler, context);
+ }
+ }
}
}
}
+ });
+
+ if (onlyCheckStatus) {
+ if (toDelete.isEmpty() && toCompile.isEmpty()) {
+ return;
+ }
+ if (LOG.isDebugEnabled()) {
+ if (!toDelete.isEmpty()) {
+ LOG.debug("Found items to delete, compiler " + compiler.getDescription());
+ }
+ if (!toCompile.isEmpty()) {
+ LOG.debug("Found items to compile, compiler " + compiler.getDescription());
+ }
+ }
+ throw new ExitException(ExitStatus.CANCELLED);
}
- }
- });
- if (onlyCheckStatus) {
- if (toDelete.isEmpty() && toCompile.isEmpty()) {
- return false;
- }
- if (LOG.isDebugEnabled()) {
if (!toDelete.isEmpty()) {
- LOG.debug("Found items to delete, compiler " + compiler.getDescription());
+ try {
+ wereFilesDeleted[0] = syncOutputDir(context, toDelete, outputDirectories);
+ }
+ catch (CacheCorruptedException e) {
+ LOG.info(e);
+ context.requestRebuildNextTime(e.getMessage());
+ }
}
- if (!toCompile.isEmpty()) {
- LOG.debug("Found items to compile, compiler " + compiler.getDescription());
- }
- }
- throw new ExitException(ExitStatus.CANCELLED);
- }
- if (!toDelete.isEmpty()) {
- try {
- wereFilesDeleted[0] = syncOutputDir(context, toDelete, outputDirectories);
+ if ((wereFilesDeleted[0] || !toCompile.isEmpty()) && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
+ final TranslatingCompiler.ExitStatus exitStatus = compiler.compile(context, toCompile.toArray(new VirtualFile[toCompile.size()]));
+ monitor.update(context, exitStatus.getSuccessfullyCompiled(), exitStatus.getFilesToRecompile());
+ }
}
- catch (CacheCorruptedException e) {
+ catch (IOException e) {
LOG.info(e);
context.requestRebuildNextTime(e.getMessage());
+ throw new ExitException(ExitStatus.ERRORS);
}
}
-
- if ((wereFilesDeleted[0] || !toCompile.isEmpty()) && context.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
- final TranslatingCompiler.ExitStatus exitStatus = compiler.compile(context, toCompile.toArray(new VirtualFile[toCompile.size()]));
- monitor.update(context, exitStatus.getSuccessfullyCompiled(), exitStatus.getFilesToRecompile());
- }
- }
- catch (IOException e) {
- LOG.info(e);
- context.requestRebuildNextTime(e.getMessage());
- throw new ExitException(ExitStatus.ERRORS);
- }
- finally {
- context.getProgressIndicator().popState();
- }
+ });
return !toCompile.isEmpty() || wereFilesDeleted[0];
}
private static boolean syncOutputDir(final CompileContextEx context, final Collection> toDelete, final Set outputDirectories) throws CacheCorruptedException {
- int total = toDelete.size();
+ final int total = toDelete.size();
final DependencyCache dependencyCache = context.getDependencyCache();
final boolean isTestMode = ApplicationManager.getApplication().isUnitTestMode();
- context.getProgressIndicator().pushState();
final List filesToRefresh = new ArrayList();
try {
- context.getProgressIndicator().setText(CompilerBundle.message("progress.synchronizing.output.directory"));
- int current = 0;
- boolean wereFilesDeleted = false;
- for (final Trinity trinity : toDelete) {
- context.getProgressIndicator().setFraction(((double)(++current)) / total);
- context.getProgressIndicator().checkCanceled();
- final File outputPath = trinity.getFirst();
- filesToRefresh.add(outputPath);
- if (deleteFile(outputPath)) {
- wereFilesDeleted = true;
- final String className = trinity.getSecond();
- if (className != null) {
- final int id = dependencyCache.getSymbolTable().getId(className);
- dependencyCache.addTraverseRoot(id);
- final boolean sourcePresent = trinity.getThird().booleanValue();
- if (!sourcePresent) {
- dependencyCache.markSourceRemoved(id);
+ final boolean[] wereFilesDeleted = {false};
+ runInContext(context, CompilerBundle.message("progress.synchronizing.output.directory"), new ThrowableRunnable(){
+ public void run() throws CacheCorruptedException {
+ int current = 0;
+ for (final Trinity trinity : toDelete) {
+ context.getProgressIndicator().setFraction((double)++current / total);
+ context.getProgressIndicator().checkCanceled();
+ final File outputPath = trinity.getFirst();
+ filesToRefresh.add(outputPath);
+ if (deleteFile(outputPath)) {
+ wereFilesDeleted[0] = true;
+ final String className = trinity.getSecond();
+ if (className != null) {
+ final int id = dependencyCache.getSymbolTable().getId(className);
+ dependencyCache.addTraverseRoot(id);
+ final boolean sourcePresent = trinity.getThird().booleanValue();
+ if (!sourcePresent) {
+ dependencyCache.markSourceRemoved(id);
+ }
+ }
+ if (isTestMode) {
+ CompilerManagerImpl.addDeletedPath(outputPath.getPath());
+ }
}
}
- if (isTestMode) {
- CompilerManagerImpl.addDeletedPath(outputPath.getPath());
- }
+ runInContext(context, "Pruning empty directories...", new ThrowableRunnable() {
+ public void run() throws RuntimeException {
+ pruneEmptyDirectories(context.getProgressIndicator(), outputDirectories);
+ }
+ });
}
- }
- pruneEmptyDirectories(context.getProgressIndicator(), outputDirectories);
- return wereFilesDeleted;
+ });
+ return wereFilesDeleted[0];
}
finally {
CompilerUtil.refreshIOFiles(filesToRefresh);
- context.getProgressIndicator().popState();
}
}
@@ -1409,14 +1416,14 @@ public class CompileDriver {
final CompileScope scope = context.getCompileScope();
final List toProcess = new ArrayList();
final Set allUrls = new HashSet();
- final IOException[] ex = new IOException[] {null};
+ final IOException[] ex = {null};
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
try {
for (FileProcessingCompiler.ProcessingItem item : items) {
final VirtualFile file = item.getFile();
if (file == null) {
- LOG.assertTrue(false, "FileProcessingCompiler.ProcessingItem.getFile() must not return null: compiler " + adapter.getCompiler().getDescription());
+ LOG.error("FileProcessingCompiler.ProcessingItem.getFile() must not return null: compiler " + adapter.getCompiler().getDescription());
}
final String url = file.getUrl();
allUrls.add(url);
@@ -1446,26 +1453,27 @@ public class CompileDriver {
final Collection urls = cache.getUrls();
final List urlsToRemove = new ArrayList();
if (!urls.isEmpty()) {
- context.getProgressIndicator().pushState();
- context.getProgressIndicator().setText(CompilerBundle.message("progress.processing.outdated.files"));
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- public void run() {
- for (final String url : urls) {
- if (!allUrls.contains(url)) {
- if (!checkScope || scope.belongs(url)) {
- urlsToRemove.add(url);
+ runInContext(context, CompilerBundle.message("progress.processing.outdated.files"), new ThrowableRunnable(){
+ public void run() throws IOException {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ public void run() {
+ for (final String url : urls) {
+ if (!allUrls.contains(url)) {
+ if (!checkScope || scope.belongs(url)) {
+ urlsToRemove.add(url);
+ }
+ }
}
}
+ });
+ if (!onlyCheckStatus && !urlsToRemove.isEmpty()) {
+ for (final String url : urlsToRemove) {
+ adapter.processOutdatedItem(context, url, cache.getExtState(url));
+ cache.remove(url);
+ }
}
}
});
- if (!onlyCheckStatus && !urlsToRemove.isEmpty()) {
- for (final String url : urlsToRemove) {
- adapter.processOutdatedItem(context, url, cache.getExtState(url));
- cache.remove(url);
- }
- }
- context.getProgressIndicator().popState();
}
if (onlyCheckStatus) {
@@ -1493,33 +1501,33 @@ public class CompileDriver {
return false;
}
- context.getProgressIndicator().pushState();
final FileProcessingCompiler.ProcessingItem[] processed =
adapter.process(toProcess.toArray(new FileProcessingCompiler.ProcessingItem[toProcess.size()]));
- context.getProgressIndicator().popState();
if (processed.length > 0) {
- context.getProgressIndicator().pushState();
- context.getProgressIndicator().setText(CompilerBundle.message("progress.updating.caches"));
- List vFiles = new ArrayList(processed.length);
- for (FileProcessingCompiler.ProcessingItem aProcessed : processed) {
- final VirtualFile file = aProcessed.getFile();
- vFiles.add(file);
- if (LOG.isDebugEnabled()) {
- LOG.debug("File processed by " + adapter.getCompiler().getDescription());
- LOG.debug("\tFile processed " + file.getPresentableUrl() + "; ts=" + file.getTimeStamp());
+ runInContext(context, CompilerBundle.message("progress.updating.caches"), new ThrowableRunnable(){
+ public void run() {
+ List vFiles = new ArrayList(processed.length);
+ for (FileProcessingCompiler.ProcessingItem aProcessed : processed) {
+ final VirtualFile file = aProcessed.getFile();
+ vFiles.add(file);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("File processed by " + adapter.getCompiler().getDescription());
+ LOG.debug("\tFile processed " + file.getPresentableUrl() + "; ts=" + file.getTimeStamp());
+ }
+ }
+ LocalFileSystem.getInstance().refreshFiles(vFiles);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Files after VFS refresh:");
+ for (VirtualFile file : vFiles) {
+ LOG.debug("\t" + file.getPresentableUrl() + "; ts=" + file.getTimeStamp());
+ }
+ }
+ for (FileProcessingCompiler.ProcessingItem item : processed) {
+ cacheUpdater.addFileForUpdate(item, cache);
+ }
}
- }
- LocalFileSystem.getInstance().refreshFiles(vFiles);
- if (LOG.isDebugEnabled()) {
- LOG.debug("Files after VFS refresh:");
- for (VirtualFile file : vFiles) {
- LOG.debug("\t" + file.getPresentableUrl() + "; ts=" + file.getTimeStamp());
- }
- }
- for (FileProcessingCompiler.ProcessingItem item : processed) {
- cacheUpdater.addFileForUpdate(item, cache);
- }
+ });
}
return true;
}
@@ -1556,21 +1564,25 @@ public class CompileDriver {
}, null);
}
- private boolean executeCompileTasks(CompileContext context, boolean beforeTasks) {
+ private boolean executeCompileTasks(final CompileContext context, final boolean beforeTasks) {
final CompilerManager manager = CompilerManager.getInstance(myProject);
final ProgressIndicator progressIndicator = context.getProgressIndicator();
try {
- CompileTask[] tasks = beforeTasks ? manager.getBeforeTasks() : manager.getAfterTasks();
- if (tasks.length > 0) {
- progressIndicator.setText(beforeTasks
- ? CompilerBundle.message("progress.executing.precompile.tasks")
- : CompilerBundle.message("progress.executing.postcompile.tasks"));
- for (CompileTask task : tasks) {
- if (!task.execute(context)) {
- return false;
+ final boolean[] result = {true};
+ runInContext(context, beforeTasks
+ ? CompilerBundle.message("progress.executing.precompile.tasks")
+ : CompilerBundle.message("progress.executing.postcompile.tasks"),new ThrowableRunnable(){
+ public void run() {
+ CompileTask[] tasks = beforeTasks ? manager.getBeforeTasks() : manager.getAfterTasks();
+ for (CompileTask task : tasks) {
+ if (!task.execute(context)) {
+ result[0] = false;
+ return;
+ }
}
}
- }
+ });
+ return result[0];
}
finally {
WindowManager.getInstance().getStatusBar(myProject).setInfo("");
@@ -1582,7 +1594,6 @@ public class CompileDriver {
});
}
}
- return true;
}
// todo: add validation for module chunks: all modules that form a chunk must have the same JDK
@@ -1877,7 +1888,7 @@ public class CompileDriver {
}
public void doUpdate() throws IOException{
- final IOException[] ex = new IOException[] {null};
+ final IOException[] ex = {null};
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
try {
diff --git a/compiler/impl/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java b/compiler/impl/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
index c02f07acf67d..4627ee5efce0 100644
--- a/compiler/impl/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
+++ b/compiler/impl/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
@@ -172,7 +172,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
final Project project = context.getProject();
final int projectId = getProjectId(project);
final LocalFileSystem lfs = LocalFileSystem.getInstance();
- final IOException[] _ex = new IOException[] {null};
+ final IOException[] _ex = {null};
// need read action here to ensure that no modifications were made to VFS while updating file attributes
ApplicationManager.getApplication().runReadAction(new Runnable() {
@@ -1032,7 +1032,7 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent {
private final String mySrcUrl;
private final LocalFileSystem myFileSystem;
- public ScheduleOutputsForDeletionProc(final String srcUrl) {
+ private ScheduleOutputsForDeletionProc(final String srcUrl) {
mySrcUrl = srcUrl;
myFileSystem = LocalFileSystem.getInstance();
}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java
index cde55a4f0d32..022c495b58aa 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java
@@ -16,17 +16,16 @@ public interface BackendCompiler {
@NotNull @NonNls String getId(); // used for externalization
@NotNull String getPresentableName();
@NotNull Configurable createConfigurable();
- @NotNull
- Set getCompilableFileTypes();
- @Nullable OutputParser createErrorParser(final String outputDir);
- @Nullable OutputParser createOutputParser(final String outputDir);
+ @NotNull Set getCompilableFileTypes();
+ @Nullable OutputParser createErrorParser(@NotNull String outputDir);
+ @Nullable OutputParser createOutputParser(@NotNull String outputDir);
boolean checkCompiler(final CompileScope scope);
@NotNull Process launchProcess(
- final ModuleChunk chunk,
- final String outputDir,
- final CompileContext compileContext) throws IOException;
+ @NotNull ModuleChunk chunk,
+ @NotNull String outputDir,
+ @NotNull CompileContext compileContext) throws IOException;
void compileFinished();
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java
index 5a6209ac99a9..c76a6bc0dc9b 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java
@@ -35,17 +35,17 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.cls.ClsFormatException;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import java.io.File;
-import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
@@ -64,35 +64,36 @@ public class BackendCompilerWrapper {
private final List myOutputItems;
private final CompileContextEx myCompileContext;
- private final VirtualFile[] myFilesToCompile;
+ private final List myFilesToCompile;
private final Project myProject;
private final Set myFilesToRecompile;
private final Map myModuleToTempDirMap = new HashMap();
private final ProjectFileIndex myProjectFileIndex;
@NonNls private static final String PACKAGE_ANNOTATION_FILE_NAME = "package-info.java";
+ private static final FileObject myStopThreadToken = new FileObject(null,null);
- public BackendCompilerWrapper(final Project project,
- VirtualFile[] filesToCompile,
- CompileContextEx compileContext,
- BackendCompiler compiler) {
+ public BackendCompilerWrapper(@NotNull final Project project,
+ @NotNull List filesToCompile,
+ @NotNull CompileContextEx compileContext,
+ @NotNull BackendCompiler compiler) {
myProject = project;
myCompiler = compiler;
myCompileContext = compileContext;
myFilesToCompile = filesToCompile;
- myFilesToRecompile = new HashSet(Arrays.asList(filesToCompile));
+ myFilesToRecompile = new HashSet(filesToCompile);
myProjectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
- mySuccesfullyCompiledJavaFiles = new HashSet(filesToCompile.length);
- myOutputItems = new ArrayList(filesToCompile.length);
- myFileNameToSourceMap = new HashMap>(filesToCompile.length);
- myFilesToRefresh = new ArrayList(filesToCompile.length);
+ mySuccesfullyCompiledJavaFiles = new HashSet(filesToCompile.size());
+ myOutputItems = new ArrayList(filesToCompile.size());
+ myFileNameToSourceMap = new HashMap>(filesToCompile.size());
+ myFilesToRefresh = new ArrayList(filesToCompile.size());
}
- public TranslatingCompiler.OutputItem[] compile() throws CompilerException, CacheCorruptedException {
+ public List compile() throws CompilerException, CacheCorruptedException {
Application application = ApplicationManager.getApplication();
final Set allDependent = new HashSet();
COMPILE:
try {
- if (myFilesToCompile.length > 0) {
+ if (!myFilesToCompile.isEmpty()) {
if (application.isUnitTestMode()) {
saveTestData();
}
@@ -101,20 +102,18 @@ public class BackendCompilerWrapper {
compileModules(moduleToFilesMap);
}
-
- VirtualFile[] dependentFiles;
+ Collection dependentFiles;
do {
dependentFiles = findDependentFiles();
- if (dependentFiles.length > 0) {
- final List deps = Arrays.asList(dependentFiles);
- myFilesToRecompile.addAll(deps);
- allDependent.addAll(deps);
+ if (!dependentFiles.isEmpty()) {
+ myFilesToRecompile.addAll(dependentFiles);
+ allDependent.addAll(dependentFiles);
if (myCompileContext.getProgressIndicator().isCanceled() || myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
break COMPILE;
}
- final VirtualFile[] filesInScope = getFilesInScope(dependentFiles);
- if (filesInScope.length == 0) {
+ final List filesInScope = getFilesInScope(dependentFiles);
+ if (filesInScope.isEmpty()) {
break;
}
final Map> moduleToFilesMap = buildModuleToFilesMap(myCompileContext, filesInScope);
@@ -122,7 +121,7 @@ public class BackendCompilerWrapper {
compileModules(moduleToFilesMap);
}
}
- while (dependentFiles.length > 0 && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0);
+ while (!dependentFiles.isEmpty() && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0);
}
catch (IOException e) {
throw new CompilerException(CompilerBundle.message("error.compiler.process.not.started", e.getMessage()), e);
@@ -151,7 +150,7 @@ public class BackendCompilerWrapper {
if (myCompileContext.getProgressIndicator().isCanceled()) {
myFilesToRecompile.clear();
// when cancelled pretend nothing was compiled and next compile will compile everything from the scratch
- return TranslatingCompiler.EMPTY_OUTPUT_ITEM_ARRAY;
+ return Collections.emptyList();
}
// do not update caches if cancelled because there is a chance that they will be incomplete
@@ -163,7 +162,7 @@ public class BackendCompilerWrapper {
myFilesToRecompile.addAll(allDependent);
}
processPackageInfoFiles();
- return myOutputItems.toArray(new TranslatingCompiler.OutputItem[myOutputItems.size()]);
+ return myOutputItems;
}
// package-info.java hack
@@ -192,8 +191,8 @@ public class BackendCompilerWrapper {
});
}
- private VirtualFile[] getFilesInScope(final VirtualFile[] dependentFiles) {
- final List filesInScope = new ArrayList(dependentFiles.length);
+ private List getFilesInScope(final Collection dependentFiles) {
+ final List filesInScope = new ArrayList(dependentFiles.size());
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
for (VirtualFile dependentFile : dependentFiles) {
@@ -203,7 +202,7 @@ public class BackendCompilerWrapper {
}
}
});
- return filesInScope.toArray(new VirtualFile[filesInScope.size()]);
+ return filesInScope;
}
private void compileModules(final Map> moduleToFilesMap) throws IOException {
@@ -328,7 +327,7 @@ public class BackendCompilerWrapper {
private final TIntHashSet myProcessedNames = new TIntHashSet();
private final Set myProcessedFiles = new HashSet();
- private VirtualFile[] findDependentFiles() throws CacheCorruptedException {
+ private Collection findDependentFiles() throws CacheCorruptedException {
myCompileContext.getProgressIndicator().setText(CompilerBundle.message("progress.checking.dependencies"));
final DependencyCache dependencyCache = myCompileContext.getDependencyCache();
@@ -388,7 +387,7 @@ public class BackendCompilerWrapper {
}
myCompileContext.getProgressIndicator().setText(CompilerBundle.message("progress.found.dependent.files", dependentFiles.size()));
- return dependentFiles.toArray(new VirtualFile[dependentFiles.size()]);
+ return dependentFiles;
}
private final Object lock = new Object();
@@ -424,14 +423,14 @@ public class BackendCompilerWrapper {
}
}
- protected void processCompiledClass(final String classFileToProcess) throws CacheCorruptedException {
+ protected void processCompiledClass(final FileObject classFileToProcess) throws CacheCorruptedException {
synchronized (lock) {
myClassParsingThread.addPath(classFileToProcess);
}
}
}
- private void doCompile(final ModuleChunk chunk, String outputDir, int sourcesFilter) throws IOException {
+ private void doCompile(@NotNull final ModuleChunk chunk, @NotNull String outputDir, int sourcesFilter) throws IOException {
myCompileContext.getProgressIndicator().checkCanceled();
chunk.setSourcesFilter(sourcesFilter);
@@ -866,7 +865,7 @@ public class BackendCompilerWrapper {
myCompileContext.getProgressIndicator().setText2(msg);
}
- private static Map> buildModuleToFilesMap(final CompileContext context, final VirtualFile[] files) {
+ private static Map> buildModuleToFilesMap(final CompileContext context, final List files) {
final Map> map = new HashMap>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
@@ -890,9 +889,8 @@ public class BackendCompilerWrapper {
}
private class ClassParsingThread implements Runnable {
- private final BlockingQueue myPaths = new ArrayBlockingQueue(50000);
+ private final BlockingQueue myPaths = new ArrayBlockingQueue(50000);
private CacheCorruptedException myError = null;
- private final String myStopThreadToken = new String();
private final boolean myAddNotNullAssertions;
private final boolean myIsJdk16;
@@ -903,10 +901,11 @@ public class BackendCompilerWrapper {
public void run() {
try {
- //noinspection StringEquality
- String path;
- while ((path = getNextPath()) != myStopThreadToken) {
- processPath(path.replace('/', File.separatorChar));
+ while (true) {
+ FileObject path = myPaths.take();
+
+ if (path == myStopThreadToken) break;
+ processPath(path);
}
}
catch (InterruptedException e) {
@@ -917,30 +916,23 @@ public class BackendCompilerWrapper {
}
}
- public void addPath(String path) throws CacheCorruptedException {
+ public void addPath(FileObject path) throws CacheCorruptedException {
if (myError != null) {
throw myError;
}
myPaths.offer(path);
}
- private String getNextPath() throws InterruptedException {
- return myPaths.take();
- }
-
public void stopParsing() {
myPaths.offer(myStopThreadToken);
}
- private void processPath(final String path) throws CacheCorruptedException {
+ private void processPath(FileObject fileObject) throws CacheCorruptedException {
+ File file = fileObject.getFile();
+ byte[] fileContent = fileObject.getContent();
+ String path = file.getPath();
try {
- final File file = new File(path); // the file is assumed to exist!
- byte[] fileContent = ArrayUtil.EMPTY_BYTE_ARRAY;
- try{
- fileContent = FileUtil.loadFileBytes(file);
- }
- catch(IOException ignored){
- }
+ // the file is assumed to exist!
final DependencyCache dependencyCache = myCompileContext.getDependencyCache();
final int newClassQName = dependencyCache.reparseClassFile(file, fileContent);
@@ -949,7 +941,8 @@ public class BackendCompilerWrapper {
final String qName = dependencyCache.resolve(newClassQName);
String relativePathToSource = "/" + MakeUtil.createRelativePathToSource(qName, sourceFileName);
putName(sourceFileName, newClassQName, relativePathToSource, path);
-
+
+ boolean fileContentChanged = false;
if (myAddNotNullAssertions && hasNotNullAnnotations(newClassesCache, dependencyCache.getSymbolTable(), newClassQName)) {
try {
ClassReader reader = new ClassReader(fileContent, 0, fileContent.length);
@@ -958,19 +951,18 @@ public class BackendCompilerWrapper {
final NotNullVerifyingInstrumenter instrumenter = new NotNullVerifyingInstrumenter(writer);
reader.accept(instrumenter, 0);
if (instrumenter.isModification()) {
- final FileOutputStream output = new FileOutputStream(file);
- try {
- output.write(writer.toByteArray());
- }
- finally {
- output.close();
- }
+ fileContent = writer.toByteArray();
+ fileContentChanged = true;
}
}
catch (Exception ignored) {
LOG.info(ignored);
}
}
+
+ if (fileContentChanged || !fileObject.isSaved()) {
+ writeFile(file, fileContent);
+ }
}
catch (ClsFormatException e) {
String message;
@@ -983,11 +975,24 @@ public class BackendCompilerWrapper {
}
myCompileContext.addMessage(CompilerMessageCategory.ERROR, message, null, -1, -1);
}
+ catch (IOException e) {
+ myCompileContext.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
+ }
finally {
myClassesCount += 1;
updateStatistics();
}
}
+
+ private void writeFile(File file, byte[] fileContent) throws IOException {
+ try {
+ FileUtil.writeToFile(file, fileContent);
+ }
+ catch (FileNotFoundException e) {
+ FileUtil.createParentDirs(file);
+ FileUtil.writeToFile(file, fileContent);
+ }
+ }
}
private static boolean hasNotNullAnnotations(final Cache cache, final SymbolTable symbolTable, final int className) throws CacheCorruptedException {
@@ -1025,11 +1030,12 @@ public class BackendCompilerWrapper {
private final String myPath;
private final int myKind;
- private OutputDir(String path, int kind) {
+ private OutputDir(@NotNull String path, int kind) {
myPath = path;
myKind = kind;
}
+ @NotNull
public String getPath() {
return myPath;
}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/CompilerParsingThread.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/CompilerParsingThread.java
index 71d08533026c..7557fa39694d 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/CompilerParsingThread.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/CompilerParsingThread.java
@@ -24,10 +24,9 @@ public abstract class CompilerParsingThread implements Runnable, OutputParser.Ca
private boolean mySkipLF = false;
private Throwable myError = null;
private final boolean myIsUnitTestMode;
- private String myClassFileToProcess = null;
+ private FileObject myClassFileToProcess = null;
private String myLastReadLine = null;
- private boolean myProcessExited = false;
-
+ private volatile boolean myProcessExited = false;
public CompilerParsingThread(Process process, OutputParser outputParser, final boolean readErrorStream, boolean trimLines) {
myProcess = process;
@@ -44,7 +43,7 @@ public abstract class CompilerParsingThread implements Runnable, OutputParser.Ca
if (!myIsUnitTestMode && myProcess == null) {
break;
}
- if (isCanceled()) {
+ if (myProcessExited || isCanceled()) {
break;
}
if (!myOutputParser.processMessageLine(this)) {
@@ -57,6 +56,7 @@ public abstract class CompilerParsingThread implements Runnable, OutputParser.Ca
}
}
catch (Throwable e) {
+ e.printStackTrace();
myError = e;
LOG.info(e);
}
@@ -92,8 +92,8 @@ public abstract class CompilerParsingThread implements Runnable, OutputParser.Ca
return myLastReadLine;
}
- public final void fileGenerated(String path) {
- String previousPath = myClassFileToProcess;
+ public final void fileGenerated(FileObject path) {
+ FileObject previousPath = myClassFileToProcess;
myClassFileToProcess = path;
if (previousPath != null) {
try {
@@ -108,8 +108,7 @@ public abstract class CompilerParsingThread implements Runnable, OutputParser.Ca
protected abstract boolean isCanceled();
- protected abstract void processCompiledClass(final String classFileToProcess) throws CacheCorruptedException;
-
+ protected abstract void processCompiledClass(final FileObject classFileToProcess) throws CacheCorruptedException;
private String readLine(final Reader reader) {
StringBuilder buffer;
@@ -176,11 +175,11 @@ public abstract class CompilerParsingThread implements Runnable, OutputParser.Ca
}
}
- private synchronized boolean isProcessTerminated() {
+ private boolean isProcessTerminated() {
return myProcessExited;
}
- public synchronized void setProcessTerminated(final boolean procesExited) {
+ public void setProcessTerminated(final boolean procesExited) {
myProcessExited = procesExited;
}
}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/ExternalCompiler.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/ExternalCompiler.java
index f08abfd9f602..562861cbdb67 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/ExternalCompiler.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/ExternalCompiler.java
@@ -31,7 +31,7 @@ public abstract class ExternalCompiler implements BackendCompiler {
}
@NotNull
- public Process launchProcess(final ModuleChunk chunk, final String outputDir, final CompileContext compileContext) throws IOException {
+ public Process launchProcess(@NotNull final ModuleChunk chunk, @NotNull final String outputDir, @NotNull final CompileContext compileContext) throws IOException {
final String[] commands = createStartupCommand(chunk, compileContext, outputDir);
if (LOG.isDebugEnabled()) {
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/FileObject.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/FileObject.java
new file mode 100644
index 000000000000..919c724d1640
--- /dev/null
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/FileObject.java
@@ -0,0 +1,46 @@
+package com.intellij.compiler.impl.javaCompiler;
+
+import com.intellij.util.ArrayUtil;
+import com.intellij.openapi.util.io.FileUtil;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author cdr
+ */
+public class FileObject {
+ private final File myFile;
+ private final byte[] myContent;
+ private final boolean mySaved;
+
+ public FileObject(File file, byte[] content) {
+ myFile = file;
+ myContent = content;
+ mySaved = false;
+ }
+
+ public FileObject(File file) {
+ myFile = file;
+ byte[] fileContent = ArrayUtil.EMPTY_BYTE_ARRAY;
+ try{
+ fileContent = FileUtil.loadFileBytes(file);
+ }
+ catch(IOException ignored){
+ }
+ myContent = fileContent;
+ mySaved = true;
+ }
+
+ public File getFile() {
+ return myFile;
+ }
+
+ public byte[] getContent() {
+ return myContent;
+ }
+
+ public boolean isSaved() {
+ return mySaved;
+ }
+}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/JavaCompiler.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/JavaCompiler.java
index 782b1554aa37..13fc95e0cd8b 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/JavaCompiler.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/JavaCompiler.java
@@ -18,6 +18,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
public class JavaCompiler implements TranslatingCompiler {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.JavaCompiler");
private final Project myProject;
@@ -38,19 +42,19 @@ public class JavaCompiler implements TranslatingCompiler {
public ExitStatus compile(CompileContext context, VirtualFile[] files) {
final BackendCompiler backEndCompiler = getBackEndCompiler();
- final BackendCompilerWrapper wrapper = new BackendCompilerWrapper(myProject, files, (CompileContextEx)context, backEndCompiler);
- OutputItem[] outputItems;
+ final BackendCompilerWrapper wrapper = new BackendCompilerWrapper(myProject, Arrays.asList(files), (CompileContextEx)context, backEndCompiler);
+ List outputItems;
try {
outputItems = wrapper.compile();
}
catch (CompilerException e) {
- outputItems = EMPTY_OUTPUT_ITEM_ARRAY;
+ outputItems = Collections.emptyList();
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
}
catch (CacheCorruptedException e) {
LOG.info(e);
context.requestRebuildNextTime(e.getMessage());
- outputItems = EMPTY_OUTPUT_ITEM_ARRAY;
+ outputItems = Collections.emptyList();
}
return new ExitStatusImpl(outputItems, wrapper.getFilesToRecompile());
@@ -66,17 +70,16 @@ public class JavaCompiler implements TranslatingCompiler {
}
private static class ExitStatusImpl implements ExitStatus {
-
- private final OutputItem[] myOuitputItems;
+ private final List myOutputItems;
private final VirtualFile[] myMyFilesToRecompile;
- public ExitStatusImpl(OutputItem[] ouitputItems, VirtualFile[] myFilesToRecompile) {
- myOuitputItems = ouitputItems;
+ private ExitStatusImpl(List outputItems, VirtualFile[] myFilesToRecompile) {
+ myOutputItems = outputItems;
myMyFilesToRecompile = myFilesToRecompile;
}
public OutputItem[] getSuccessfullyCompiled() {
- return myOuitputItems;
+ return myOutputItems.toArray(new OutputItem[myOutputItems.size()]);
}
public VirtualFile[] getFilesToRecompile() {
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java
new file mode 100644
index 000000000000..4a2b644ca426
--- /dev/null
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompAPIDriver.java
@@ -0,0 +1,110 @@
+package com.intellij.compiler.impl.javaCompiler.api;
+
+import com.intellij.compiler.OutputParser;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import org.jetbrains.annotations.NotNull;
+
+import javax.tools.*;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.File;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * @author cdr
+ */
+@SuppressWarnings({"Since15"})
+public class CompAPIDriver {
+ private final BlockingQueue myCompilationResults = new LinkedBlockingQueue();
+ private static final CompilationEvent GUARD = new CompilationEvent() {
+ @Override
+ protected void process(OutputParser.Callback callback) {
+ }
+ };
+
+ public void compile(List commandLine, List paths, final String outputDir) {
+ JavaCompiler compiler = new com.sun.tools.javac.api.JavacTool(); //use current classloader
+ StandardJavaFileManager manager = new MyFileManager(this, outputDir);
+
+ Iterable extends JavaFileObject> input = manager.getJavaFileObjectsFromFiles(paths);
+
+ DiagnosticListener listener = new DiagnosticListener() {
+ public void report(Diagnostic extends JavaFileObject> diagnostic) {
+ CompilationEvent event = CompilationEvent.diagnostic(diagnostic);
+ myCompilationResults.offer(event);
+ }
+ };
+ try {
+ PrintWriter silent = new PrintWriter(new OutputStream(){
+ public void write(int b) {}
+ });
+
+ JavaCompiler.CompilationTask task = compiler.getTask(silent, manager, listener, commandLine, null, input);
+ ((JavacTask)task).setTaskListener(new TaskListener() {
+ public void started(TaskEvent taskEvent) {
+ JavaFileObject sourceFile = taskEvent.getSourceFile();
+ CompilationEvent event;
+ switch (taskEvent.getKind()) {
+ case ANALYZE:
+ event = CompilationEvent.progress("Analyzing ",sourceFile);
+ break;
+ case PARSE:
+ event = CompilationEvent.progress("Parsing ", sourceFile);
+ break;
+ default:
+ event = null;
+ }
+ if (event != null) {
+ myCompilationResults.offer(event);
+ }
+ }
+ public void finished(TaskEvent taskEvent) {
+ CompilationEvent event;
+ switch (taskEvent.getKind()) {
+ case ENTER:
+ event = CompilationEvent.fileProcessed();
+ break;
+ default:
+ event = null;
+ }
+ if (event != null) {
+ myCompilationResults.offer(event);
+ }
+ }
+ });
+ task.call();
+ }
+ finally {
+ myCompilationResults.offer(GUARD);
+ }
+ }
+
+ public boolean processAll(@NotNull OutputParser.Callback callback) {
+ try {
+ while (true) {
+ CompilationEvent event = myCompilationResults.take();
+ if (event == GUARD) break;
+ event.process(callback);
+ }
+ }
+ catch (InterruptedException ignored) {
+ System.out.println("ignored " + ignored);
+ }
+ return false;
+ }
+
+ public void finish() {
+ myCompilationResults.clear();
+ }
+
+
+ public void offer(CompilationEvent compilationEvent) {
+ myCompilationResults.offer(compilationEvent);
+ }
+}
+
+
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompilationEvent.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompilationEvent.java
new file mode 100644
index 000000000000..4835d32929f8
--- /dev/null
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompilationEvent.java
@@ -0,0 +1,70 @@
+package com.intellij.compiler.impl.javaCompiler.api;
+
+import com.intellij.compiler.OutputParser;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.compiler.CompilerMessageCategory;
+
+import javax.tools.JavaFileObject;
+import javax.tools.Diagnostic;
+import java.net.URI;
+import java.io.File;
+
+/**
+ * @author cdr
+ */
+@SuppressWarnings({"Since15"})
+abstract class CompilationEvent {
+ protected abstract void process(OutputParser.Callback callback);
+ static CompilationEvent progress(final String title, final JavaFileObject fileObject) {
+ return new CompilationEvent() {
+ @Override
+ protected void process(OutputParser.Callback callback) {
+ showProgressFor(title, fileObject.toUri(), callback);
+ }
+ };
+ }
+
+ private static void showProgressFor(String title, URI uri, OutputParser.Callback callback) {
+ callback.setProgressText(title + StringUtil.last(uri.toString(), 70, true));
+ }
+
+ static CompilationEvent generateClass(final URI uri, final byte[] bytes) {
+ return new CompilationEvent() {
+ @Override
+ protected void process(OutputParser.Callback callback) {
+ showProgressFor("Writing ", uri, callback);
+ File file = new File(uri);
+ callback.fileGenerated(new com.intellij.compiler.impl.javaCompiler.FileObject(file,bytes));
+ }
+ };
+ }
+ static CompilationEvent diagnostic(final Diagnostic extends JavaFileObject> diagnostic) {
+ return new CompilationEvent() {
+ @Override
+ protected void process(OutputParser.Callback callback) {
+ JavaFileObject fileObject = diagnostic.getSource();
+ String message = diagnostic.getMessage(null);
+ String url = fileObject == null ? null : VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(new File(fileObject.toUri()).getPath()));
+
+ CompilerMessageCategory category = diagnostic.getKind() == Diagnostic.Kind.ERROR
+ ? CompilerMessageCategory.ERROR
+ : diagnostic.getKind() == Diagnostic.Kind.WARNING ||
+ diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING
+ ? CompilerMessageCategory.WARNING
+ : CompilerMessageCategory.INFORMATION;
+ callback.message(category, message, url, (int)diagnostic.getLineNumber(), (int)diagnostic.getColumnNumber());
+ }
+ };
+ }
+
+ public static CompilationEvent fileProcessed() {
+ return new CompilationEvent() {
+ @Override
+ protected void process(OutputParser.Callback callback) {
+ callback.fileProcessed(null);
+ }
+ };
+ }
+}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java
new file mode 100644
index 000000000000..26f815531939
--- /dev/null
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/CompilerAPICompiler.java
@@ -0,0 +1,182 @@
+package com.intellij.compiler.impl.javaCompiler.api;
+
+import com.intellij.compiler.OutputParser;
+import com.intellij.compiler.impl.CompilerUtil;
+import com.intellij.compiler.impl.javaCompiler.BackendCompiler;
+import com.intellij.compiler.impl.javaCompiler.DependencyProcessor;
+import com.intellij.compiler.impl.javaCompiler.ModuleChunk;
+import com.intellij.compiler.impl.javaCompiler.javac.JavacCompiler;
+import com.intellij.compiler.impl.javaCompiler.javac.JavacConfigurable;
+import com.intellij.compiler.impl.javaCompiler.javac.JavacSettings;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileScope;
+import com.intellij.openapi.compiler.CompilerMessageCategory;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.*;
+
+
+public class CompilerAPICompiler implements BackendCompiler {
+ private final Project myProject;
+ private int myExitCode;
+ private static final Set COMPILABLE_TYPES = Collections.singleton(StdFileTypes.JAVA);
+ private final CompAPIDriver myCompAPIDriver = new CompAPIDriver();
+
+ public CompilerAPICompiler(Project project) {
+ myProject = project;
+ }
+
+ public DependencyProcessor getDependencyProcessor() {
+ return null;
+ }
+
+ public boolean checkCompiler(final CompileScope scope) {
+ final Module[] modules = scope.getAffectedModules();
+ final Set checkedJdks = new HashSet();
+ for (final Module module : modules) {
+ final Sdk jdk = ModuleRootManager.getInstance(module).getSdk();
+ if (jdk == null) {
+ continue;
+ }
+ checkedJdks.add(jdk);
+ }
+ Sdk projectJdk = ProjectRootManager.getInstance(myProject).getProjectJdk();
+ if (projectJdk != null) checkedJdks.add(projectJdk);
+
+ for (Sdk sdk : checkedJdks) {
+ if (!CompilerUtil.isOfVersion(sdk.getVersionString(), "1.6")) {
+ Messages.showErrorDialog(myProject, "Compiler API supports JDK of version 6 only: "+sdk.getVersionString(), "Incompatible JDK");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @NotNull
+ @NonNls
+ // used for externalization
+ public String getId() {
+ return "compAPI";
+ }
+
+ @NotNull
+ public String getPresentableName() {
+ return "Javac in-process (Java6 only)";
+ }
+
+ @NotNull
+ public Configurable createConfigurable() {
+ return new JavacConfigurable(JavacSettings.getInstance(myProject));
+ }
+
+ @NotNull
+ public Set getCompilableFileTypes() {
+ return COMPILABLE_TYPES;
+ }
+
+ @Nullable
+ public OutputParser createErrorParser(@NotNull final String outputDir) {
+ return new OutputParser() {
+ public boolean processMessageLine(Callback callback) {
+ return myCompAPIDriver.processAll(callback);
+ }
+ };
+ }
+
+ @Nullable
+ public OutputParser createOutputParser(@NotNull final String outputDir) {
+ return null;
+ }
+
+ public void compileFinished() {
+ myCompAPIDriver.finish();
+ }
+
+ @NotNull
+ public Process launchProcess(@NotNull final ModuleChunk chunk, @NotNull final String outputDir, @NotNull final CompileContext compileContext) throws IOException {
+ final IOException[] ex = {null};
+ @NonNls final List commandLine = ApplicationManager.getApplication().runReadAction(new Computable>() {
+ public List compute() {
+ try {
+ List commandLine = new ArrayList();
+ JavacSettings javacSettings = JavacSettings.getInstance(myProject);
+ final List additionalOptions =
+ JavacCompiler.addAdditionalSettings(commandLine, javacSettings, false, false, false, false, false);
+
+ JavacCompiler.addCommandLineOptions(chunk, commandLine, outputDir, chunk.getJdk(), false,false, null, false, false);
+ commandLine.addAll(additionalOptions);
+ return commandLine;
+ }
+ catch (IOException e) {
+ ex[0] = e;
+ }
+ return null;
+ }
+ });
+ if (ex[0] != null) {
+ throw ex[0];
+ }
+
+ return new Process() {
+ public OutputStream getOutputStream() {
+ throw new UnsupportedOperationException();
+ }
+
+ public InputStream getInputStream() {
+ return null;
+ }
+
+ public InputStream getErrorStream() {
+ return null;
+ }
+
+ public void destroy() {
+ }
+
+ public int waitFor() {
+ try {
+ //commandLine.remove("-verbose");
+ compile(commandLine, chunk, outputDir);
+ myExitCode = 0;
+ return myExitCode;
+ }
+ catch (Exception e) {
+ compileContext.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
+ myExitCode = -1;
+ return -1;
+ }
+ }
+
+ public int exitValue() {
+ return myExitCode;
+ }
+ };
+ }
+
+ private void compile(List commandLine, ModuleChunk chunk, String outputDir) {
+ VirtualFile[] filesToCompile = chunk.getFilesToCompile();
+ List paths = new ArrayList(filesToCompile.length);
+ for (VirtualFile file : filesToCompile) {
+ paths.add(new File(file.getPresentableUrl()));
+ }
+ myCompAPIDriver.compile(commandLine, paths, outputDir);
+ }
+}
\ No newline at end of file
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/MyFileManager.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/MyFileManager.java
new file mode 100644
index 000000000000..49f221d220e8
--- /dev/null
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/api/MyFileManager.java
@@ -0,0 +1,126 @@
+package com.intellij.compiler.impl.javaCompiler.api;
+
+import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.DefaultFileManager;
+import gnu.trove.THashMap;
+
+import javax.tools.FileObject;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author cdr
+*/
+class MyFileManager extends DefaultFileManager {
+ private final String myOutputDir;
+ private final CompAPIDriver myCompAPIDriver;
+ private final Map uri2Output = new THashMap();
+ private final Map uri2Source = new THashMap();
+
+ MyFileManager(CompAPIDriver compAPIDriver, String outputDir) {
+ super(new Context(), false, null);
+ myCompAPIDriver = compAPIDriver;
+ myOutputDir = outputDir;
+ }
+
+ @Override
+ public Iterable extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable extends File> files) {
+ //return super.getJavaFileObjectsFromFiles(files);
+ int size = ((Collection)files).size();
+ List result = new ArrayList(size);
+
+ for (File file : files) {
+ result.add(getSource(file));
+ }
+
+ return result;
+ }
+
+ private JavaFileObject getSource(File file) {
+ URI uri = file.toURI();
+ JavaFileObject fileObject = uri2Source.get(uri);
+ if (fileObject == null) {
+ fileObject = new JavaFile(file);
+ uri2Source.put(uri, fileObject);
+ }
+ return fileObject;
+ }
+ private JavaFileObject getOutput(URI uri) {
+ JavaFileObject fileObject = uri2Output.get(uri);
+ if (fileObject == null) {
+ fileObject = new Output(uri) {
+ protected void offerClassFile(URI uri, byte[] bytes) {
+ myCompAPIDriver.offer(CompilationEvent.generateClass(uri, bytes));
+ }
+ };
+ uri2Output.put(uri, fileObject);
+ }
+ return fileObject;
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject fileObject) {
+ return getOutput(toURI(myOutputDir,name));
+ }
+
+ private static class JavaFile extends SimpleJavaFileObject {
+ private final File myFile;
+
+ protected JavaFile(File file) {
+ super(file.toURI(), Kind.SOURCE);
+ myFile = file;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(myFile);
+ if (virtualFile == null) return null;
+ return LoadTextUtil.loadText(virtualFile);
+ }
+
+ @Override
+ public String toString() {
+ return toUri().toString();
+ }
+ }
+
+ private abstract static class Output extends SimpleJavaFileObject {
+ private Output(URI uri) {
+ super(uri, Kind.CLASS);
+ }
+
+ @Override
+ public ByteArrayOutputStream openOutputStream() {
+ return new ByteArrayOutputStream() {
+ @Override
+ public void close() throws IOException {
+ super.close();
+ offerClassFile(toUri(), toByteArray());
+ }
+ };
+ }
+
+ protected abstract void offerClassFile(URI uri, byte[] bytes);
+ }
+
+ private static URI toURI(String outputDir, String name) {
+ try {
+ return new URI("file:///" + outputDir.replace('\\','/') + "/" + name.replace('.', '/') + JavaFileObject.Kind.CLASS.extension);
+ }
+ catch (URISyntaxException exception) {
+ throw new Error(exception);
+ }
+ }
+}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerDriver.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerDriver.java
index 528bddd55388..e914943852b9 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerDriver.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerDriver.java
@@ -19,6 +19,7 @@
package com.intellij.compiler.impl.javaCompiler.eclipse;
import com.intellij.compiler.OutputParser;
+import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerMessageCategory;
@@ -55,7 +56,7 @@ import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
-public class EclipseCompilerDriver implements IEclipseCompilerDriver {
+public class EclipseCompilerDriver {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.javaCompiler.eclipse.EclipseCompilerDriver");
private String[] sourceFilePaths;
@@ -183,17 +184,11 @@ public class EclipseCompilerDriver implements IEclipseCompilerDriver {
String filePath = String.valueOf(classFile.fileName());
String relativePath = FileUtil.toSystemDependentName(filePath + ".class");
String path = FileUtil.toSystemDependentName(outputDir) + File.separatorChar + relativePath;
-
- try {
- File out = new File(path);
- FileUtil.createParentDirs(out);
- FileUtil.writeToFile(out, classFile.getBytes());
- }
- catch (IOException e) {
- LOG.error(e);
- }
- callback.fileGenerated(path);
+ byte[] bytes = classFile.getBytes();
+ File out = new File(path);
+
+ callback.fileGenerated(new FileObject(out,bytes));
}
IProblem[] problems = result.getProblems();
if (problems != null) {
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerOutputParser.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerOutputParser.java
index 30ddc51c23d0..a191207cc3eb 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerOutputParser.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseCompilerOutputParser.java
@@ -1,11 +1,13 @@
package com.intellij.compiler.impl.javaCompiler.eclipse;
import com.intellij.compiler.OutputParser;
+import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NonNls;
+import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -61,7 +63,7 @@ public class EclipseCompilerOutputParser extends OutputParser {
String path = matcher.group(1);
String absPath = FileUtil.toSystemDependentName(myOutputDir + '/' + path);
//callback.setProgressText(CompilerBundle.message("eclipse.compiler.writing", absPath));
- callback.fileGenerated(absPath);
+ callback.fileGenerated(new FileObject(new File(absPath)));
return true;
}
if (COMPILED_PATTERN.matcher(line).matches() || GENERATED_PATTERN.matcher(line).matches()) {
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseEmbeddedCompiler.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseEmbeddedCompiler.java
index 57fb4efa2ba7..68a69234f783 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseEmbeddedCompiler.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/eclipse/EclipseEmbeddedCompiler.java
@@ -30,13 +30,13 @@ public class EclipseEmbeddedCompiler implements BackendCompiler {
private final Project myProject;
private final EclipseCompiler myEclipseExternalCompiler;
private int myExitCode;
- private IEclipseCompilerDriver myEclipseCompilerDriver;
+ private final EclipseCompilerDriver myEclipseCompilerDriver;
private static final Set COMPILABLE_TYPES = Collections.singleton(StdFileTypes.JAVA);
public EclipseEmbeddedCompiler(Project project) {
myProject = project;
myEclipseExternalCompiler = new EclipseCompiler(project);
- createCompileDriver();
+ myEclipseCompilerDriver = new EclipseCompilerDriver();
}
public DependencyProcessor getDependencyProcessor() {
@@ -49,8 +49,8 @@ public class EclipseEmbeddedCompiler implements BackendCompiler {
@NotNull
@NonNls
- public String getId() // used for externalization
- {
+ public String getId() {
+ // used for externalization
return "EclipseEmbedded";
}
@@ -70,7 +70,7 @@ public class EclipseEmbeddedCompiler implements BackendCompiler {
}
@Nullable
- public OutputParser createErrorParser(final String outputDir) {
+ public OutputParser createErrorParser(@NotNull final String outputDir) {
return new OutputParser() {
public boolean processMessageLine(Callback callback) {
return myEclipseCompilerDriver.processMessageLine(callback, outputDir, myProject);
@@ -79,7 +79,7 @@ public class EclipseEmbeddedCompiler implements BackendCompiler {
}
@Nullable
- public OutputParser createOutputParser(final String outputDir) {
+ public OutputParser createOutputParser(@NotNull final String outputDir) {
return null;
}
@@ -88,9 +88,9 @@ public class EclipseEmbeddedCompiler implements BackendCompiler {
@NotNull
- public Process launchProcess(final ModuleChunk chunk, final String outputDir, final CompileContext compileContext) throws IOException {
+ public Process launchProcess(@NotNull final ModuleChunk chunk, @NotNull final String outputDir, @NotNull final CompileContext compileContext) throws IOException {
@NonNls final ArrayList commandLine = new ArrayList();
- final IOException[] ex = new IOException[]{null};
+ final IOException[] ex = {null};
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
try {
@@ -141,8 +141,4 @@ public class EclipseEmbeddedCompiler implements BackendCompiler {
}
};
}
-
- private void createCompileDriver() {
- myEclipseCompilerDriver = new EclipseCompilerDriver();
- }
}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/javac/FilePathActionJavac.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/javac/FilePathActionJavac.java
index 7e9ac583d0a6..bf5971702b46 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/javac/FilePathActionJavac.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/javac/FilePathActionJavac.java
@@ -16,12 +16,14 @@
package com.intellij.compiler.impl.javaCompiler.javac;
import com.intellij.compiler.OutputParser;
+import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.openapi.compiler.CompilerBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
+import java.io.File;
import java.util.regex.Matcher;
/**
@@ -48,8 +50,7 @@ public class FilePathActionJavac extends JavacParserAction {
callback.setProgressText(CompilerBundle.message("progress.parsing.file", name));
}
else if (StdFileTypes.CLASS.equals(fileType)) {
- callback.fileGenerated(filePath);
+ callback.fileGenerated(new FileObject(new File(filePath)));
}
}
-
}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/javac/JavacCompiler.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/javac/JavacCompiler.java
index 52b26f90f5c7..e5c305140eb8 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/javac/JavacCompiler.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/javac/JavacCompiler.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
import com.intellij.openapi.projectRoots.impl.MockJdkWrapper;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
@@ -112,61 +113,54 @@ public class JavacCompiler extends ExternalCompiler {
return new JavacConfigurable(JavacSettings.getInstance(myProject));
}
- public OutputParser createErrorParser(final String outputDir) {
+ public OutputParser createErrorParser(@NotNull final String outputDir) {
return new JavacOutputParser(myProject);
}
- public OutputParser createOutputParser(final String outputDir) {
+ public OutputParser createOutputParser(@NotNull final String outputDir) {
return null;
}
+ private static class MyException extends RuntimeException {
+ private MyException(Throwable cause) {
+ super(cause);
+ }
+ }
+
@NotNull
public String[] createStartupCommand(final ModuleChunk chunk, final CompileContext context, final String outputPath)
throws IOException, IllegalArgumentException {
- final ArrayList commandLine = new ArrayList();
-
- final Exception[] ex = new Exception[]{null};
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- public void run() {
- try {
- createStartupCommand(chunk, commandLine, outputPath);
+ try {
+ return ApplicationManager.getApplication().runReadAction(new Computable() {
+ public String[] compute() {
+ try {
+ final List commandLine = new ArrayList();
+ createStartupCommand(chunk, commandLine, outputPath, JavacSettings.getInstance(myProject));
+ return ArrayUtil.toStringArray(commandLine);
+ }
+ catch (IOException e) {
+ throw new MyException(e);
+ }
}
- catch (IllegalArgumentException e) {
- ex[0] = e;
- }
- catch (IOException e) {
- ex[0] = e;
- }
- }
- });
- if (ex[0] != null) {
- if (ex[0] instanceof IOException) {
- throw (IOException)ex[0];
- }
- else if (ex[0] instanceof IllegalArgumentException) {
- throw (IllegalArgumentException)ex[0];
- }
- else {
- LOG.error(ex[0]);
- }
+ });
+ }
+ catch (MyException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof IOException) {
+ throw (IOException)cause;
+ }
+ throw e;
}
- return ArrayUtil.toStringArray(commandLine);
}
- private void createStartupCommand(final ModuleChunk chunk, @NonNls final List commandLine, final String outputPath) throws IOException {
+ private void createStartupCommand(final ModuleChunk chunk, @NonNls final List commandLine, final String outputPath,
+ JavacSettings javacSettings) throws IOException {
final Sdk jdk = getJdkForStartupCommand(chunk);
final String versionString = jdk.getVersionString();
if (versionString == null || "".equals(versionString) || !(jdk.getSdkType() instanceof JavaSdkType)) {
throw new IllegalArgumentException(CompilerBundle.message("javac.error.unknown.jdk.version", jdk.getName()));
}
-
- final JavaSdkType sdkType = (JavaSdkType)jdk.getSdkType();
- final String toolsJarPath = sdkType.getToolsPath(jdk);
- if (toolsJarPath == null) {
- throw new IllegalArgumentException(CompilerBundle.message("javac.error.tools.jar.missing", jdk.getName()));
- }
-
final boolean isVersion1_0 = CompilerUtil.isOfVersion(versionString, "1.0");
final boolean isVersion1_1 = CompilerUtil.isOfVersion(versionString, "1.1");
final boolean isVersion1_2 = CompilerUtil.isOfVersion(versionString, "1.2");
@@ -175,11 +169,18 @@ public class JavacCompiler extends ExternalCompiler {
final boolean isVersion1_5 = CompilerUtil.isOfVersion(versionString, "1.5") || CompilerUtil.isOfVersion(versionString, "5.0");
final boolean isVersion1_5_or_higher = isVersion1_5 || !(isVersion1_0 || isVersion1_1 || isVersion1_2 || isVersion1_3 || isVersion1_4);
- final JavacSettings javacSettings = JavacSettings.getInstance(myProject);
+
+ JavaSdkType sdkType = (JavaSdkType)jdk.getSdkType();
+
+ final String toolsJarPath = sdkType.getToolsPath(jdk);
+ if (toolsJarPath == null) {
+ throw new IllegalArgumentException(CompilerBundle.message("javac.error.tools.jar.missing", jdk.getName()));
+ }
final String vmExePath = sdkType.getVMExecutablePath(jdk);
commandLine.add(vmExePath);
+
if (isVersion1_1 || isVersion1_0) {
commandLine.add("-mx" + javacSettings.MAXIMUM_HEAP_SIZE + "m");
}
@@ -187,27 +188,8 @@ public class JavacCompiler extends ExternalCompiler {
commandLine.add("-Xmx" + javacSettings.MAXIMUM_HEAP_SIZE + "m");
}
- final List additionalOptions = new ArrayList();
- StringTokenizer tokenizer = new StringTokenizer(javacSettings.getOptionsString(), " ");
- while (tokenizer.hasMoreTokens()) {
- @NonNls String token = tokenizer.nextToken();
- if (isVersion1_0) {
- if ("-deprecation".equals(token)) {
- continue; // not supported for this version
- }
- }
- if (isVersion1_0 || isVersion1_1 || isVersion1_2 || isVersion1_3 || isVersion1_4) {
- if ("-Xlint".equals(token)) {
- continue; // not supported in these versions
- }
- }
- if (token.startsWith("-J-")) {
- commandLine.add(token.substring("-J".length()));
- }
- else {
- additionalOptions.add(token);
- }
- }
+ final List additionalOptions =
+ addAdditionalSettings(commandLine, javacSettings, isVersion1_0, isVersion1_1, isVersion1_2, isVersion1_3, isVersion1_4);
CompilerUtil.addLocaleOptions(commandLine, false);
@@ -229,40 +211,9 @@ public class JavacCompiler extends ExternalCompiler {
commandLine.add(JAVAC_MAIN_CLASS);
}
- LanguageLevel languageLevel = chunk.getLanguageLevel();
- CompilerUtil.addSourceCommandLineSwitch(jdk, languageLevel, commandLine);
+ addCommandLineOptions(chunk, commandLine, outputPath, jdk, isVersion1_0, isVersion1_1, myTempFiles, true, true);
- commandLine.add("-verbose");
-
- final String cp = chunk.getCompilationClasspath();
- final String bootCp = chunk.getCompilationBootClasspath();
-
- final String classPath;
- if (isVersion1_0 || isVersion1_1) {
- classPath = bootCp + File.pathSeparator + cp;
- }
- else {
- classPath = cp;
- commandLine.add("-bootclasspath");
- addClassPathValue(jdk, false, commandLine, bootCp, "javac_bootcp");
- }
-
- commandLine.add("-classpath");
- addClassPathValue(jdk, isVersion1_0, commandLine, classPath, "javac_cp");
-
- if (!isVersion1_1 && !isVersion1_0) {
- commandLine.add("-sourcepath");
- // this way we tell the compiler that the sourcepath is "empty". However, javac thinks that sourcepath is 'new File("")'
- // this may cause problems if we have java code in IDEA working directory
- commandLine.add("\"\"");
- }
-
- commandLine.add("-d");
- commandLine.add(outputPath.replace('/', File.separatorChar));
-
- for (String option : additionalOptions) {
- commandLine.add(option);
- }
+ commandLine.addAll(additionalOptions);
final VirtualFile[] files = chunk.getFilesToCompile();
@@ -298,11 +249,80 @@ public class JavacCompiler extends ExternalCompiler {
}
}
- private void addClassPathValue(final Sdk jdk,
- final boolean isVersion1_0,
- final List commandLine,
- final String cpString,
- @NonNls final String tempFileName) throws IOException {
+ public static List addAdditionalSettings(List commandLine, JavacSettings javacSettings,
+ boolean version1_0,
+ boolean version1_1,
+ boolean version1_2,
+ boolean version1_3,
+ boolean version1_4) {
+ final List additionalOptions = new ArrayList();
+ StringTokenizer tokenizer = new StringTokenizer(javacSettings.getOptionsString(), " ");
+ while (tokenizer.hasMoreTokens()) {
+ @NonNls String token = tokenizer.nextToken();
+ if (version1_0) {
+ if ("-deprecation".equals(token)) {
+ continue; // not supported for this version
+ }
+ }
+ if (version1_0 || version1_1 || version1_2 || version1_3 || version1_4) {
+ if ("-Xlint".equals(token)) {
+ continue; // not supported in these versions
+ }
+ }
+ if (token.startsWith("-J-")) {
+ commandLine.add(token.substring("-J".length()));
+ }
+ else {
+ additionalOptions.add(token);
+ }
+ }
+ return additionalOptions;
+ }
+
+ public static void addCommandLineOptions(ModuleChunk chunk, @NonNls List commandLine, String outputPath, Sdk jdk,
+ boolean version1_0,
+ boolean version1_1,
+ List tempFiles, boolean addSourcePath, boolean useTempFile) throws IOException {
+
+ LanguageLevel languageLevel = chunk.getLanguageLevel();
+ CompilerUtil.addSourceCommandLineSwitch(jdk, languageLevel, commandLine);
+
+ commandLine.add("-verbose");
+
+ final String cp = chunk.getCompilationClasspath();
+ final String bootCp = chunk.getCompilationBootClasspath();
+
+ final String classPath;
+ if (version1_0 || version1_1) {
+ classPath = bootCp + File.pathSeparator + cp;
+ }
+ else {
+ classPath = cp;
+ commandLine.add("-bootclasspath");
+ addClassPathValue(jdk, false, commandLine, bootCp, "javac_bootcp", tempFiles, useTempFile);
+ }
+
+ commandLine.add("-classpath");
+ addClassPathValue(jdk, version1_0, commandLine, classPath, "javac_cp", tempFiles, useTempFile);
+
+ if (!version1_1 && !version1_0 && addSourcePath) {
+ commandLine.add("-sourcepath");
+ // this way we tell the compiler that the sourcepath is "empty". However, javac thinks that sourcepath is 'new File("")'
+ // this may cause problems if we have java code in IDEA working directory
+ commandLine.add("\"\"");
+ }
+
+ commandLine.add("-d");
+ commandLine.add(outputPath.replace('/', File.separatorChar));
+ }
+
+ private static void addClassPathValue(final Sdk jdk, final boolean isVersion1_0, final List commandLine, final String cpString, @NonNls final String tempFileName,
+ List tempFiles,
+ boolean useTempFile) throws IOException {
+ if (!useTempFile) {
+ commandLine.add(cpString);
+ return;
+ }
// must include output path to classpath, otherwise javac will compile all dependent files no matter were they compiled before or not
if (isVersion1_0) {
commandLine.add(((JavaSdkType)jdk.getSdkType()).getToolsPath(jdk) + File.pathSeparator + cpString);
@@ -310,7 +330,7 @@ public class JavacCompiler extends ExternalCompiler {
else {
File cpFile = FileUtil.createTempFile(tempFileName, ".tmp");
cpFile.deleteOnExit();
- myTempFiles.add(cpFile);
+ tempFiles.add(cpFile);
final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(cpFile)));
try {
CompilerIOUtil.writeString(cpString, out);
@@ -337,5 +357,6 @@ public class JavacCompiler extends ExternalCompiler {
public void compileFinished() {
FileUtil.asyncDelete(myTempFiles);
+ myTempFiles.clear();
}
}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/jikes/JikesCompiler.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/jikes/JikesCompiler.java
index 59db836113e2..d7cf1d4a6e1a 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/jikes/JikesCompiler.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/jikes/JikesCompiler.java
@@ -99,12 +99,12 @@ public class JikesCompiler extends ExternalCompiler {
return new JikesConfigurable(JikesSettings.getInstance(myProject));
}
- public OutputParser createErrorParser(final String outputDir) {
+ public OutputParser createErrorParser(@NotNull final String outputDir) {
return new JikesOutputParser(myProject);
}
@Nullable
- public OutputParser createOutputParser(final String outputDir) {
+ public OutputParser createOutputParser(@NotNull final String outputDir) {
return null;
}
diff --git a/compiler/impl/com/intellij/compiler/impl/javaCompiler/jikes/ParserActionJikes.java b/compiler/impl/com/intellij/compiler/impl/javaCompiler/jikes/ParserActionJikes.java
index 8832fa66f926..4c1a5b24246f 100644
--- a/compiler/impl/com/intellij/compiler/impl/javaCompiler/jikes/ParserActionJikes.java
+++ b/compiler/impl/com/intellij/compiler/impl/javaCompiler/jikes/ParserActionJikes.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.compiler.ParserAction;
import com.intellij.compiler.OutputParser;
+import com.intellij.compiler.impl.javaCompiler.FileObject;
import org.jetbrains.annotations.NonNls;
import java.io.File;
@@ -81,7 +82,7 @@ public class ParserActionJikes extends ParserAction {
callback.setProgressText(CompilerBundle.message("progress.parsing.file", name));
}
else if (StdFileTypes.CLASS.equals(fileType)) {
- callback.fileGenerated(filePath);
+ callback.fileGenerated(new FileObject(new File(filePath)));
}
}
}
diff --git a/compiler/impl/com/intellij/compiler/impl/resourceCompiler/ResourceCompiler.java b/compiler/impl/com/intellij/compiler/impl/resourceCompiler/ResourceCompiler.java
index 2a8851b55005..28976eeea8b9 100644
--- a/compiler/impl/com/intellij/compiler/impl/resourceCompiler/ResourceCompiler.java
+++ b/compiler/impl/com/intellij/compiler/impl/resourceCompiler/ResourceCompiler.java
@@ -57,7 +57,7 @@ public class ResourceCompiler implements TranslatingCompiler {
return !StdFileTypes.JAVA.equals(FILE_TYPE_MANAGER.getFileTypeByFile(file)) && myConfiguration.isResourceFile(file.getName());
}
- public TranslatingCompiler.ExitStatus compile(final CompileContext context, final VirtualFile[] files) {
+ public ExitStatus compile(final CompileContext context, final VirtualFile[] files) {
context.getProgressIndicator().pushState();
context.getProgressIndicator().setText(CompilerBundle.message("progress.copying.resources"));
@@ -116,6 +116,7 @@ public class ResourceCompiler implements TranslatingCompiler {
break;
}
context.getProgressIndicator().setFraction(i * 1.0 / copyCommands.size());
+ context.getProgressIndicator().setText2("Copying "+command.getToPath()+"...");
try {
final MyOutputItem outputItem = command.copy(filesToRefresh);
processed.add(outputItem);
@@ -128,7 +129,7 @@ public class ResourceCompiler implements TranslatingCompiler {
);
}
}
- if (filesToRefresh.size() > 0) {
+ if (!filesToRefresh.isEmpty()) {
CompilerUtil.refreshIOFiles(filesToRefresh);
}
@@ -145,7 +146,7 @@ public class ResourceCompiler implements TranslatingCompiler {
private final String myToPath;
private final VirtualFile mySourceFile;
- public CopyCommand(String outputPath, String fromPath, String toPath, VirtualFile sourceFile) {
+ private CopyCommand(String outputPath, String fromPath, String toPath, VirtualFile sourceFile) {
myOutputPath = outputPath;
myFromPath = fromPath;
myToPath = toPath;
@@ -181,7 +182,7 @@ public class ResourceCompiler implements TranslatingCompiler {
private final String myTargetPath;
private final VirtualFile myFile;
- public MyOutputItem(String outputPath, String targetPath, VirtualFile file) {
+ private MyOutputItem(String outputPath, String targetPath, VirtualFile file) {
myOutputPath = outputPath;
myTargetPath = targetPath;
myFile = file;
@@ -202,7 +203,7 @@ public class ResourceCompiler implements TranslatingCompiler {
private static class MyExitStatus implements ExitStatus {
private final OutputItem[] myItemsArray;
- public MyExitStatus(OutputItem[] itemsArray) {
+ private MyExitStatus(OutputItem[] itemsArray) {
myItemsArray = itemsArray;
}
diff --git a/compiler/impl/com/intellij/compiler/impl/rmiCompiler/RmicCompiler.java b/compiler/impl/com/intellij/compiler/impl/rmiCompiler/RmicCompiler.java
index ef76e8ab0b53..7a431baa3094 100644
--- a/compiler/impl/com/intellij/compiler/impl/rmiCompiler/RmicCompiler.java
+++ b/compiler/impl/com/intellij/compiler/impl/rmiCompiler/RmicCompiler.java
@@ -5,6 +5,7 @@ import com.intellij.compiler.RmicSettings;
import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.compiler.impl.javaCompiler.CompilerParsingThread;
import com.intellij.compiler.impl.javaCompiler.CompilerParsingThreadImpl;
+import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.compiler.make.Cache;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.compiler.make.DependencyCache;
@@ -230,8 +231,9 @@ public class RmicCompiler implements ClassPostProcessingCompiler{
final Process process = Runtime.getRuntime().exec(cmdLine);
final Set successfullyCompiledItems = new HashSet();
final CompilerParsingThread parsingThread = new CompilerParsingThreadImpl(process, context, outputParser, false, true) {
- protected void processCompiledClass(String classFileToProcess) {
- final RmicProcessingItem item = pathToItemMap.get(classFileToProcess.replace(File.separatorChar, '/'));
+ protected void processCompiledClass(FileObject classFileToProcess) {
+ String key = classFileToProcess.getFile().getPath().replace(File.separatorChar, '/');
+ final RmicProcessingItem item = pathToItemMap.get(key);
if (item != null) {
successfullyCompiledItems.add(item);
}
@@ -251,9 +253,9 @@ public class RmicCompiler implements ClassPostProcessingCompiler{
try {
parsingThreadFuture.get();
}
- catch (InterruptedException e) {
+ catch (InterruptedException ignored) {
}
- catch (ExecutionException e) {
+ catch (ExecutionException ignored) {
}
return successfullyCompiledItems.toArray(new RmicProcessingItem[successfullyCompiledItems.size()]);
}
@@ -407,7 +409,7 @@ public class RmicCompiler implements ClassPostProcessingCompiler{
private final long mySkelTimestamp;
private final long myTieTimestamp;
- public RemoteClassValidityState(long remoteClassTimestamp, long stubTimestamp, long skelTimestamp, long tieTimestamp) {
+ private RemoteClassValidityState(long remoteClassTimestamp, long stubTimestamp, long skelTimestamp, long tieTimestamp) {
myRemoteClassTimestamp = remoteClassTimestamp;
myStubTimestamp = stubTimestamp;
mySkelTimestamp = skelTimestamp;
@@ -443,7 +445,7 @@ public class RmicCompiler implements ClassPostProcessingCompiler{
private final File myTie;
private boolean myIsRemoteObject = false;
- public RmicProcessingItem(Module module, final VirtualFile outputClassFile, File outputDir, String qName) {
+ private RmicProcessingItem(Module module, final VirtualFile outputClassFile, File outputDir, String qName) {
myModule = module;
myOutputClassFile = outputClassFile;
myOutputDir = outputDir;
diff --git a/lib/dev/compilerapi.jar b/lib/dev/compilerapi.jar
new file mode 100644
index 000000000000..b5bf1f3d8ed7
Binary files /dev/null and b/lib/dev/compilerapi.jar differ
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
index 9ff9652bf248..24cb2c3bc267 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/OutputParser.java
@@ -2,6 +2,7 @@ package com.intellij.lang.ant.config.execution;
import com.intellij.compiler.impl.javaCompiler.javac.JavacOutputParser;
import com.intellij.compiler.impl.javaCompiler.jikes.JikesOutputParser;
+import com.intellij.compiler.impl.javaCompiler.FileObject;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.lang.ant.AntBundle;
import com.intellij.openapi.application.ApplicationManager;
@@ -263,7 +264,7 @@ public class OutputParser{
public void fileProcessed(String path) {
}
- public void fileGenerated(String path) {
+ public void fileGenerated(FileObject path) {
}
};
try {
diff --git a/resources_eng/src/messages/CompilerBundle.properties b/resources_eng/src/messages/CompilerBundle.properties
index bcb35b94022c..abef44e30153 100644
--- a/resources_eng/src/messages/CompilerBundle.properties
+++ b/resources_eng/src/messages/CompilerBundle.properties
@@ -140,7 +140,7 @@ eclipse.options.group.title=Eclipse Options
eclipse.compiler.parsing=Parsing {0}
eclipse.compiler.reading=Reading classes
eclipse.compiler.analyzing=Analyzing {0}
-compiler.eclipse.embedded.name=Eclipse embedded (faster, but requires more/leaks memory)
+compiler.eclipse.embedded.name=Eclipse in-process
generate.ant.build.title=Generate Ant Build
generate.ant.build.progress.message=Generating ant build...
diff --git a/ui-designer/impl/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java b/ui-designer/impl/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java
index 579eff891813..3650fea2db34 100644
--- a/ui-designer/impl/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java
+++ b/ui-designer/impl/com/intellij/uiDesigner/make/Form2ByteCodeCompiler.java
@@ -153,7 +153,7 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler {
}
});
- return items.toArray(new FileProcessingCompiler.ProcessingItem[items.size()]);
+ return items.toArray(new ProcessingItem[items.size()]);
}
private static boolean belongsToCompileScope(final CompileContext context, final VirtualFile formFile, final String classToBind) {
@@ -184,7 +184,7 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler {
return module2formFiles;
}
- private HashMap> sortByModules(final FileProcessingCompiler.ProcessingItem[] items) {
+ private HashMap> sortByModules(final ProcessingItem[] items) {
final HashMap> module2formFiles = new HashMap>();
for (ProcessingItem item1 : items) {
final MyInstrumentationItem item = (MyInstrumentationItem)item1;
@@ -282,7 +282,7 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler {
final ArrayList list = module2itemsList.get(module);
for (final MyInstrumentationItem item : list) {
- context.getProgressIndicator().setFraction((double)(++formsProcessed) / ((double)items.length));
+ context.getProgressIndicator().setFraction((double)++formsProcessed / (double)items.length);
final VirtualFile formFile = item.getFormFile();