use of com.intellij.concurrency.JobLauncherImpl in project intellij-community by JetBrains.
the class GlobalInspectionContextImpl method runTools.
@Override
protected void runTools(@NotNull final AnalysisScope scope, boolean runGlobalToolsOnly, boolean isOfflineInspections) {
final ProgressIndicator progressIndicator = ProgressIndicatorProvider.getGlobalProgressIndicator();
if (progressIndicator == null) {
throw new IncorrectOperationException("Must be run under progress");
}
if (!isOfflineInspections && ApplicationManager.getApplication().isDispatchThread()) {
throw new IncorrectOperationException("Must not start inspections from within EDT");
}
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
throw new IncorrectOperationException("Must not start inspections from within write action");
}
// in offline inspection application we don't care about global read action
if (!isOfflineInspections && ApplicationManager.getApplication().isReadAccessAllowed()) {
throw new IncorrectOperationException("Must not start inspections from within global read action");
}
final InspectionManager inspectionManager = InspectionManager.getInstance(getProject());
((RefManagerImpl) getRefManager()).initializeAnnotators();
final List<Tools> globalTools = new ArrayList<>();
final List<Tools> localTools = new ArrayList<>();
final List<Tools> globalSimpleTools = new ArrayList<>();
initializeTools(globalTools, localTools, globalSimpleTools);
appendPairedInspectionsForUnfairTools(globalTools, globalSimpleTools, localTools);
runGlobalTools(scope, inspectionManager, globalTools, isOfflineInspections);
if (runGlobalToolsOnly || localTools.isEmpty() && globalSimpleTools.isEmpty())
return;
SearchScope searchScope = ReadAction.compute(scope::toSearchScope);
final Set<VirtualFile> localScopeFiles = searchScope instanceof LocalSearchScope ? new THashSet<>() : null;
for (Tools tools : globalSimpleTools) {
GlobalInspectionToolWrapper toolWrapper = (GlobalInspectionToolWrapper) tools.getTool();
GlobalSimpleInspectionTool tool = (GlobalSimpleInspectionTool) toolWrapper.getTool();
tool.inspectionStarted(inspectionManager, this, getPresentation(toolWrapper));
}
final boolean headlessEnvironment = ApplicationManager.getApplication().isHeadlessEnvironment();
final Map<String, InspectionToolWrapper> map = getInspectionWrappersMap(localTools);
final BlockingQueue<PsiFile> filesToInspect = new ArrayBlockingQueue<>(1000);
// use original progress indicator here since we don't want it to cancel on write action start
ProgressIndicator iteratingIndicator = new SensitiveProgressWrapper(progressIndicator);
Future<?> future = startIterateScopeInBackground(scope, localScopeFiles, headlessEnvironment, filesToInspect, iteratingIndicator);
Processor<PsiFile> processor = file -> {
ProgressManager.checkCanceled();
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(() -> {
if (!file.isValid()) {
return;
}
LOG.assertTrue(scope.contains(file.getVirtualFile()), file.getName());
inspectFile(file, inspectionManager, localTools, globalSimpleTools, map);
})) {
throw new ProcessCanceledException();
}
boolean includeDoNotShow = includeDoNotShow(getCurrentProfile());
Stream.concat(getWrappersFromTools(localTools, file, includeDoNotShow).stream(), getWrappersFromTools(globalSimpleTools, file, includeDoNotShow).stream()).filter(wrapper -> wrapper.getTool() instanceof ExternalAnnotatorBatchInspection).forEach(wrapper -> {
ProblemDescriptor[] descriptors = ((ExternalAnnotatorBatchInspection) wrapper.getTool()).checkFile(file, this, inspectionManager);
InspectionToolPresentation toolPresentation = getPresentation(wrapper);
ReadAction.run(() -> LocalDescriptorsUtil.addProblemDescriptors(Arrays.asList(descriptors), false, this, null, CONVERT, toolPresentation));
});
return true;
};
try {
final Queue<PsiFile> filesFailedToInspect = new LinkedBlockingQueue<>();
while (true) {
Disposable disposable = Disposer.newDisposable();
ProgressIndicator wrapper = new SensitiveProgressWrapper(progressIndicator);
wrapper.start();
ProgressIndicatorUtils.forceWriteActionPriority(wrapper, disposable);
try {
// use wrapper here to cancel early when write action start but do not affect the original indicator
((JobLauncherImpl) JobLauncher.getInstance()).processQueue(filesToInspect, filesFailedToInspect, wrapper, TOMBSTONE, processor);
break;
} catch (ProcessCanceledException ignored) {
progressIndicator.checkCanceled();
// go on with the write and then resume processing the rest of the queue
assert !ApplicationManager.getApplication().isReadAccessAllowed();
assert !ApplicationManager.getApplication().isDispatchThread();
// wait for write action to complete
ApplicationManager.getApplication().runReadAction(EmptyRunnable.getInstance());
} finally {
Disposer.dispose(disposable);
}
}
} finally {
// tell file scanning thread to stop
iteratingIndicator.cancel();
// let file scanning thread a chance to put TOMBSTONE and complete
filesToInspect.clear();
try {
future.get(30, TimeUnit.SECONDS);
} catch (Exception e) {
LOG.error("Thread dump: \n" + ThreadDumper.dumpThreadsToString(), e);
}
}
progressIndicator.checkCanceled();
for (Tools tools : globalSimpleTools) {
GlobalInspectionToolWrapper toolWrapper = (GlobalInspectionToolWrapper) tools.getTool();
GlobalSimpleInspectionTool tool = (GlobalSimpleInspectionTool) toolWrapper.getTool();
ProblemDescriptionsProcessor problemDescriptionProcessor = getProblemDescriptionProcessor(toolWrapper, map);
tool.inspectionFinished(inspectionManager, this, problemDescriptionProcessor);
}
addProblemsToView(globalSimpleTools);
}
Aggregations