mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
new Compiler API based compiler (java6 only)
This commit is contained in:
@@ -24,6 +24,15 @@
|
||||
<orderEntry type="module" module-name="j2ee-openapi" />
|
||||
<orderEntry type="module" module-name="boot" />
|
||||
<orderEntry type="module" module-name="platform-api" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../lib/dev/compilerapi.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -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<BackendCompiler> myRegisteredCompilers = new ArrayList<BackendCompiler>();
|
||||
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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<IntermediateOutputCompiler, Module> pair : myGenerationCompilerModuleToOutputDirMap.keySet()) {
|
||||
final Pair<VirtualFile, VirtualFile> outputs = myGenerationCompilerModuleToOutputDirMap.get(pair);
|
||||
compileContext.assignModule(outputs.getFirst(), pair.getSecond(), false);
|
||||
compileContext.assignModule(outputs.getSecond(), pair.getSecond(), true);
|
||||
for (Map.Entry<Pair<IntermediateOutputCompiler, Module>, Pair<VirtualFile, VirtualFile>> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) {
|
||||
final Pair<VirtualFile, VirtualFile> outputs = entry.getValue();
|
||||
Module module = entry.getKey().getSecond();
|
||||
compileContext.assignModule(outputs.getFirst(), module, false);
|
||||
compileContext.assignModule(outputs.getSecond(), module, true);
|
||||
}
|
||||
|
||||
final Ref<ExitStatus> status = new Ref<ExitStatus>();
|
||||
@@ -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<Module> affected = new HashSet<Module>(Arrays.asList(originalScope.getAffectedModules()));
|
||||
for (final Pair<IntermediateOutputCompiler, Module> pair : myGenerationCompilerModuleToOutputDirMap.keySet()) {
|
||||
if (affected.contains(pair.getSecond())) {
|
||||
final Pair<VirtualFile, VirtualFile> outputs = myGenerationCompilerModuleToOutputDirMap.get(pair);
|
||||
scope = new CompositeScope(scope, new FileSetCompileScope(new VirtualFile[]{outputs.getFirst(), outputs.getSecond()}, new Module[]{pair.getSecond()}));
|
||||
for (Map.Entry<Pair<IntermediateOutputCompiler, Module>, Pair<VirtualFile, VirtualFile>> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) {
|
||||
Module module = entry.getKey().getSecond();
|
||||
if (affected.contains(module)) {
|
||||
final Pair<VirtualFile, VirtualFile> 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<IntermediateOutputCompiler, Module> pair : myGenerationCompilerModuleToOutputDirMap.keySet()) {
|
||||
final Pair<VirtualFile, VirtualFile> outputs = myGenerationCompilerModuleToOutputDirMap.get(pair);
|
||||
compileContext.assignModule(outputs.getFirst(), pair.getSecond(), false);
|
||||
compileContext.assignModule(outputs.getSecond(), pair.getSecond(), true);
|
||||
for (Map.Entry<Pair<IntermediateOutputCompiler, Module>, Pair<VirtualFile, VirtualFile>> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) {
|
||||
final Pair<VirtualFile, VirtualFile> 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<VirtualFile> outputsToRefresh = new ArrayList<VirtualFile>();
|
||||
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<IntermediateOutputCompiler, Module> pair : myGenerationCompilerModuleToOutputDirMap.keySet()) {
|
||||
final Pair<VirtualFile, VirtualFile> 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<RuntimeException>(){
|
||||
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<RuntimeException>(){
|
||||
public void run() {
|
||||
// need this to make sure the VFS is built
|
||||
boolean needRecalcOutputDirs = false;
|
||||
final List<VirtualFile> outputsToRefresh = new ArrayList<VirtualFile>();
|
||||
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<IntermediateOutputCompiler, Module>, Pair<VirtualFile, VirtualFile>> entry : myGenerationCompilerModuleToOutputDirMap.entrySet()) {
|
||||
final Pair<VirtualFile, VirtualFile> 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<RuntimeException>(){
|
||||
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<File> outputDirectories) {
|
||||
private static <T extends Throwable> void runInContext(CompileContext context, String title, ThrowableRunnable<T> 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<ValidityState> cache = getGeneratingCompilerCache((GeneratingCompiler)compiler);
|
||||
final Iterator<String> urlIterator = cache.getUrlsIterator();
|
||||
while (urlIterator.hasNext()) {
|
||||
context.getProgressIndicator().checkCanceled();
|
||||
deleteFile(new File(VirtualFileManager.extractPath(urlIterator.next())));
|
||||
}
|
||||
}
|
||||
else if (compiler instanceof TranslatingCompiler) {
|
||||
final ArrayList<Trinity<File, String, Boolean>> toDelete = new ArrayList<Trinity<File, String, Boolean>>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
TranslatingCompilerFilesMonitor.getInstance().collectFiles(
|
||||
context,
|
||||
(TranslatingCompiler)compiler, Arrays.<VirtualFile>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<VirtualFile>(),
|
||||
toDelete
|
||||
);
|
||||
}
|
||||
});
|
||||
for (Trinity<File, String, Boolean> 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<File> outputDirectories) {
|
||||
runInContext(context, CompilerBundle.message("progress.clearing.output"), new ThrowableRunnable<RuntimeException>(){
|
||||
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<ValidityState> cache = getGeneratingCompilerCache((GeneratingCompiler)compiler);
|
||||
final Iterator<String> urlIterator = cache.getUrlsIterator();
|
||||
while (urlIterator.hasNext()) {
|
||||
context.getProgressIndicator().checkCanceled();
|
||||
deleteFile(new File(VirtualFileManager.extractPath(urlIterator.next())));
|
||||
}
|
||||
}
|
||||
else if (compiler instanceof TranslatingCompiler) {
|
||||
final ArrayList<Trinity<File, String, Boolean>> toDelete = new ArrayList<Trinity<File, String, Boolean>>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
TranslatingCompilerFilesMonitor.getInstance().collectFiles(
|
||||
context,
|
||||
(TranslatingCompiler)compiler, Arrays.<VirtualFile>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<VirtualFile>(),
|
||||
toDelete
|
||||
);
|
||||
}
|
||||
});
|
||||
for (Trinity<File, String, Boolean> 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<File> outPutDirectories) {
|
||||
private static boolean doPrune(ProgressIndicator progress, final File directory, final Set<File> 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<GeneratingCompiler.GenerationItem> toGenerate = new ArrayList<GeneratingCompiler.GenerationItem>();
|
||||
final List<File> filesToRefresh = new ArrayList<File>();
|
||||
final List<File> generatedFiles = new ArrayList<File>();
|
||||
final List<Module> affectedModules = new ArrayList<Module>();
|
||||
final Set<Module> affectedModules = new THashSet<Module>();
|
||||
try {
|
||||
final StateCache<ValidityState> cache = getGeneratingCompilerCache(compiler);
|
||||
final Set<String> pathsToRemove = new HashSet<String>(cache.getUrls());
|
||||
|
||||
final Map<GeneratingCompiler.GenerationItem, String> itemToOutputPathMap = new HashMap<GeneratingCompiler.GenerationItem, String>();
|
||||
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<IOException>(){
|
||||
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<Module, Set<GeneratingCompiler.GenerationItem>> moduleToItemMap =
|
||||
final Map<Module, Set<GeneratingCompiler.GenerationItem>> moduleToItemMap =
|
||||
buildModuleToGenerationItemMap(toGenerate.toArray(new GeneratingCompiler.GenerationItem[toGenerate.size()]));
|
||||
List<Module> modules = new ArrayList<Module>(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<GeneratingCompiler.GenerationItem> 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<IOException>(){
|
||||
public void run() throws IOException {
|
||||
final Set<GeneratingCompiler.GenerationItem> 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<IOException>() {
|
||||
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<VirtualFile> vFiles = ApplicationManager.getApplication().runReadAction(new Computable<List<VirtualFile>>() {
|
||||
@@ -1244,116 +1249,118 @@ public class CompileDriver {
|
||||
final boolean trackDependencies,
|
||||
final Set<File> outputDirectories,
|
||||
final boolean onlyCheckStatus) throws ExitException {
|
||||
|
||||
|
||||
final Set<VirtualFile> toCompile = new HashSet<VirtualFile>();
|
||||
final List<Trinity<File, String, Boolean>> toDelete = new ArrayList<Trinity<File, String, Boolean>>();
|
||||
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<ExitException>(){
|
||||
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<Trinity<File, String, Boolean>> toDelete, final Set<File> 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<File> filesToRefresh = new ArrayList<File>();
|
||||
try {
|
||||
context.getProgressIndicator().setText(CompilerBundle.message("progress.synchronizing.output.directory"));
|
||||
int current = 0;
|
||||
boolean wereFilesDeleted = false;
|
||||
for (final Trinity<File, String, Boolean> 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<CacheCorruptedException>(){
|
||||
public void run() throws CacheCorruptedException {
|
||||
int current = 0;
|
||||
for (final Trinity<File, String, Boolean> 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<RuntimeException>() {
|
||||
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<FileProcessingCompiler.ProcessingItem> toProcess = new ArrayList<FileProcessingCompiler.ProcessingItem>();
|
||||
final Set<String> allUrls = new HashSet<String>();
|
||||
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<String> urls = cache.getUrls();
|
||||
final List<String> urlsToRemove = new ArrayList<String>();
|
||||
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<IOException>(){
|
||||
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<VirtualFile> vFiles = new ArrayList<VirtualFile>(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<RuntimeException>(){
|
||||
public void run() {
|
||||
List<VirtualFile> vFiles = new ArrayList<VirtualFile>(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<RuntimeException>(){
|
||||
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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -16,17 +16,16 @@ public interface BackendCompiler {
|
||||
@NotNull @NonNls String getId(); // used for externalization
|
||||
@NotNull String getPresentableName();
|
||||
@NotNull Configurable createConfigurable();
|
||||
@NotNull
|
||||
Set<FileType> getCompilableFileTypes();
|
||||
@Nullable OutputParser createErrorParser(final String outputDir);
|
||||
@Nullable OutputParser createOutputParser(final String outputDir);
|
||||
@NotNull Set<FileType> 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();
|
||||
|
||||
|
||||
@@ -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<TranslatingCompiler.OutputItem> myOutputItems;
|
||||
|
||||
private final CompileContextEx myCompileContext;
|
||||
private final VirtualFile[] myFilesToCompile;
|
||||
private final List<VirtualFile> myFilesToCompile;
|
||||
private final Project myProject;
|
||||
private final Set<VirtualFile> myFilesToRecompile;
|
||||
private final Map<Module, VirtualFile> myModuleToTempDirMap = new HashMap<Module, VirtualFile>();
|
||||
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<VirtualFile> filesToCompile,
|
||||
@NotNull CompileContextEx compileContext,
|
||||
@NotNull BackendCompiler compiler) {
|
||||
myProject = project;
|
||||
myCompiler = compiler;
|
||||
myCompileContext = compileContext;
|
||||
myFilesToCompile = filesToCompile;
|
||||
myFilesToRecompile = new HashSet<VirtualFile>(Arrays.asList(filesToCompile));
|
||||
myFilesToRecompile = new HashSet<VirtualFile>(filesToCompile);
|
||||
myProjectFileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
mySuccesfullyCompiledJavaFiles = new HashSet<VirtualFile>(filesToCompile.length);
|
||||
myOutputItems = new ArrayList<TranslatingCompiler.OutputItem>(filesToCompile.length);
|
||||
myFileNameToSourceMap = new HashMap<String, Set<CompiledClass>>(filesToCompile.length);
|
||||
myFilesToRefresh = new ArrayList<File>(filesToCompile.length);
|
||||
mySuccesfullyCompiledJavaFiles = new HashSet<VirtualFile>(filesToCompile.size());
|
||||
myOutputItems = new ArrayList<TranslatingCompiler.OutputItem>(filesToCompile.size());
|
||||
myFileNameToSourceMap = new HashMap<String, Set<CompiledClass>>(filesToCompile.size());
|
||||
myFilesToRefresh = new ArrayList<File>(filesToCompile.size());
|
||||
}
|
||||
|
||||
public TranslatingCompiler.OutputItem[] compile() throws CompilerException, CacheCorruptedException {
|
||||
public List<TranslatingCompiler.OutputItem> compile() throws CompilerException, CacheCorruptedException {
|
||||
Application application = ApplicationManager.getApplication();
|
||||
final Set<VirtualFile> allDependent = new HashSet<VirtualFile>();
|
||||
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<VirtualFile> dependentFiles;
|
||||
do {
|
||||
dependentFiles = findDependentFiles();
|
||||
|
||||
if (dependentFiles.length > 0) {
|
||||
final List<VirtualFile> 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<VirtualFile> filesInScope = getFilesInScope(dependentFiles);
|
||||
if (filesInScope.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
final Map<Module, Set<VirtualFile>> 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<VirtualFile> filesInScope = new ArrayList<VirtualFile>(dependentFiles.length);
|
||||
private List<VirtualFile> getFilesInScope(final Collection<VirtualFile> dependentFiles) {
|
||||
final List<VirtualFile> filesInScope = new ArrayList<VirtualFile>(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<Module, Set<VirtualFile>> moduleToFilesMap) throws IOException {
|
||||
@@ -328,7 +327,7 @@ public class BackendCompilerWrapper {
|
||||
private final TIntHashSet myProcessedNames = new TIntHashSet();
|
||||
private final Set<VirtualFile> myProcessedFiles = new HashSet<VirtualFile>();
|
||||
|
||||
private VirtualFile[] findDependentFiles() throws CacheCorruptedException {
|
||||
private Collection<VirtualFile> 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<Module, Set<VirtualFile>> buildModuleToFilesMap(final CompileContext context, final VirtualFile[] files) {
|
||||
private static Map<Module, Set<VirtualFile>> buildModuleToFilesMap(final CompileContext context, final List<VirtualFile> files) {
|
||||
final Map<Module, Set<VirtualFile>> map = new HashMap<Module, Set<VirtualFile>>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
@@ -890,9 +889,8 @@ public class BackendCompilerWrapper {
|
||||
}
|
||||
|
||||
private class ClassParsingThread implements Runnable {
|
||||
private final BlockingQueue<String> myPaths = new ArrayBlockingQueue<String>(50000);
|
||||
private final BlockingQueue<FileObject> myPaths = new ArrayBlockingQueue<FileObject>(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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<OutputItem> 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<OutputItem> myOutputItems;
|
||||
private final VirtualFile[] myMyFilesToRecompile;
|
||||
|
||||
public ExitStatusImpl(OutputItem[] ouitputItems, VirtualFile[] myFilesToRecompile) {
|
||||
myOuitputItems = ouitputItems;
|
||||
private ExitStatusImpl(List<OutputItem> outputItems, VirtualFile[] myFilesToRecompile) {
|
||||
myOutputItems = outputItems;
|
||||
myMyFilesToRecompile = myFilesToRecompile;
|
||||
}
|
||||
|
||||
public OutputItem[] getSuccessfullyCompiled() {
|
||||
return myOuitputItems;
|
||||
return myOutputItems.toArray(new OutputItem[myOutputItems.size()]);
|
||||
}
|
||||
|
||||
public VirtualFile[] getFilesToRecompile() {
|
||||
|
||||
@@ -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<CompilationEvent> myCompilationResults = new LinkedBlockingQueue<CompilationEvent>();
|
||||
private static final CompilationEvent GUARD = new CompilationEvent() {
|
||||
@Override
|
||||
protected void process(OutputParser.Callback callback) {
|
||||
}
|
||||
};
|
||||
|
||||
public void compile(List<String> commandLine, List<File> 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<JavaFileObject> listener = new DiagnosticListener<JavaFileObject>() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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<FileType> COMPILABLE_TYPES = Collections.<FileType>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<Sdk> checkedJdks = new HashSet<Sdk>();
|
||||
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<FileType> 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<String> commandLine = ApplicationManager.getApplication().runReadAction(new Computable<List<String>>() {
|
||||
public List<String> compute() {
|
||||
try {
|
||||
List<String> commandLine = new ArrayList<String>();
|
||||
JavacSettings javacSettings = JavacSettings.getInstance(myProject);
|
||||
final List<String> 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<String> commandLine, ModuleChunk chunk, String outputDir) {
|
||||
VirtualFile[] filesToCompile = chunk.getFilesToCompile();
|
||||
List<File> paths = new ArrayList<File>(filesToCompile.length);
|
||||
for (VirtualFile file : filesToCompile) {
|
||||
paths.add(new File(file.getPresentableUrl()));
|
||||
}
|
||||
myCompAPIDriver.compile(commandLine, paths, outputDir);
|
||||
}
|
||||
}
|
||||
@@ -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<URI, JavaFileObject> uri2Output = new THashMap<URI, JavaFileObject>();
|
||||
private final Map<URI, JavaFileObject> uri2Source = new THashMap<URI, JavaFileObject>();
|
||||
|
||||
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<JavaFileObject> result = new ArrayList<JavaFileObject>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-11
@@ -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) {
|
||||
|
||||
+3
-1
@@ -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()) {
|
||||
|
||||
+8
-12
@@ -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<FileType> COMPILABLE_TYPES = Collections.<FileType>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<String> commandLine = new ArrayList<String>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<String> commandLine = new ArrayList<String>();
|
||||
|
||||
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<String[]>() {
|
||||
public String[] compute() {
|
||||
try {
|
||||
final List<String> commandLine = new ArrayList<String>();
|
||||
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<String> commandLine, final String outputPath) throws IOException {
|
||||
private void createStartupCommand(final ModuleChunk chunk, @NonNls final List<String> 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<String> additionalOptions = new ArrayList<String>();
|
||||
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<String> 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<String> commandLine,
|
||||
final String cpString,
|
||||
@NonNls final String tempFileName) throws IOException {
|
||||
public static List<String> addAdditionalSettings(List<String> commandLine, JavacSettings javacSettings,
|
||||
boolean version1_0,
|
||||
boolean version1_1,
|
||||
boolean version1_2,
|
||||
boolean version1_3,
|
||||
boolean version1_4) {
|
||||
final List<String> additionalOptions = new ArrayList<String>();
|
||||
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<String> commandLine, String outputPath, Sdk jdk,
|
||||
boolean version1_0,
|
||||
boolean version1_1,
|
||||
List<File> 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<String> commandLine, final String cpString, @NonNls final String tempFileName,
|
||||
List<File> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<RmicProcessingItem> successfullyCompiledItems = new HashSet<RmicProcessingItem>();
|
||||
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;
|
||||
|
||||
Binary file not shown.
@@ -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 {
|
||||
|
||||
@@ -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...
|
||||
|
||||
|
||||
@@ -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<Module, ArrayList<MyInstrumentationItem>> sortByModules(final FileProcessingCompiler.ProcessingItem[] items) {
|
||||
private HashMap<Module, ArrayList<MyInstrumentationItem>> sortByModules(final ProcessingItem[] items) {
|
||||
final HashMap<Module, ArrayList<MyInstrumentationItem>> module2formFiles = new HashMap<Module,ArrayList<MyInstrumentationItem>>();
|
||||
for (ProcessingItem item1 : items) {
|
||||
final MyInstrumentationItem item = (MyInstrumentationItem)item1;
|
||||
@@ -282,7 +282,7 @@ public final class Form2ByteCodeCompiler implements ClassInstrumentingCompiler {
|
||||
final ArrayList<MyInstrumentationItem> 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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user