Skip to content

Commit 23036f4

Browse files
committed
rewrite javac process console handling. try to fix bug with freezing javac console
1 parent 9884585 commit 23036f4

6 files changed

Lines changed: 181 additions & 272 deletions

File tree

java-compiler-impl/src/main/java/com/intellij/compiler/impl/javaCompiler/BackendCompiler.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
import java.io.IOException;
1919

2020
import javax.annotation.Nonnull;
21+
import javax.annotation.Nullable;
2122

2223
import com.intellij.compiler.OutputParser;
2324
import com.intellij.compiler.impl.ModuleChunk;
25+
import com.intellij.execution.configurations.GeneralCommandLine;
26+
import com.intellij.execution.process.ProcessHandler;
2427
import com.intellij.openapi.compiler.CompileContext;
2528
import com.intellij.openapi.compiler.CompileScope;
2629
import com.intellij.openapi.extensions.ExtensionPointName;
@@ -33,16 +36,16 @@ public interface BackendCompiler
3336
@Nonnull
3437
String getPresentableName();
3538

36-
@javax.annotation.Nullable
37-
OutputParser createErrorParser(@Nonnull String outputDir, Process process);
39+
@Nullable
40+
OutputParser createErrorParser(@Nonnull String outputDir, ProcessHandler process);
3841

39-
@javax.annotation.Nullable
42+
@Nullable
4043
OutputParser createOutputParser(@Nonnull String outputDir);
4144

4245
boolean checkCompiler(final CompileScope scope);
4346

4447
@Nonnull
45-
Process launchProcess( @Nonnull ModuleChunk chunk, @Nonnull String outputDir, @Nonnull CompileContext compileContext) throws IOException;
48+
GeneralCommandLine launchProcess(@Nonnull ModuleChunk chunk, @Nonnull String outputDir, @Nonnull CompileContext compileContext) throws IOException;
4649

4750
void compileFinished();
4851
}

java-compiler-impl/src/main/java/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java

Lines changed: 78 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
import java.util.Set;
3333
import java.util.concurrent.ArrayBlockingQueue;
3434
import java.util.concurrent.BlockingQueue;
35-
import java.util.concurrent.ExecutionException;
36-
import java.util.concurrent.Future;
35+
import java.util.concurrent.ExecutorService;
3736

3837
import javax.annotation.Nonnull;
38+
import javax.annotation.Nullable;
3939

4040
import org.jetbrains.annotations.NonNls;
4141
import com.intellij.compiler.CompilerEncodingService;
@@ -48,6 +48,11 @@
4848
import com.intellij.compiler.impl.CompilerUtil;
4949
import com.intellij.compiler.impl.ModuleChunk;
5050
import com.intellij.compiler.make.CacheCorruptedException;
51+
import com.intellij.execution.ExecutionException;
52+
import com.intellij.execution.configurations.GeneralCommandLine;
53+
import com.intellij.execution.process.OSProcessHandler;
54+
import com.intellij.execution.process.ProcessHandler;
55+
import com.intellij.execution.process.ProcessHandlerFactory;
5156
import com.intellij.openapi.application.Application;
5257
import com.intellij.openapi.application.ApplicationManager;
5358
import com.intellij.openapi.compiler.CompileContext;
@@ -69,7 +74,6 @@
6974
import com.intellij.openapi.roots.ProjectRootManager;
7075
import com.intellij.openapi.util.Comparing;
7176
import com.intellij.openapi.util.Computable;
72-
import consulo.util.dataholder.Key;
7377
import com.intellij.openapi.util.Pair;
7478
import com.intellij.openapi.util.Ref;
7579
import com.intellij.openapi.util.io.FileUtil;
@@ -84,7 +88,10 @@
8488
import com.intellij.psi.search.GlobalSearchScopes;
8589
import com.intellij.util.Chunk;
8690
import com.intellij.util.cls.ClsFormatException;
91+
import com.intellij.util.concurrency.AppExecutorUtil;
92+
import consulo.application.AccessRule;
8793
import consulo.compiler.make.impl.CompositeDependencyCache;
94+
import consulo.util.dataholder.Key;
8895

