void (@NotNull ProgressIndicator progress) { FileViewProvider viewProvider = myFile.getViewProvider(); HighlightingLevelManager highlightingManager = HighlightingLevelManager.getInstance(myProject); Map<PsiFile, List<ExternalAnnotator<?,?>>> allAnnotators = new HashMap<>(); int externalAnnotatorsInRoots = 0; InspectionProfileImpl currentProfile = InspectionProjectProfileManager.getInstance(myProject).getCurrentProfile(); Function<? super InspectionProfile, ? extends InspectionProfileWrapper> custom = InspectionProfileWrapper.getCustomInspectionProfileWrapper(myFile); InspectionProfile profile; if (custom != null) { profile = custom.apply(currentProfile).getInspectionProfile(); } else { profile = currentProfile; } for (PsiFile psiRoot : viewProvider.getAllFiles()) { if (highlightingManager.shouldInspect(psiRoot) && !highlightingManager.runEssentialHighlightingOnly(psiRoot)) { List<ExternalAnnotator<?,?>> annotators = ExternalLanguageAnnotators.allForFile(psiRoot.getLanguage(), psiRoot); annotators = ContainerUtil.filter(annotators, annotator -> { String shortName = annotator.getPairedBatchInspectionShortName(); if (shortName != null) { HighlightDisplayKey key = HighlightDisplayKey.find(shortName); if (key == null) { if (!ApplicationManager.getApplication().isUnitTestMode()) { // tests should care about registering corresponding paired tools processError(new Exception("Paired tool '" + shortName + "' not found"), annotator, psiRoot); } return false; } return profile.isToolEnabled(key, myFile); } return true; }); if (!annotators.isEmpty()) { externalAnnotatorsInRoots += annotators.size(); allAnnotators.put(psiRoot, annotators); } } } setProgressLimit(externalAnnotatorsInRoots); boolean errorFound = DaemonCodeAnalyzerEx.getInstanceEx(myProject).getFileStatusMap().wasErrorFound(myDocument); Editor editor = getEditor(); DumbService dumbService = DumbService.getInstance(myProject); for (Map.Entry<PsiFile, List<ExternalAnnotator<?,?>>> entry : allAnnotators.entrySet()) { PsiFile psiRoot = entry.getKey(); List<ExternalAnnotator<?,?>> annotators = entry.getValue(); for (ExternalAnnotator<?,?> annotator : annotators) { progress.checkCanceled(); if (dumbService.isDumb() && !DumbService.isDumbAware(annotator)) { continue; } Object collectedInfo = null; try { collectedInfo = editor == null ? annotator.collectInformation(psiRoot) : annotator.collectInformation(psiRoot, editor, errorFound); } catch (Throwable t) { processError(t, annotator, psiRoot); } if (collectedInfo != null) { //noinspection unchecked,rawtypes myAnnotationData.add(new MyData(annotator, psiRoot, collectedInfo)); } advanceProgress(1); } } long modificationStampBefore = myDocument.getModificationStamp(); AnnotationSessionImpl.computeWithSession(myFile, false, annotationHolder -> { Update update = new Update(myFile) { @Override public void setRejected() { super.setRejected(); if (!myProject.isDisposed()) { // Project close in EDT might call MergeUpdateQueue.dispose which calls setRejected in EDT doFinish(convertToHighlights(annotationHolder)); } } @Override public void run() { if (documentChanged(modificationStampBefore) || myProject.isDisposed()) { return; } // have to instantiate new indicator because the old one (progress) might have already been canceled DaemonProgressIndicator indicator = new DaemonProgressIndicator(); BackgroundTaskUtil.runUnderDisposeAwareIndicator(myProject, () -> { // run annotators outside the read action because they could start OSProcessHandler runChangeAware(myDocument, () -> doAnnotate()); ReadAction.run(() -> { ProgressManager.checkCanceled(); if (!documentChanged(modificationStampBefore)) { doApply(annotationHolder); doFinish(convertToHighlights(annotationHolder)); } }); }, indicator); } }; ExternalAnnotatorManager.getInstance().queue(update); return null; }); }