private void reportErrorsToWolf() { if (!myFile.getViewProvider().isPhysical()) return; // e.g. errors in evaluate expression Project project = myFile.getProject(); if (!PsiManager.getInstance(project).isInProject(myFile)) return; // do not report problems in libraries VirtualFile file = myFile.getVirtualFile(); if (file == null) return; List<Problem> problems = convertToProblems(getInfos(), file, myHasErrorElement); WolfTheProblemSolver wolf = WolfTheProblemSolver.getInstance(project); boolean hasErrors = DaemonCodeAnalyzerImpl.hasErrors(project, getDocument()); if (!hasErrors || isWholeFileHighlighting()) { wolf.reportProblems(file, problems); } else { wolf.weHaveGotProblems(file, problems); } }
@Override protected void collectInformationWithProgress(final ProgressIndicator progress) { final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>(100); final Set<HighlightInfo> outsideResult = new THashSet<HighlightInfo>(100); DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(myProject); HighlightVisitor[] highlightVisitors = getHighlightVisitors(); final HighlightVisitor[] filteredVisitors = filterVisitors(highlightVisitors, myFile); final List<PsiElement> inside = new ArrayList<PsiElement>(); final List<PsiElement> outside = new ArrayList<PsiElement>(); try { Divider.divideInsideAndOutside( myFile, myStartOffset, myEndOffset, myPriorityRange, inside, outside, HighlightLevelUtil.AnalysisLevel.HIGHLIGHT, false); setProgressLimit((long) (inside.size() + outside.size())); final boolean forceHighlightParents = forceHighlightParents(); if (!isDumbMode()) { highlightTodos( myFile, myDocument.getCharsSequence(), myStartOffset, myEndOffset, progress, myPriorityRange, gotHighlights, outsideResult); } collectHighlights( inside, new Runnable() { @Override public void run() { // all infos for the "injected fragment for the host which is inside" are indeed // inside // but some of the infos for the "injected fragment for the host which is outside" can // be still inside Set<HighlightInfo> injectedResult = new THashSet<HighlightInfo>(); final Set<PsiFile> injected = new THashSet<PsiFile>(); getInjectedPsiFiles(inside, outside, progress, injected); if (!addInjectedPsiHighlights( injected, progress, Collections.synchronizedSet(injectedResult))) throw new ProcessCanceledException(); final List<HighlightInfo> injectionsOutside = new ArrayList<HighlightInfo>(gotHighlights.size()); Set<HighlightInfo> result; synchronized (injectedResult) { // sync here because all writes happened in another thread result = injectedResult; } for (HighlightInfo info : result) { if (myPriorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) { gotHighlights.add(info); } else { // nonconditionally apply injected results regardless whether they are in // myStartOffset,myEndOffset injectionsOutside.add(info); } } if (outsideResult.isEmpty() && injectionsOutside.isEmpty()) { return; // apply only result (by default apply command) and only within inside } final ProperTextRange priorityIntersection = myPriorityRange.intersection(new TextRange(myStartOffset, myEndOffset)); if ((!inside.isEmpty() || !gotHighlights.isEmpty()) && priorityIntersection != null) { // do not apply when there were no elements to highlight // clear infos found in visible area to avoid applying them twice final List<HighlightInfo> toApplyInside = new ArrayList<HighlightInfo>(gotHighlights); myHighlights.addAll(toApplyInside); gotHighlights.clear(); gotHighlights.addAll(outsideResult); final long modificationStamp = myDocument.getModificationStamp(); UIUtil.invokeLaterIfNeeded( new Runnable() { @Override public void run() { if (myProject.isDisposed() || modificationStamp != myDocument.getModificationStamp()) return; MarkupModel markupModel = DocumentMarkupModel.forDocument(myDocument, myProject, true); UpdateHighlightersUtil.setHighlightersInRange( myProject, myDocument, priorityIntersection, getColorsScheme(), toApplyInside, (MarkupModelEx) markupModel, Pass.UPDATE_ALL); if (myEditor != null) { new ShowAutoImportPass(myProject, myFile, myEditor) .applyInformationToEditor(); } } }); } myApplyCommand = new Runnable() { @Override public void run() { ProperTextRange range = new ProperTextRange(myStartOffset, myEndOffset); List<HighlightInfo> toApply = new ArrayList<HighlightInfo>(); for (HighlightInfo info : gotHighlights) { if (!range.containsRange(info.getStartOffset(), info.getEndOffset())) continue; if (!myPriorityRange.containsRange( info.getStartOffset(), info.getEndOffset())) { toApply.add(info); } } toApply.addAll(injectionsOutside); UpdateHighlightersUtil.setHighlightersOutsideRange( myProject, myDocument, toApply, getColorsScheme(), myStartOffset, myEndOffset, myPriorityRange, Pass.UPDATE_ALL); } }; } }, outside, progress, filteredVisitors, gotHighlights, forceHighlightParents); if (myUpdateAll) { ((DaemonCodeAnalyzerImpl) daemonCodeAnalyzer) .getFileStatusMap() .setErrorFoundFlag(myDocument, myErrorFound); } } finally { incVisitorUsageCount(-1); } myHighlights.addAll(gotHighlights); }
@NotNull protected DaemonCodeAnalyzerStatus getDaemonCodeAnalyzerStatus( @NotNull SeverityRegistrar severityRegistrar) { DaemonCodeAnalyzerStatus status = new DaemonCodeAnalyzerStatus(); if (myFile == null) { status.reasonWhyDisabled = "No file"; status.errorAnalyzingFinished = true; return status; } if (myProject != null && myProject.isDisposed()) { status.reasonWhyDisabled = "Project is disposed"; status.errorAnalyzingFinished = true; return status; } if (!myDaemonCodeAnalyzer.isHighlightingAvailable(myFile)) { if (!myFile.isPhysical()) { status.reasonWhyDisabled = "File is generated"; status.errorAnalyzingFinished = true; return status; } else if (myFile instanceof PsiCompiledElement) { status.reasonWhyDisabled = "File is decompiled"; status.errorAnalyzingFinished = true; return status; } final FileType fileType = myFile.getFileType(); if (fileType.isBinary()) { status.reasonWhyDisabled = "File is binary"; status.errorAnalyzingFinished = true; return status; } status.reasonWhyDisabled = "Highlighting is disabled for this file"; status.errorAnalyzingFinished = true; return status; } FileViewProvider provider = myFile.getViewProvider(); Set<Language> languages = provider.getLanguages(); HighlightingSettingsPerFile levelSettings = HighlightingSettingsPerFile.getInstance(myProject); boolean shouldHighlight = languages.isEmpty(); for (Language language : languages) { PsiFile root = provider.getPsi(language); FileHighlightingSetting level = levelSettings.getHighlightingSettingForRoot(root); shouldHighlight |= level != FileHighlightingSetting.SKIP_HIGHLIGHTING; } if (!shouldHighlight) { status.reasonWhyDisabled = "Highlighting level is None"; status.errorAnalyzingFinished = true; return status; } if (HeavyProcessLatch.INSTANCE.isRunning()) { status.reasonWhySuspended = StringUtil.defaultIfEmpty( HeavyProcessLatch.INSTANCE.getRunningOperationName(), "Heavy operation is running"); status.errorAnalyzingFinished = true; return status; } status.errorCount = errorCount.clone(); fillDaemonCodeAnalyzerErrorsStatus(status, severityRegistrar); List<TextEditorHighlightingPass> passes = myDaemonCodeAnalyzer.getPassesToShowProgressFor(myDocument); status.passStati = passes.isEmpty() ? Collections.<ProgressableTextEditorHighlightingPass>emptyList() : new ArrayList<>(passes.size()); //noinspection ForLoopReplaceableByForEach for (int i = 0; i < passes.size(); i++) { TextEditorHighlightingPass tepass = passes.get(i); if (!(tepass instanceof ProgressableTextEditorHighlightingPass)) continue; ProgressableTextEditorHighlightingPass pass = (ProgressableTextEditorHighlightingPass) tepass; if (pass.getProgress() < 0) continue; status.passStati.add(pass); } status.errorAnalyzingFinished = myDaemonCodeAnalyzer.isAllAnalysisFinished(myFile); status.reasonWhySuspended = myDaemonCodeAnalyzer.isUpdateByTimerEnabled() ? null : "Highlighting is paused temporarily"; return status; }