8996
/**
9097
* @author Eugene Zhuravlev
@@ -114,12 +121,12 @@ public class BackendCompilerWrapper
114121
private boolean myForceCompileTestsSeparately = false;
115122

116123
public BackendCompilerWrapper(TranslatingCompiler translatingCompiler,
117-
Chunk<Module> chunk,
118-
@Nonnull final Project project,
119-
@Nonnull List<VirtualFile> filesToCompile,
120-
@Nonnull CompileContextEx compileContext,
121-
@Nonnull BackendCompiler compiler,
122-
TranslatingCompiler.OutputSink sink)
124+
Chunk<Module> chunk,
125+
@Nonnull final Project project,
126+
@Nonnull List<VirtualFile> filesToCompile,
127+
@Nonnull CompileContextEx compileContext,
128+
@Nonnull BackendCompiler compiler,
129+
TranslatingCompiler.OutputSink sink)
123130
{
124131
myTranslatingCompiler = translatingCompiler;
125132
myChunk = chunk;
@@ -329,7 +336,7 @@ public String compute()
329336
});
330337
}
331338

332-
@javax.annotation.Nullable
339+
@Nullable
333340
private File getOutputDirsToCompileTo(ModuleChunk chunk, final List<OutputDir> dirs) throws IOException
334341
{
335342
File fileToDelete = null;
@@ -414,110 +421,80 @@ public void run() {
414421
}); */
415422
}
416423

417-
private final Object lock = new Object();
418-
419-
private class SynchedCompilerParsing extends CompilerParsingThread
424+
private class CompilerParsingHandler extends CompilerParsingThread
420425
{
421-
private final ClassParsingThread myClassParsingThread;
422-
423-
private SynchedCompilerParsing(Process process,
424-
final CompileContext context,
425-
OutputParser outputParser,
426-
ClassParsingThread classParsingThread,
427-
boolean readErrorStream,
428-
boolean trimLines)
426+
private final ClassParsingHandler myClassParsingThread;
427+
428+
private CompilerParsingHandler(ProcessHandler processHandler,
429+
CompileContext context,
430+
OutputParser outputParser,
431+
ClassParsingHandler classParsingThread,
432+
boolean readErrorStream,
433+
boolean trimLines)
429434
{
430-
super(process, outputParser, readErrorStream, trimLines, context);
435+
super(processHandler, outputParser, readErrorStream, trimLines, context);
431436
myClassParsingThread = classParsingThread;
432437
}
433438

434-
@Override
435-
public void setProgressText(String text)
436-
{
437-
synchronized(lock)
438-
{
439-
super.setProgressText(text);
440-
}
441-
}
442-
443-
@Override
444-
public void message(CompilerMessageCategory category, String message, String url, int lineNum, int columnNum)
445-
{
446-
synchronized(lock)
447-
{
448-
super.message(category, message, url, lineNum, columnNum);
449-
}
450-
}
451-
452-
@Override
453-
public void fileProcessed(String path)
454-
{
455-
synchronized(lock)
456-
{
457-
sourceFileProcessed();
458-
}
459-
}
460-
461439
@Override
462440
protected void processCompiledClass(final FileObject classFileToProcess) throws CacheCorruptedException
463441
{
464-
synchronized(lock)
465-
{
466-
myClassParsingThread.addPath(classFileToProcess);
467-
}
442+
myClassParsingThread.addPath(classFileToProcess);
468443
}
469444
}
470445

