Let general HighlightingPasses (i.e. not TextEditorHighlightingPass-derived) run in parallel to other passes since they are not dependent on anything. Make document notnull as by-product

GitOrigin-RevId: 7f478ae9a7cf1396276888991a5c3d29d8a9c755
This commit is contained in:
Alexey Kudravtsev
2020-04-27 10:21:25 +00:00
committed by intellij-monorepo-bot
parent b79801ae84
commit e7f246b594
25 changed files with 132 additions and 226 deletions
@@ -36,7 +36,7 @@ private class JavaSoftKeywordHighlightingPass(private val file: PsiJavaFile, doc
}
override fun doApplyInformationToEditor() {
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument!!, 0, file.textLength, results, colorsScheme, id)
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, file.textLength, results, colorsScheme, id)
}
}
@@ -25,7 +25,6 @@ abstract class ElementProcessingHintPass(
private val hints = TIntObjectHashMap<SmartList<String>>()
override fun doCollectInformation(progress: ProgressIndicator) {
assert(myDocument != null)
hints.clear()
val virtualFile = rootElement.containingFile?.originalFile?.virtualFile ?: return
@@ -1589,7 +1589,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
if (errorDescription.equals(description)) {
errorRemoved[0] = true;
List<TextEditorHighlightingPass> passes = myDaemonCodeAnalyzer.getPassesToShowProgressFor(document);
List<ProgressableTextEditorHighlightingPass> passes = myDaemonCodeAnalyzer.getPassesToShowProgressFor(document);
GeneralHighlightingPass ghp = null;
for (TextEditorHighlightingPass pass : passes) {
if (pass instanceof GeneralHighlightingPass && pass.getId() == Pass.UPDATE_ALL) {
@@ -22,8 +22,10 @@ import java.util.List;
public abstract class TextEditorHighlightingPass implements HighlightingPass {
public static final TextEditorHighlightingPass[] EMPTY_ARRAY = new TextEditorHighlightingPass[0];
@Nullable protected final Document myDocument;
@NotNull protected final Project myProject;
@NotNull
protected final Document myDocument;
@NotNull
protected final Project myProject;
private final boolean myRunIntentionPassAfter;
private final long myInitialDocStamp;
private final long myInitialPsiStamp;
@@ -33,14 +35,14 @@ public abstract class TextEditorHighlightingPass implements HighlightingPass {
private volatile boolean myDumb;
private EditorColorsScheme myColorsScheme;
protected TextEditorHighlightingPass(@NotNull final Project project, @Nullable final Document document, boolean runIntentionPassAfter) {
protected TextEditorHighlightingPass(@NotNull final Project project, @NotNull final Document document, boolean runIntentionPassAfter) {
myDocument = document;
myProject = project;
myRunIntentionPassAfter = runIntentionPassAfter;
myInitialDocStamp = document == null ? 0 : document.getModificationStamp();
myInitialDocStamp = document.getModificationStamp();
myInitialPsiStamp = PsiModificationTracker.SERVICE.getInstance(myProject).getModificationCount();
}
protected TextEditorHighlightingPass(@NotNull final Project project, @Nullable final Document document) {
protected TextEditorHighlightingPass(@NotNull final Project project, @NotNull Document document) {
this(project, document, true);
}
@@ -74,13 +76,9 @@ public abstract class TextEditorHighlightingPass implements HighlightingPass {
return false;
}
if (myDocument != null) {
if (myDocument.getModificationStamp() != myInitialDocStamp) return false;
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument);
return file != null && file.isValid();
}
return true;
if (myDocument.getModificationStamp() != myInitialDocStamp) return false;
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument);
return file != null && file.isValid();
}
@Override
@@ -88,7 +86,7 @@ public abstract class TextEditorHighlightingPass implements HighlightingPass {
if (!isValid()) return; // Document has changed.
if (DumbService.getInstance(myProject).isDumb() && !DumbService.isDumbAware(this)) {
Document document = getDocument();
PsiFile file = document == null ? null : PsiDocumentManager.getInstance(myProject).getPsiFile(document);
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
if (file != null) {
DaemonCodeAnalyzerEx.getInstanceEx(myProject).getFileStatusMap().markFileUpToDate(getDocument(), getId());
}
@@ -121,7 +119,7 @@ public abstract class TextEditorHighlightingPass implements HighlightingPass {
myCompletionPredecessorIds = completionPredecessorIds;
}
@Nullable
@NotNull
public Document getDocument() {
return myDocument;
}
@@ -100,13 +100,6 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
return myFile;
}
@Override
public @NotNull Document getDocument() {
// this pass always get not-null document
//noinspection ConstantConditions
return super.getDocument();
}
private static final Key<AtomicInteger> HIGHLIGHT_VISITOR_INSTANCE_COUNT = new Key<>("HIGHLIGHT_VISITOR_INSTANCE_COUNT");
private HighlightVisitor @NotNull [] cloneHighlightVisitors() {
int oldCount = incVisitorUsageCount(1);
@@ -48,7 +48,7 @@ public abstract class ProgressableTextEditorHighlightingPass extends TextEditorH
HighlightingSession myHighlightingSession;
protected ProgressableTextEditorHighlightingPass(@NotNull Project project,
@Nullable final Document document,
@NotNull final Document document,
@NotNull String presentableName,
@Nullable PsiFile file,
@Nullable Editor editor,
@@ -77,8 +77,8 @@ public abstract class ProgressableTextEditorHighlightingPass extends TextEditorH
GlobalInspectionContextBase.assertUnderDaemonProgress();
myFinished = false;
if (myFile != null) {
myHighlightingSession =
HighlightingSessionImpl.getOrCreateHighlightingSession(myFile, (DaemonProgressIndicator)ProgressWrapper.unwrapAll(progress), getColorsScheme());
DaemonProgressIndicator daemonProgressIndicator = (DaemonProgressIndicator)ProgressWrapper.unwrapAll(progress);
myHighlightingSession = HighlightingSessionImpl.getOrCreateHighlightingSession(myFile, daemonProgressIndicator, getColorsScheme());
}
try {
collectInformationWithProgress(progress);
@@ -161,7 +161,7 @@ public abstract class ProgressableTextEditorHighlightingPass extends TextEditorH
}
static class EmptyPass extends TextEditorHighlightingPass {
EmptyPass(final Project project, @Nullable final Document document) {
EmptyPass(@NotNull Project project, @NotNull Document document) {
super(project, document, false);
}
@@ -47,7 +47,10 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.RefreshQueueImpl;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.*;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiCompiledElement;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.*;
@@ -546,15 +549,13 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
}
@NotNull
public List<TextEditorHighlightingPass> getPassesToShowProgressFor(Document document) {
List<TextEditorHighlightingPass> allPasses = myPassExecutorService.getAllSubmittedPasses();
List<TextEditorHighlightingPass> result = new ArrayList<>(allPasses.size());
for (TextEditorHighlightingPass pass : allPasses) {
if (pass.getDocument() == document || pass.getDocument() == null) {
result.add(pass);
}
}
return result;
public List<ProgressableTextEditorHighlightingPass> getPassesToShowProgressFor(@NotNull Document document) {
List<HighlightingPass> allPasses = myPassExecutorService.getAllSubmittedPasses();
return allPasses.stream()
.map(p->p instanceof ProgressableTextEditorHighlightingPass ? (ProgressableTextEditorHighlightingPass)p : null)
.filter(p-> p != null && p.getDocument() == document)
.sorted(Comparator.comparingInt(p->p.getId()))
.collect(Collectors.toList());
}
boolean isAllAnalysisFinished(@NotNull PsiFile file) {
@@ -328,9 +328,7 @@ public class IdentifierHighlighterPass extends TextEditorHighlightingPass {
* In brace matching case this is done from {@link BraceHighlightingHandler#highlightBraces(com.intellij.openapi.util.TextRange, com.intellij.openapi.util.TextRange, boolean, boolean, com.intellij.openapi.fileTypes.FileType)}
*/
private void doAdditionalCodeBlockHighlighting() {
if (myCodeBlockMarkerRanges.size() < 2 ||
myDocument == null ||
!(myEditor instanceof EditorEx)) {
if (myCodeBlockMarkerRanges.size() < 2 || !(myEditor instanceof EditorEx)) {
return;
}
ArrayList<TextRange> markers = new ArrayList<>(myCodeBlockMarkerRanges);
@@ -183,7 +183,6 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
@Override
public void doCollectInformation(@NotNull ProgressIndicator progress) {
assert myDocument != null;
final Long stamp = myEditor.getUserData(LAST_TIME_INDENTS_BUILT);
if (stamp != null && stamp.longValue() == nowStamp()) return;
@@ -203,7 +202,6 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
private long nowStamp() {
if (!myEditor.getSettings().isIndentGuidesShown()) return -1;
assert myDocument != null;
// include tab size into stamp to make sure indent guides are recalculated on tab size change
return myDocument.getModificationStamp() ^ (((long)getTabSize()) << 24);
}
@@ -257,7 +255,6 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
}
final int startRangeIndex = curRange;
assert myDocument != null;
DocumentUtil.executeInBulk(myDocument, myRanges.size() > 10000, () -> {
for (int i = startRangeIndex; i < myRanges.size(); i++) {
newHighlighters.add(createHighlighter(mm, myRanges.get(i)));
@@ -282,7 +279,6 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
lines.push(0);
indents.push(0);
assert myDocument != null;
List<IndentGuideDescriptor> descriptors = new ArrayList<>();
for (int line = 1; line < lineIndents.length; line++) {
ProgressManager.checkCanceled();
@@ -371,7 +367,6 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
@NotNull final CharSequence myChars;
IndentsCalculator() {
assert myDocument != null;
lineIndents = new int[myDocument.getLineCount()];
myChars = myDocument.getCharsSequence();
}
@@ -380,7 +375,6 @@ public class IndentsPass extends TextEditorHighlightingPass implements DumbAware
* Calculates line indents for the {@link #myDocument target document}.
*/
void calculate() {
assert myDocument != null;
final FileType fileType = myFile.getFileType();
int tabSize = getTabSize();
@@ -63,13 +63,6 @@ public class LineMarkersPass extends TextEditorHighlightingPass {
myRestrictRange = restrictRange;
}
@NotNull
@Override
public Document getDocument() {
//noinspection ConstantConditions
return super.getDocument();
}
@Override
public void doApplyInformationToEditor() {
try {
@@ -72,7 +72,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
private final boolean myInspectInjectedPsi;
public LocalInspectionsPass(@NotNull PsiFile file,
@Nullable Document document,
@NotNull Document document,
int startOffset,
int endOffset,
@NotNull TextRange priorityRange,
@@ -47,7 +47,7 @@ public final class LocalInspectionsPassFactory implements MainHighlightingPassFa
private static class MyLocalInspectionsPass extends LocalInspectionsPass {
private MyLocalInspectionsPass(@NotNull PsiFile file,
Document document,
@NotNull Document document,
@NotNull TextRange textRange,
@NotNull TextRange visibleRange,
@NotNull HighlightInfoProcessor highlightInfoProcessor) {
@@ -2,10 +2,12 @@
package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.*;
import com.intellij.codeHighlighting.EditorBoundHighlightingPass;
import com.intellij.codeHighlighting.HighlightingPass;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
import com.intellij.concurrency.Job;
import com.intellij.concurrency.JobLauncher;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
@@ -38,7 +40,6 @@ import gnu.trove.THashMap;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
@@ -95,34 +96,22 @@ final class PassExecutorService implements Disposable {
void submitPasses(@NotNull Map<FileEditor, HighlightingPass[]> passesMap, @NotNull DaemonProgressIndicator updateProgress) {
if (isDisposed()) return;
ApplicationManager.getApplication().assertIsDispatchThread();
// null keys are ok
MultiMap<Document, FileEditor> documentToEditors = MultiMap.createSet();
MultiMap<FileEditor, TextEditorHighlightingPass> documentBoundPasses = MultiMap.createSmart();
MultiMap<FileEditor, EditorBoundHighlightingPass> editorBoundPasses = MultiMap.createSmart();
List<Pair<FileEditor, TextEditorHighlightingPass>> passesWithNoDocuments = new ArrayList<>();
Map<FileEditor, TIntObjectHashMap<TextEditorHighlightingPass>> id2Pass = new THashMap<>();
Set<VirtualFile> vFiles = new HashSet<>();
List<ScheduledPass> freePasses = new ArrayList<>(documentToEditors.size() * 5);
AtomicInteger threadsToStartCountdown = new AtomicInteger(0);
for (Map.Entry<FileEditor, HighlightingPass[]> entry : passesMap.entrySet()) {
FileEditor fileEditor = entry.getKey();
HighlightingPass[] passes = entry.getValue();
Document document;
if (fileEditor instanceof TextEditor) {
Editor editor = ((TextEditor)fileEditor).getEditor();
LOG.assertTrue(!(editor instanceof EditorWindow));
document = editor.getDocument();
}
else {
VirtualFile virtualFile = ((FileEditorManagerEx)FileEditorManager.getInstance(myProject)).getFile(fileEditor);
document = virtualFile == null ? null : FileDocumentManager.getInstance().getDocument(virtualFile);
}
if (document != null) {
vFiles.add(FileDocumentManager.getInstance().getFile(document));
}
int prevId = 0;
for (final HighlightingPass pass : passes) {
for (HighlightingPass pass : passes) {
TIntObjectHashMap<TextEditorHighlightingPass> thisEditorId2Pass = id2Pass.computeIfAbsent(fileEditor, __ -> new TIntObjectHashMap<>(20));
if (pass instanceof EditorBoundHighlightingPass) {
EditorBoundHighlightingPass editorPass = (EditorBoundHighlightingPass)pass;
@@ -132,35 +121,26 @@ final class PassExecutorService implements Disposable {
editorBoundPasses.putValue(fileEditor, editorPass);
}
else {
TextEditorHighlightingPass convertedPass;
TextEditorHighlightingPass tePass;
if (pass instanceof TextEditorHighlightingPass) {
convertedPass = (TextEditorHighlightingPass)pass;
tePass = (TextEditorHighlightingPass)pass;
checkUniquePassId(tePass.getId(), tePass, thisEditorId2Pass);
documentBoundPasses.putValue(fileEditor, tePass);
documentToEditors.putValue(tePass.getDocument(), fileEditor);
}
else {
// run all passes in sequence
convertedPass = convertToTextHighlightingPass(pass, document, prevId);
convertedPass.setId(nextAvailablePassId.incrementAndGet());
// generic HighlightingPass, run all of them concurrently
freePasses.add(new ScheduledPass(fileEditor, pass, updateProgress, threadsToStartCountdown));
}
checkUniquePassId(convertedPass.getId(), convertedPass, thisEditorId2Pass);
document = convertedPass.getDocument();
documentBoundPasses.putValue(fileEditor, convertedPass);
if (document == null) {
passesWithNoDocuments.add(Pair.create(fileEditor, convertedPass));
}
else {
documentToEditors.putValue(document, fileEditor);
}
prevId = convertedPass.getId();
}
}
}
List<ScheduledPass> freePasses = new ArrayList<>(documentToEditors.size() * 5);
List<ScheduledPass> dependentPasses = new ArrayList<>(documentToEditors.size() * 10);
// fileEditor-> (passId -> created pass)
Map<FileEditor, TIntObjectHashMap<ScheduledPass>> toBeSubmitted = new THashMap<>(passesMap.size());
final AtomicInteger threadsToStartCountdown = new AtomicInteger(0);
for (Map.Entry<Document, Collection<FileEditor>> entry : documentToEditors.entrySet()) {
Collection<FileEditor> fileEditors = entry.getValue();
Document document = entry.getKey();
@@ -183,17 +163,15 @@ final class PassExecutorService implements Disposable {
}
}
for (Pair<FileEditor, TextEditorHighlightingPass> pair : passesWithNoDocuments) {
FileEditor fileEditor = pair.first;
TextEditorHighlightingPass pass = pair.second;
createScheduledPass(fileEditor, pass, toBeSubmitted, id2Pass, freePasses, dependentPasses, updateProgress, threadsToStartCountdown);
}
if (CHECK_CONSISTENCY && !ApplicationInfoImpl.isInStressTest()) {
assertConsistency(freePasses, toBeSubmitted, threadsToStartCountdown);
}
log(updateProgress, null, vFiles + " ----- starting " + threadsToStartCountdown.get(), freePasses);
if (LOG.isDebugEnabled()) {
Set<VirtualFile> vFiles = ContainerUtil.map2Set(passesMap.keySet(), fe -> ((FileEditorManagerEx)FileEditorManager.getInstance(myProject)).getFile(fe));
log(updateProgress, null, vFiles + " ----- starting " + threadsToStartCountdown.get(), freePasses);
}
for (ScheduledPass dependentPass : dependentPasses) {
mySubmittedPasses.put(dependentPass, Job.nullJob());
@@ -218,8 +196,11 @@ final class PassExecutorService implements Disposable {
assert threadsToStartCountdown.get() == toBeSubmitted.values().stream().mapToInt(m->m.size()).sum();
TIntObjectHashMap<Pair<ScheduledPass, Integer>> id2Visits = new TIntObjectHashMap<>();
for (ScheduledPass freePass : freePasses) {
id2Visits.put(freePass.myPass.getId(), Pair.create(freePass, 0));
checkConsistency(freePass, id2Visits);
HighlightingPass pass = freePass.myPass;
if (pass instanceof TextEditorHighlightingPass) {
id2Visits.put(((TextEditorHighlightingPass)pass).getId(), Pair.create(freePass, 0));
checkConsistency(freePass, id2Visits);
}
}
id2Visits.forEachEntry((id, pair) -> {
int count = pair.second;
@@ -231,7 +212,7 @@ final class PassExecutorService implements Disposable {
private void checkConsistency(@NotNull ScheduledPass pass, @NotNull TIntObjectHashMap<Pair<ScheduledPass, Integer>> id2Visits) {
for (ScheduledPass succ : ContainerUtil.concat(pass.mySuccessorsOnCompletion, pass.mySuccessorsOnSubmit)) {
int succId = succ.myPass.getId();
int succId = ((TextEditorHighlightingPass)succ.myPass).getId();
Pair<ScheduledPass, Integer> succPair = id2Visits.get(succId);
if (succPair == null) {
succPair = Pair.create(succ, succ.myRunningPredecessorsCount.get());
@@ -247,48 +228,17 @@ final class PassExecutorService implements Disposable {
}
@NotNull
private TextEditorHighlightingPass convertToTextHighlightingPass(@NotNull HighlightingPass pass,
@Nullable Document document,
int previousPassId) {
TextEditorHighlightingPass textEditorHighlightingPass;
textEditorHighlightingPass = new TextEditorHighlightingPass(myProject, document, true) {
@Override
public void doCollectInformation(@NotNull ProgressIndicator progress) {
pass.collectInformation(progress);
}
@Override
public void doApplyInformationToEditor() {
pass.applyInformationToEditor();
if (document != null) {
VirtualFile file = FileDocumentManager.getInstance().getFile(document);
FileEditor[] editors = file == null ? FileEditor.EMPTY_ARRAY : FileEditorManager.getInstance(myProject).getEditors(file);
for (FileEditor editor : editors) {
repaintErrorStripeAndIcon(editor);
}
}
}
};
if (previousPassId != 0) {
textEditorHighlightingPass.setCompletionPredecessorIds(new int[]{previousPassId});
}
return textEditorHighlightingPass;
}
@NotNull
private FileEditor getPreferredFileEditor(Document document, @NotNull Collection<? extends FileEditor> fileEditors) {
private FileEditor getPreferredFileEditor(@NotNull Document document, @NotNull Collection<? extends FileEditor> fileEditors) {
assert !fileEditors.isEmpty();
if (document != null) {
FileEditor focusedEditor = ContainerUtil.find(fileEditors, it -> it instanceof TextEditor &&
((TextEditor)it).getEditor().getContentComponent().isFocusOwner());
if (focusedEditor != null) return focusedEditor;
FileEditor focusedEditor = ContainerUtil.find(fileEditors, it -> it instanceof TextEditor &&
((TextEditor)it).getEditor().getContentComponent().isFocusOwner());
if (focusedEditor != null) return focusedEditor;
final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
if (file != null) {
final FileEditor selected = FileEditorManager.getInstance(myProject).getSelectedEditor(file);
if (selected != null && fileEditors.contains(selected)) {
return selected;
}
final VirtualFile file = FileDocumentManager.getInstance().getFile(document);
if (file != null) {
final FileEditor selected = FileEditorManager.getInstance(myProject).getSelectedEditor(file);
if (selected != null && fileEditors.contains(selected)) {
return selected;
}
}
return fileEditors.iterator().next();
@@ -340,7 +290,7 @@ final class PassExecutorService implements Disposable {
int id = nextAvailablePassId.incrementAndGet();
ip.setId(id);
checkUniquePassId(id, ip, thisEditorId2Pass);
ip.setCompletionPredecessorIds(new int[]{scheduledPass.myPass.getId()});
ip.setCompletionPredecessorIds(new int[]{passId});
createScheduledPass(fileEditor, ip, toBeSubmitted, id2Pass, freePasses, dependentPasses, updateProgress, threadsToStartCountdown);
}
@@ -388,7 +338,7 @@ final class PassExecutorService implements Disposable {
private class ScheduledPass implements Runnable {
private final FileEditor myFileEditor;
private final TextEditorHighlightingPass myPass;
private final HighlightingPass myPass;
private final AtomicInteger myThreadsToStartCountdown;
private final AtomicInteger myRunningPredecessorsCount = new AtomicInteger(0);
private final List<ScheduledPass> mySuccessorsOnCompletion = new ArrayList<>();
@@ -396,7 +346,7 @@ final class PassExecutorService implements Disposable {
@NotNull private final DaemonProgressIndicator myUpdateProgress;
private ScheduledPass(@NotNull FileEditor fileEditor,
@NotNull TextEditorHighlightingPass pass,
@NotNull HighlightingPass pass,
@NotNull DaemonProgressIndicator progressIndicator,
@NotNull AtomicInteger threadsToStartCountdown) {
myFileEditor = fileEditor;
@@ -495,7 +445,7 @@ final class PassExecutorService implements Disposable {
}
private void applyInformationToEditorsLater(@NotNull final FileEditor fileEditor,
@NotNull final TextEditorHighlightingPass pass,
@NotNull final HighlightingPass pass,
@NotNull final DaemonProgressIndicator updateProgress,
@NotNull final AtomicInteger threadsToStartCountdown,
@NotNull Runnable callbackOnApplied) {
@@ -507,15 +457,16 @@ final class PassExecutorService implements Disposable {
log(updateProgress, pass, " is canceled during apply, sorry");
return;
}
Document document = pass.getDocument();
try {
if (fileEditor instanceof TextEditor && EditorActivityManager.getInstance().isVisible(((TextEditor)fileEditor).getEditor())
|| fileEditor.getComponent().isDisplayable()) {
pass.applyInformationToEditor();
repaintErrorStripeAndIcon(fileEditor);
FileStatusMap fileStatusMap = DaemonCodeAnalyzerEx.getInstanceEx(myProject).getFileStatusMap();
if (document != null) {
fileStatusMap.markFileUpToDate(document, pass.getId());
if (pass instanceof TextEditorHighlightingPass) {
FileStatusMap fileStatusMap = DaemonCodeAnalyzerEx.getInstanceEx(myProject).getFileStatusMap();
Document document = ((TextEditorHighlightingPass)pass).getDocument();
int passId = ((TextEditorHighlightingPass)pass).getId();
fileStatusMap.markFileUpToDate(document, passId);
}
log(updateProgress, pass, " Applied");
}
@@ -525,7 +476,7 @@ final class PassExecutorService implements Disposable {
throw e;
}
catch (RuntimeException e) {
VirtualFile file = document == null ? null : FileDocumentManager.getInstance().getFile(document);
VirtualFile file = FileEditorManagerEx.getInstanceEx(myProject).getFile(fileEditor);
FileType fileType = file == null ? null : file.getFileType();
String message = "Exception while applying information to " + fileEditor + "("+fileType+")";
log(updateProgress, pass, message + e);
@@ -559,14 +510,13 @@ final class PassExecutorService implements Disposable {
}
@NotNull
List<TextEditorHighlightingPass> getAllSubmittedPasses() {
List<TextEditorHighlightingPass> result = new ArrayList<>(mySubmittedPasses.size());
List<HighlightingPass> getAllSubmittedPasses() {
List<HighlightingPass> result = new ArrayList<>(mySubmittedPasses.size());
for (ScheduledPass scheduledPass : mySubmittedPasses.keySet()) {
if (!scheduledPass.myUpdateProgress.isCanceled()) {
result.add(scheduledPass.myPass);
}
}
sortById(result);
return result;
}
@@ -580,9 +530,10 @@ final class PassExecutorService implements Disposable {
return StringUtil.parseInt(num, 0);
}
static void log(ProgressIndicator progressIndicator, TextEditorHighlightingPass pass, @NonNls Object @NotNull ... info) {
static void log(ProgressIndicator progressIndicator, HighlightingPass pass, @NonNls Object @NotNull ... info) {
if (LOG.isDebugEnabled()) {
CharSequence docText = pass == null || pass.getDocument() == null ? "" : ": '" + StringUtil.first(pass.getDocument().getCharsSequence(), 10, true)+ "'";
Document document = pass instanceof TextEditorHighlightingPass ? ((TextEditorHighlightingPass)pass).getDocument() : null;
CharSequence docText = document == null ? "" : ": '" + StringUtil.first(document.getCharsSequence(), 10, true)+ "'";
synchronized (PassExecutorService.class) {
String infos = StringUtil.join(info, Functions.TO_STRING(), " ");
String message = StringUtil.repeatSymbol(' ', getThreadNum() * 4)
@@ -65,6 +65,7 @@ import java.util.stream.Collectors;
public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
@NotNull
private final Project myProject;
@NotNull
private final Document myDocument;
private final DaemonCodeAnalyzerImpl myDaemonCodeAnalyzer;
private final SeverityRegistrar mySeverityRegistrar;
@@ -94,7 +95,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
DeprecatedMethodException.report("Please use TrafficLightRenderer(Project, Document) instead");
}
public TrafficLightRenderer(@NotNull Project project, @Nullable Document document) {
public TrafficLightRenderer(@NotNull Project project, @NotNull Document document) {
myProject = project;
myDaemonCodeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(project);
myDocument = document;
@@ -102,25 +103,23 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
refresh(null);
if (document != null) {
final MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
model.addMarkupModelListener(this, new MarkupModelListener() {
@Override
public void afterAdded(@NotNull RangeHighlighterEx highlighter) {
incErrorCount(highlighter, 1);
}
final MarkupModelEx model = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
model.addMarkupModelListener(this, new MarkupModelListener() {
@Override
public void afterAdded(@NotNull RangeHighlighterEx highlighter) {
incErrorCount(highlighter, 1);
}
@Override
public void beforeRemoved(@NotNull RangeHighlighterEx highlighter) {
incErrorCount(highlighter, -1);
}
});
UIUtil.invokeLaterIfNeeded(() -> {
for (RangeHighlighter rangeHighlighter : model.getAllHighlighters()) {
incErrorCount(rangeHighlighter, 1);
}
});
}
@Override
public void beforeRemoved(@NotNull RangeHighlighterEx highlighter) {
incErrorCount(highlighter, -1);
}
});
UIUtil.invokeLaterIfNeeded(() -> {
for (RangeHighlighter rangeHighlighter : model.getAllHighlighters()) {
incErrorCount(rangeHighlighter, 1);
}
});
}
private PsiFile getPsiFile() {
@@ -154,7 +153,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
}
public boolean isValid() {
return myDocument == null || getPsiFile() != null;
return getPsiFile() != null;
}
protected static final class DaemonCodeAnalyzerStatus {
@@ -250,12 +249,8 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
status.errorCount = errorCount.clone();
status.passes = ContainerUtil.mapNotNull(myDaemonCodeAnalyzer.getPassesToShowProgressFor(myDocument), pass-> {
if (!(pass instanceof ProgressableTextEditorHighlightingPass)) return null;
ProgressableTextEditorHighlightingPass p = (ProgressableTextEditorHighlightingPass)pass;
if (StringUtil.isEmpty(p.getPresentableName()) || p.getProgress() < 0) return null;
return p;
});
status.passes = ContainerUtil.filter(myDaemonCodeAnalyzer.getPassesToShowProgressFor(myDocument),
p -> !StringUtil.isEmpty(p.getPresentableName()) && p.getProgress() >= 0);
status.errorAnalyzingFinished = myDaemonCodeAnalyzer.isAllAnalysisFinished(psiFile);
status.reasonWhySuspended = myDaemonCodeAnalyzer.isUpdateByTimerEnabled() ? null : "Highlighting is paused temporarily";
@@ -429,7 +424,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
}
}
if (statusItems.size() > 0) {
if (!statusItems.isEmpty()) {
if (mainIcon == null) {
mainIcon = AllIcons.General.InspectionsOK;
}
@@ -484,7 +479,7 @@ public class TrafficLightRenderer implements ErrorStripeRenderer, Disposable {
private final List<LanguageHighlightLevel> myLevelsList;
private final List<HectorComponentPanel> myAdditionalPanels;
protected AbstractUIController() {
AbstractUIController() {
PsiFile psiFile = getPsiFile();
if (psiFile != null) {
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(getProject()).getFileIndex();
@@ -64,7 +64,7 @@ class TrafficProgressPanel extends JPanel {
fakeStatusLargeEnough.passes = new ArrayList<>();
for (int i = 0; i < 3; i++) {
fakeStatusLargeEnough.passes
.add(new ProgressableTextEditorHighlightingPass(project, null, DaemonBundle.message("pass.wolf"), psiFile, editor, TextRange.EMPTY_RANGE, false,
.add(new ProgressableTextEditorHighlightingPass(project, editor.getDocument(), DaemonBundle.message("pass.wolf"), psiFile, editor, TextRange.EMPTY_RANGE, false,
HighlightInfoProcessor.getEmpty()) {
@Override
protected void collectInformationWithProgress(@NotNull ProgressIndicator progress) {
@@ -25,7 +25,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
public class DocRenderPassFactory implements TextEditorHighlightingPassFactoryRegistrar, TextEditorHighlightingPassFactory, DumbAware {
private static final Logger LOG = Logger.getInstance(DocRenderPassFactory.class);
@@ -62,7 +61,7 @@ public class DocRenderPassFactory implements TextEditorHighlightingPassFactoryRe
@Override
public void doCollectInformation(@NotNull ProgressIndicator progress) {
items = calculateItemsToRender(Objects.requireNonNull(myDocument), myFile);
items = calculateItemsToRender(myDocument, myFile);
}
@Override
@@ -56,7 +56,6 @@ public class ParameterHintsPass extends EditorBoundHighlightingPass {
@Override
public void doCollectInformation(@NotNull ProgressIndicator progress) {
assert myDocument != null;
myHints.clear();
Language language = myFile.getLanguage();
@@ -135,8 +134,6 @@ public class ParameterHintsPass extends EditorBoundHighlightingPass {
@NotNull
private List<Inlay> hintsInRootElementArea(ParameterHintsPresentationManager manager) {
assert myDocument != null;
TextRange range = myRootElement.getTextRange();
int elementStart = range.getStartOffset();
int elementEnd = range.getEndOffset();
@@ -163,7 +160,7 @@ public class ParameterHintsPass extends EditorBoundHighlightingPass {
if (!rootRange.containsOffset(offset)) return false;
if (offset > rootRange.getStartOffset() && offset < rootRange.getEndOffset()) return true;
return myDocument != null && myDocument.getTextLength() == rootRange.getLength();
return myDocument.getTextLength() == rootRange.getLength();
}
static class HintData {
@@ -804,7 +804,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextEx {
if (!lTools.isEmpty()) {
try {
final LocalInspectionsPass pass = new LocalInspectionsPass(file, PsiDocumentManager.getInstance(getProject()).getDocument(file), range != null ? range.getStartOffset() : 0,
final LocalInspectionsPass pass = new LocalInspectionsPass(file, file.getViewProvider().getDocument(), range != null ? range.getStartOffset() : 0,
range != null ? range.getEndOffset() : file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true,
HighlightInfoProcessor.getEmpty(), true);
Runnable runnable = () -> pass.doInspectInBatch(GlobalInspectionContextImpl.this, InspectionManager.getInstance(getProject()), lTools);
@@ -26,7 +26,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.util.ui.PlatformColors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -43,7 +42,7 @@ public class TestDataHighlightingPass extends TextEditorHighlightingPass {
private static final TextAttributes CARET_ATTRIBUTES = new TextAttributes(PlatformColors.BLUE, null, null, null, Font.BOLD);
private static final String CARET = "<caret>";
protected TestDataHighlightingPass(@NotNull final Project project, @Nullable final Document document) {
protected TestDataHighlightingPass(@NotNull final Project project, @NotNull final Document document) {
super(project, document);
}
@@ -55,30 +54,22 @@ public class TestDataHighlightingPass extends TextEditorHighlightingPass {
public void doApplyInformationToEditor() {
removeHighlighters();
if (myDocument == null) {
return;
}
final MarkupModel model = DocumentMarkupModel.forDocument(myDocument, myProject, true);
final String text = myDocument.getText();
if (text != null) {
int ind = -1;
while ((ind = text.indexOf(CARET, ind + 1)) >= 0) {
final RangeHighlighter highlighter = model.addRangeHighlighter(ind,
ind + CARET.length(),
HighlighterLayer.ADDITIONAL_SYNTAX,
CARET_ATTRIBUTES,
HighlighterTargetArea.EXACT_RANGE);
highlighter.setGutterIconRenderer(ICON_RENDERER);
highlighter.putUserData(KEY, VALUE);
}
int ind = -1;
while ((ind = text.indexOf(CARET, ind + 1)) >= 0) {
final RangeHighlighter highlighter = model.addRangeHighlighter(ind,
ind + CARET.length(),
HighlighterLayer.ADDITIONAL_SYNTAX,
CARET_ATTRIBUTES,
HighlighterTargetArea.EXACT_RANGE);
highlighter.setGutterIconRenderer(ICON_RENDERER);
highlighter.putUserData(KEY, VALUE);
}
}
private void removeHighlighters() {
if (myDocument == null) {
return;
}
final MarkupModel model = DocumentMarkupModel.forDocument(myDocument, myProject, true);
for (RangeHighlighter highlighter : model.getAllHighlighters()) {
if (highlighter.getUserData(KEY) == VALUE) {
@@ -6,13 +6,13 @@ import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory;
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactoryRegistrar;
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
import com.intellij.ide.scratch.ScratchUtil;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -39,8 +39,9 @@ final class TestDataHighlightingPassFactory implements TextEditorHighlightingPas
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null) {
Project project = file.getProject();
if (isSupported(virtualFile, project)) {
return new TestDataHighlightingPass(project, PsiDocumentManager.getInstance(project).getDocument(file));
Document document = file.getViewProvider().getDocument();
if (isSupported(virtualFile, project) && document != null) {
return new TestDataHighlightingPass(project, document);
}
}
return null;
@@ -7,7 +7,6 @@ import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.progress.ProgressIndicator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import java.util.ArrayList;
@@ -22,7 +21,7 @@ public class GrReferenceHighlighter extends TextEditorHighlightingPass {
private final GroovyFileBase myFile;
private List<HighlightInfo> myInfos = null;
public GrReferenceHighlighter(@Nullable Document document, @NotNull GroovyFileBase file) {
public GrReferenceHighlighter(@NotNull GroovyFileBase file, @NotNull Document document) {
super(file.getProject(), document);
myFile = file;
}
@@ -37,7 +36,7 @@ public class GrReferenceHighlighter extends TextEditorHighlightingPass {
@Override
public void doApplyInformationToEditor() {
if (myInfos == null || myDocument == null) return;
if (myInfos == null) return;
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), myInfos, getColorsScheme(), getId());
}
}
@@ -24,7 +24,7 @@ final class GrReferenceHighlighterFactory implements TextEditorHighlightingPassF
@Override
public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull Editor editor) {
PsiFile groovyFile = file.getViewProvider().getPsi(GroovyLanguage.INSTANCE);
return groovyFile instanceof GroovyFileBase ? new GrReferenceHighlighter(editor.getDocument(), (GroovyFileBase)groovyFile) : null;
return groovyFile instanceof GroovyFileBase ? new GrReferenceHighlighter((GroovyFileBase)groovyFile, editor.getDocument()) : null;
}
static boolean shouldHighlight(@NotNull PsiFile file) {
@@ -26,7 +26,7 @@ internal abstract class GroovyHighlightingPass(val myFile: PsiFile, document: Do
private val myInfos = mutableListOf<HighlightInfo>()
override fun doApplyInformationToEditor() {
if (myDocument == null || myInfos.isEmpty()) return
if (myInfos.isEmpty()) return
UpdateHighlightersUtil.setHighlightersToEditor(
myProject, myDocument, 0, myFile.textLength, myInfos, colorsScheme, id
)
@@ -22,7 +22,6 @@ import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.Alarm;
import com.intellij.util.containers.ContainerUtil;
@@ -141,7 +140,7 @@ public class DomElementsErrorPanel extends JPanel implements CommittablePanel, H
private class DomElementsTrafficLightRenderer extends TrafficLightRenderer {
DomElementsTrafficLightRenderer(@NotNull XmlFile xmlFile) {
super(xmlFile.getProject(),
PsiDocumentManager.getInstance(xmlFile.getProject()).getDocument(xmlFile));
xmlFile.getViewProvider().getDocument());
}
@NotNull
@@ -161,10 +161,8 @@ public class XmlTagTreeHighlightingPass extends TextEditorHighlightingPass {
@Override
public void doApplyInformationToEditor() {
if (myDocument != null) {
List<HighlightInfo> infos = getHighlights();
UpdateHighlightersUtil.setHighlightersToSingleEditor(myProject, myEditor, 0, myFile.getTextLength(), infos, getColorsScheme(), getId());
}
List<HighlightInfo> infos = getHighlights();
UpdateHighlightersUtil.setHighlightersToSingleEditor(myProject, myEditor, 0, myFile.getTextLength(), infos, getColorsScheme(), getId());
}
public List<HighlightInfo> getHighlights() {