471446
private void doCompile(@Nonnull final ModuleChunk chunk, @Nonnull String outputDir, Map<File, FileObject> parsingInfo) throws IOException
472447
{
473448
myCompileContext.getProgressIndicator().checkCanceled();
474449

475-
if(ApplicationManager.getApplication().runReadAction((Computable<Boolean>) () -> chunk.getFilesToCompile().isEmpty() ? Boolean.TRUE :
476-
Boolean.FALSE))
450+
if(AccessRule.read(() -> chunk.getFilesToCompile().isEmpty()))
477451
{
478452
return; // should not invoke javac with empty sources list
479453
}
480454

481455
int exitValue = 0;
482456
try
483457
{
484-
final Process process = myCompiler.launchProcess(chunk, outputDir, myCompileContext);
485-
final long compilationStart = System.currentTimeMillis();
486-
final ClassParsingThread classParsingThread = new ClassParsingThread(parsingInfo);
487-
final Future<?> classParsingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(classParsingThread);
458+
final GeneralCommandLine commandLine = myCompiler.launchProcess(chunk, outputDir, myCompileContext);
459+
460+
OSProcessHandler process;
461+
try
462+
{
463+
process = ProcessHandlerFactory.getInstance().createProcessHandler(commandLine);
464+
}
465+
catch(ExecutionException e)
466+
{
467+
throw new IOException(e);
468+
}
469+
470+
ClassParsingHandler classParsingThread = new ClassParsingHandler(parsingInfo);
471+
ExecutorService executorService = AppExecutorUtil.getAppExecutorService();
472+
executorService.execute(classParsingThread);
488473

489474
OutputParser errorParser = myCompiler.createErrorParser(outputDir, process);
490-
CompilerParsingThread errorParsingThread = errorParser == null ? null : new SynchedCompilerParsing(process, myCompileContext,
491-
errorParser, classParsingThread, true, errorParser.isTrimLines());
492-
Future<?> errorParsingThreadFuture = null;
475+
CompilerParsingThread errorParsingThread = errorParser == null ? null : new CompilerParsingHandler(process, myCompileContext, errorParser, classParsingThread, true, errorParser.isTrimLines());
476+
493477
if(errorParsingThread != null)
494478
{
495-
errorParsingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(errorParsingThread);
479+
executorService.execute(errorParsingThread);
496480
}
497481

498482
OutputParser outputParser = myCompiler.createOutputParser(outputDir);
499-
CompilerParsingThread outputParsingThread = outputParser == null ? null : new SynchedCompilerParsing(process, myCompileContext,
500-
outputParser, classParsingThread, false, outputParser.isTrimLines());
501-
Future<?> outputParsingThreadFuture = null;
502-
if(outputParsingThread != null)
483+
CompilerParsingThread outputParsingHandler = outputParser == null ? null : new CompilerParsingHandler(process, myCompileContext, outputParser, classParsingThread, false, outputParser.isTrimLines());
484+
if(outputParsingHandler != null)
503485
{
504-
outputParsingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(outputParsingThread);
486+
executorService.submit(outputParsingHandler);
505487
}
506488

507489
try
508490
{
509-
exitValue = process.waitFor();
510-
}
511-
catch(InterruptedException e)
512-
{
513-
process.destroy();
514-
exitValue = process.exitValue();
491+
process.startNotify();
492+
493+
process.waitFor();
515494
}
516-
catch(Error e)
495+
catch(Throwable e)
517496
{
518-
process.destroy();
519-
exitValue = process.exitValue();
520-
throw e;
497+
throw new IOException(e);
521498
}
522499
finally
523500
{
@@ -529,18 +506,17 @@ private void doCompile(@Nonnull final ModuleChunk chunk, @Nonnull String outputD
529506
{
530507
errorParsingThread.setProcessTerminated(true);
531508
}
532-
if(outputParsingThread != null)
509+
510+
if(outputParsingHandler != null)
533511
{
534-
outputParsingThread.setProcessTerminated(true);
512+
outputParsingHandler.setProcessTerminated(true);
535513
}
536-
joinThread(errorParsingThreadFuture);
537-
joinThread(outputParsingThreadFuture);
538514
classParsingThread.stopParsing();
539-
joinThread(classParsingThreadFuture);
540515

541-
registerParsingException(outputParsingThread);
516+
registerParsingException(outputParsingHandler);
542517
registerParsingException(errorParsingThread);
543-
assert outputParsingThread == null || !outputParsingThread.processing;
518+
519+
assert outputParsingHandler == null || !outputParsingHandler.processing;
544520
assert errorParsingThread == null || !errorParsingThread.processing;
545521
assert classParsingThread == null || !classParsingThread.processing;
546522
}
@@ -552,25 +528,6 @@ private void doCompile(@Nonnull final ModuleChunk chunk, @Nonnull String outputD
552528
}
553529
}
554530

555-
private static void joinThread(final Future<?> threadFuture)
556-
{
557-
if(threadFuture != null)
558-
{
559-
try
560-
{
561-
threadFuture.get();
562-
}
563-
catch(InterruptedException ignored)
564-
{
565-
LOG.info("Thread interrupted", ignored);
566-
}
567-
catch(ExecutionException ignored)
568-
{
569-
LOG.info("Thread interrupted", ignored);
570-
}
571-
}
572-
}
573-
574531
private void registerParsingException(final CompilerParsingThread outputParsingThread)
575532
{
576533
Throwable error = outputParsingThread == null ? null : outputParsingThread.getError();
@@ -590,8 +547,7 @@ private void registerParsingException(final CompilerParsingThread outputParsingT
590547

591548
private void runTransformingCompilers(final ModuleChunk chunk)
592549
{
593-
final JavaSourceTransformingCompiler[] transformers = CompilerManager.getInstance(myProject).getCompilers(JavaSourceTransformingCompiler
594-
.class);
550+
final JavaSourceTransformingCompiler[] transformers = CompilerManager.getInstance(myProject).getCompilers(JavaSourceTransformingCompiler.class);
595551
if(transformers.length == 0)
596552
{
597553
return;
@@ -763,13 +719,13 @@ private void compileFinished(int exitValue, final ModuleChunk chunk, final Strin
763719
}
764720

765721
private void buildOutputItemsList(final String outputDir,
766-
final Module module,
767-
VirtualFile from,
768-
final FileTypeManager typeManager,
769-
final VirtualFile sourceRoot,
770-
final String packagePrefix,
771-
final List<File> filesToRefresh,
772-
final Map<String, Collection<TranslatingCompiler.OutputItem>> results) throws CacheCorruptedException
722+
final Module module,
723+
VirtualFile from,
724+
final FileTypeManager typeManager,
725+
final VirtualFile sourceRoot,
726+
final String packagePrefix,
727+
final List<File> filesToRefresh,
728+
final Map<String, Collection<TranslatingCompiler.OutputItem>> results) throws CacheCorruptedException
773729
{
774730
final Ref<CacheCorruptedException> exRef = new Ref<>(null);
775731
final ModuleFileIndex fileIndex = ModuleRootManager.getInstance(module).getFileIndex();
@@ -847,12 +803,12 @@ private void putName(String sourceFileName, int classQName, String relativePathT
847803
}
848804

849805
private void updateOutputItemsList(final String outputDir,
850-
final VirtualFile srcFile,
851-
VirtualFile sourceRoot,
852-
final String packagePrefix,
853-
final List<File> filesToRefresh,
854-
Map<String, Collection<TranslatingCompiler.OutputItem>> results,
855-
final GlobalSearchScope srcRootScope) throws CacheCorruptedException
806+
final VirtualFile srcFile,
807+
VirtualFile sourceRoot,
808+
final String packagePrefix,
809+
final List<File> filesToRefresh,
810+
Map<String, Collection<TranslatingCompiler.OutputItem>> results,
811+
final GlobalSearchScope srcRootScope) throws CacheCorruptedException
856812
{
857813
CompositeDependencyCache dependencyCache = myCompileContext.getDependencyCache();
858814
JavaDependencyCache child = dependencyCache.findChild(JavaDependencyCache.class);
@@ -956,7 +912,7 @@ protected static String calcPackagePath(VirtualFile srcFile, VirtualFile sourceR
956912
return prefix + VfsUtilCore.getRelativePath(srcFile, sourceRoot, '/');
957913
}
958914

959-
@javax.annotation.Nullable
915+
@Nullable
960916
private Pair<String, String> moveToRealLocation(String tempOutputDir, String pathToClass, VirtualFile sourceFile, final List<File>
961917
filesToRefresh)
962918
{
@@ -1073,14 +1029,14 @@ private void updateStatistics()
10731029
//myCompileContext.getProgressIndicator().setFraction(1.0* myProcessedFilesCount /myTotalFilesToCompile);
10741030
}
10751031

1076-
private class ClassParsingThread implements Runnable
1032+
private class ClassParsingHandler implements Runnable
10771033
{
10781034
private final BlockingQueue<FileObject> myPaths = new ArrayBlockingQueue<>(50000);
10791035
private CacheCorruptedException myError = null;
10801036
private final JavaDependencyCache myJavaDependencyCache;
10811037
private final Map<File, FileObject> myParsingInfo;
10821038

1083-
private ClassParsingThread(Map<File, FileObject> parsingInfo)
1039+
private ClassParsingHandler(Map<File, FileObject> parsingInfo)
10841040
{
10851041
myParsingInfo = parsingInfo;
10861042
myJavaDependencyCache = myCompileContext.getDependencyCache().findChild(JavaDependencyCache.class);

0 commit comments

Comments
 (0)