mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
File level highlights should be managed in EDT only (add EDT assertions for that), event when added via BackgroundUpdateHighlightUtil. Tighten calling requirements for the latter to require HighlightingSession.
GitOrigin-RevId: c0e17d0523bc58db2e570aa242d0dbedeabe4294
This commit is contained in:
committed by
intellij-monorepo-bot
parent
5adb20dcc6
commit
bb1200ef00
@@ -185,8 +185,10 @@ public abstract class FileEditorManager {
|
||||
* To change the order of components, the specified component may implement the
|
||||
* {@link com.intellij.openapi.util.Weighted Weighted} interface.
|
||||
*/
|
||||
@RequiresEdt
|
||||
public abstract void addTopComponent(final @NotNull FileEditor editor, final @NotNull JComponent component);
|
||||
|
||||
@RequiresEdt
|
||||
public abstract void removeTopComponent(final @NotNull FileEditor editor, final @NotNull JComponent component);
|
||||
|
||||
/**
|
||||
@@ -200,8 +202,10 @@ public abstract class FileEditorManager {
|
||||
* To change the order of components, the specified component may implement the
|
||||
* {@link com.intellij.openapi.util.Weighted Weighted} interface.
|
||||
*/
|
||||
@RequiresEdt
|
||||
public abstract void addBottomComponent(final @NotNull FileEditor editor, final @NotNull JComponent component);
|
||||
|
||||
@RequiresEdt
|
||||
public abstract void removeBottomComponent(final @NotNull FileEditor editor, final @NotNull JComponent component);
|
||||
|
||||
public static final Key<Boolean> SEPARATOR_DISABLED = Key.create("FileEditorSeparatorDisabled");
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.intellij.codeInsight.daemon.GutterMark;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
@@ -18,11 +17,8 @@ import com.intellij.openapi.editor.markup.*;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.TextRangeScalarUtil;
|
||||
import com.intellij.psi.PsiCompiledFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -81,56 +77,21 @@ public final class BackgroundUpdateHighlightersUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void setHighlightersToSingleEditor(@NotNull Project project,
|
||||
@NotNull Editor editor,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull Collection<? extends HighlightInfo> highlights,
|
||||
@Nullable EditorColorsScheme colorsScheme, // if null, the global scheme will be used
|
||||
int group) {
|
||||
Document document = editor.getDocument();
|
||||
MarkupModelEx markup = (MarkupModelEx)editor.getMarkupModel();
|
||||
setHighlightersToEditor(project, document, startOffset, endOffset, highlights, colorsScheme, group, markup);
|
||||
}
|
||||
|
||||
public static void setHighlightersToEditor(@NotNull Project project,
|
||||
@NotNull PsiFile psiFile,
|
||||
@NotNull Document document,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull Collection<? extends HighlightInfo> highlights,
|
||||
@Nullable EditorColorsScheme colorsScheme, // if null, the global scheme will be used
|
||||
int group) {
|
||||
HighlightingSession session = HighlightingSessionImpl.getFromCurrentIndicator(psiFile);
|
||||
MarkupModelEx markup = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
|
||||
setHighlightersToEditor(project, document, startOffset, endOffset, highlights, colorsScheme, group, markup);
|
||||
}
|
||||
|
||||
private static void setHighlightersToEditor(@NotNull Project project,
|
||||
@NotNull Document document,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull Collection<? extends HighlightInfo> infos,
|
||||
@Nullable EditorColorsScheme colorsScheme, // if null, the global scheme will be used
|
||||
int group,
|
||||
@NotNull MarkupModelEx markup) {
|
||||
TextRange range = new TextRange(startOffset, endOffset);
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
if (psiFile instanceof PsiCompiledFile) {
|
||||
psiFile = ((PsiCompiledFile)psiFile).getDecompiledPsiFile();
|
||||
}
|
||||
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(project);
|
||||
if (psiFile != null) {
|
||||
codeAnalyzer.cleanFileLevelHighlights(group, psiFile);
|
||||
}
|
||||
|
||||
if (psiFile != null) {
|
||||
HighlightingSession session = HighlightingSessionImpl.createHighlightingSession(psiFile, new DaemonProgressIndicator(), colorsScheme, ProperTextRange.create(startOffset, endOffset), CanISilentlyChange.Result.UH_UH);
|
||||
setHighlightersInRange(document, range, new ArrayList<>(infos), markup, group, session);
|
||||
}
|
||||
setHighlightersInRange(range, new ArrayList<>(highlights), markup, group, session);
|
||||
}
|
||||
|
||||
// set highlights inside startOffset,endOffset but outside priorityRange
|
||||
static void setHighlightersOutsideRange(@NotNull Document document,
|
||||
@NotNull List<? extends HighlightInfo> infos,
|
||||
static void setHighlightersOutsideRange(@NotNull List<? extends HighlightInfo> infos,
|
||||
@NotNull TextRange restrictedRange,
|
||||
@NotNull TextRange priorityRange,
|
||||
int group,
|
||||
@@ -140,13 +101,7 @@ public final class BackgroundUpdateHighlightersUtil {
|
||||
PsiFile psiFile = session.getPsiFile();
|
||||
Project project = session.getProject();
|
||||
List<HighlightInfo> filteredInfos = UpdateHighlightersUtil.HighlightInfoPostFilters.applyPostFilter(project, infos);
|
||||
|
||||
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(project);
|
||||
|
||||
if (restrictedRange.getStartOffset() == 0 && restrictedRange.getEndOffset() == document.getTextLength()) {
|
||||
codeAnalyzer.cleanFileLevelHighlights(group, psiFile);
|
||||
}
|
||||
|
||||
Document document = session.getDocument();
|
||||
MarkupModel markup = DocumentMarkupModel.forDocument(document, project, true);
|
||||
|
||||
SeverityRegistrar severityRegistrar = SeverityRegistrar.getSeverityRegistrar(project);
|
||||
@@ -177,6 +132,7 @@ public final class BackgroundUpdateHighlightersUtil {
|
||||
Long2ObjectMap<RangeMarker> range2markerCache = new Long2ObjectOpenHashMap<>(10);
|
||||
boolean[] changed = {false};
|
||||
SweepProcessor.Generator<HighlightInfo> generator = proc -> ContainerUtil.process(filteredInfos, proc);
|
||||
List<HighlightInfo> fileLevelHighlights = new ArrayList<>();
|
||||
SweepProcessor.sweep(generator, (offset, info, atStart, overlappingIntervals) -> {
|
||||
if (!atStart) return true;
|
||||
if (!info.isFromInjection() && info.getEndOffset() < document.getTextLength() && !restrictedRange.contains(info)) {
|
||||
@@ -184,7 +140,7 @@ public final class BackgroundUpdateHighlightersUtil {
|
||||
}
|
||||
|
||||
if (info.isFileLevelAnnotation()) {
|
||||
codeAnalyzer.addFileLevelHighlight(group, info, psiFile);
|
||||
fileLevelHighlights.add(info);
|
||||
changed[0] = true;
|
||||
return true;
|
||||
}
|
||||
@@ -200,25 +156,26 @@ public final class BackgroundUpdateHighlightersUtil {
|
||||
return true;
|
||||
});
|
||||
|
||||
boolean shouldClean = restrictedRange.getStartOffset() == 0 && restrictedRange.getEndOffset() == document.getTextLength();
|
||||
session.updateFileLevelHighlights(fileLevelHighlights, group, shouldClean);
|
||||
changed[0] |= UpdateHighlightersUtil.incinerateObsoleteHighlighters(infosToRemove, session);
|
||||
|
||||
if (changed[0]) {
|
||||
UpdateHighlightersUtil.clearWhiteSpaceOptimizationFlag(document);
|
||||
}
|
||||
}
|
||||
|
||||
static void setHighlightersInRange(@NotNull Document document,
|
||||
@NotNull TextRange range,
|
||||
static void setHighlightersInRange(@NotNull TextRange range,
|
||||
@NotNull List<? extends HighlightInfo> infos,
|
||||
@NotNull MarkupModelEx markup,
|
||||
int group,
|
||||
@NotNull HighlightingSession session) {
|
||||
ApplicationManager.getApplication().assertIsNonDispatchThread();
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
Project project = session.getProject();
|
||||
PsiFile psiFile = session.getPsiFile();
|
||||
Project project = session.getProject();
|
||||
SeverityRegistrar severityRegistrar = SeverityRegistrar.getSeverityRegistrar(project);
|
||||
HighlightersRecycler infosToRemove = new HighlightersRecycler();
|
||||
Document document = session.getDocument();
|
||||
DaemonCodeAnalyzerEx.processHighlights(markup, project, null, range.getStartOffset(), range.getEndOffset(), info -> {
|
||||
if (info.getGroup() == group) {
|
||||
RangeHighlighter highlighter = info.getHighlighter();
|
||||
@@ -236,15 +193,15 @@ public final class BackgroundUpdateHighlightersUtil {
|
||||
List<HighlightInfo> filteredInfos = UpdateHighlightersUtil.HighlightInfoPostFilters.applyPostFilter(project, infos);
|
||||
ContainerUtil.quickSort(filteredInfos, UpdateHighlightersUtil.BY_START_OFFSET_NO_DUPS);
|
||||
Long2ObjectMap<RangeMarker> range2markerCache = new Long2ObjectOpenHashMap<>(10);
|
||||
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(project);
|
||||
boolean[] changed = {false};
|
||||
SweepProcessor.Generator<HighlightInfo> generator = processor -> ContainerUtil.process(filteredInfos, processor);
|
||||
List<HighlightInfo> fileLevelHighlights = new ArrayList<>();
|
||||
SweepProcessor.sweep(generator, (__, info, atStart, overlappingIntervals) -> {
|
||||
if (!atStart) {
|
||||
return true;
|
||||
}
|
||||
if (info.isFileLevelAnnotation()) {
|
||||
codeAnalyzer.addFileLevelHighlight(group, info, psiFile);
|
||||
fileLevelHighlights.add(info);
|
||||
changed[0] = true;
|
||||
return true;
|
||||
}
|
||||
@@ -256,6 +213,7 @@ public final class BackgroundUpdateHighlightersUtil {
|
||||
return true;
|
||||
});
|
||||
|
||||
session.updateFileLevelHighlights(fileLevelHighlights, group, range.equalsToRange(0, document.getTextLength()));
|
||||
changed[0] |= UpdateHighlightersUtil.incinerateObsoleteHighlighters(infosToRemove, session);
|
||||
|
||||
if (changed[0]) {
|
||||
|
||||
@@ -82,9 +82,8 @@ public abstract class DaemonCodeAnalyzerEx extends DaemonCodeAnalyzer {
|
||||
@NotNull
|
||||
@TestOnly
|
||||
public abstract List<HighlightInfo> getFileLevelHighlights(@NotNull Project project, @NotNull PsiFile file);
|
||||
|
||||
public abstract void cleanFileLevelHighlights(int group, @NotNull PsiFile psiFile);
|
||||
|
||||
public abstract boolean hasFileLevelHighlights(int group, @NotNull PsiFile psiFile);
|
||||
public abstract void addFileLevelHighlight(int group, @NotNull HighlightInfo info, @NotNull PsiFile psiFile);
|
||||
|
||||
public void markDocumentDirty(@NotNull Document document, @NotNull Object reason) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.lang.annotation.AnnotationHolder;
|
||||
import com.intellij.lang.annotation.Annotator;
|
||||
@@ -28,6 +29,8 @@ import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This instance is created at the highlighting start and discarded when the highlighting is finished.
|
||||
* Intended to store highlighting-related data to make it accessible in the background, during the highlighting process,
|
||||
@@ -53,4 +56,12 @@ public interface HighlightingSession {
|
||||
ProperTextRange getVisibleRange();
|
||||
|
||||
boolean isEssentialHighlightingOnly();
|
||||
|
||||
/**
|
||||
* @return true if the daemon-cancel event (see {@link DaemonCodeAnalyzer.DaemonListener#daemonCancelEventOccurred(String)}) happened
|
||||
* since the {@link HighlightingSession} creation.
|
||||
*/
|
||||
boolean isCanceled();
|
||||
|
||||
void updateFileLevelHighlights(@NotNull List<? extends HighlightInfo> highlights, int group, boolean cleanOldHighlights);
|
||||
}
|
||||
@@ -17,8 +17,11 @@ import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedFileViewProvider;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.concurrency.EdtExecutorService;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
@@ -26,9 +29,13 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.RunnableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class HighlightingSessionImpl implements HighlightingSession {
|
||||
@@ -41,16 +48,20 @@ public final class HighlightingSessionImpl implements HighlightingSession {
|
||||
private final ProperTextRange myVisibleRange;
|
||||
@NotNull
|
||||
private final CanISilentlyChange.Result myCanChangeFileSilently;
|
||||
private final Number myDaemonCancelEventCount;
|
||||
private final int myDaemonInitialCancelEventCount;
|
||||
private volatile boolean myIsEssentialHighlightingOnly;
|
||||
private final Long2ObjectMap<RangeMarker> myRange2markerCache = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>());
|
||||
private volatile boolean myInContent;
|
||||
private volatile ThreeState extensionsAllowToChangeFileSilently;
|
||||
private final List<RunnableFuture<?>> pendingFileLevelHighlightRequests = ContainerUtil.createLockFreeCopyOnWriteList();
|
||||
|
||||
private HighlightingSessionImpl(@NotNull PsiFile psiFile,
|
||||
@NotNull DaemonProgressIndicator progressIndicator,
|
||||
@Nullable EditorColorsScheme editorColorsScheme,
|
||||
@NotNull ProperTextRange visibleRange,
|
||||
@NotNull CanISilentlyChange.Result canChangeFileSilently) {
|
||||
@NotNull CanISilentlyChange.Result canChangeFileSilently,
|
||||
@NotNull Number daemonCancelEventCount) {
|
||||
myPsiFile = psiFile;
|
||||
myProgressIndicator = progressIndicator;
|
||||
myEditorColorsScheme = editorColorsScheme;
|
||||
@@ -58,6 +69,9 @@ public final class HighlightingSessionImpl implements HighlightingSession {
|
||||
myDocument = ReadAction.compute(() -> psiFile.getOriginalFile().getViewProvider().getDocument());
|
||||
myVisibleRange = visibleRange;
|
||||
myCanChangeFileSilently = canChangeFileSilently;
|
||||
myDaemonCancelEventCount = daemonCancelEventCount;
|
||||
myDaemonInitialCancelEventCount = daemonCancelEventCount.intValue();
|
||||
assert !(psiFile.getViewProvider() instanceof InjectedFileViewProvider) : "Expected top-level file, but got: " + psiFile.getViewProvider();
|
||||
}
|
||||
|
||||
private static final Key<ConcurrentMap<PsiFile, HighlightingSession>> HIGHLIGHTING_SESSION = Key.create("HIGHLIGHTING_SESSION");
|
||||
@@ -90,36 +104,38 @@ public final class HighlightingSessionImpl implements HighlightingSession {
|
||||
Map<PsiFile, HighlightingSession> map = progressIndicator.getUserData(HIGHLIGHTING_SESSION);
|
||||
HighlightingSession session = map == null ? null : map.get(psiFile);
|
||||
if (session == null) {
|
||||
createHighlightingSession(psiFile, progressIndicator, null, visibleRange, CanISilentlyChange.Result.UH_UH);
|
||||
createHighlightingSession(psiFile, progressIndicator, null, visibleRange, CanISilentlyChange.Result.UH_UH, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static HighlightingSessionImpl createHighlightingSession(@NotNull PsiFile psiFile,
|
||||
@Nullable Editor editor,
|
||||
@Nullable EditorColorsScheme editorColorsScheme,
|
||||
@NotNull DaemonProgressIndicator progressIndicator) {
|
||||
@Nullable Editor editor,
|
||||
@Nullable EditorColorsScheme editorColorsScheme,
|
||||
@NotNull DaemonProgressIndicator progressIndicator,
|
||||
@NotNull Number daemonCancelEventCount) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
TextRange fileRange = psiFile.getTextRange();
|
||||
ProperTextRange visibleRange;
|
||||
visibleRange =
|
||||
editor == null ? ProperTextRange.create(ObjectUtils.notNull(fileRange, TextRange.EMPTY_RANGE)) : editor.calculateVisibleRange();
|
||||
visibleRange = editor == null ? ProperTextRange.create(ObjectUtils.notNull(fileRange, TextRange.EMPTY_RANGE))
|
||||
: editor.calculateVisibleRange();
|
||||
CanISilentlyChange.Result canChangeFileSilently = CanISilentlyChange.thisFile(psiFile);
|
||||
return (HighlightingSessionImpl)createHighlightingSession(psiFile, progressIndicator, editorColorsScheme, visibleRange, canChangeFileSilently);
|
||||
return createHighlightingSession(psiFile, progressIndicator, editorColorsScheme, visibleRange, canChangeFileSilently, daemonCancelEventCount);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static HighlightingSession createHighlightingSession(@NotNull PsiFile psiFile,
|
||||
@NotNull DaemonProgressIndicator progressIndicator,
|
||||
@Nullable EditorColorsScheme editorColorsScheme,
|
||||
@NotNull ProperTextRange visibleRange,
|
||||
@NotNull CanISilentlyChange.Result canChangeFileSilently) {
|
||||
static HighlightingSessionImpl createHighlightingSession(@NotNull PsiFile psiFile,
|
||||
@NotNull DaemonProgressIndicator progressIndicator,
|
||||
@Nullable EditorColorsScheme editorColorsScheme,
|
||||
@NotNull ProperTextRange visibleRange,
|
||||
@NotNull CanISilentlyChange.Result canChangeFileSilently,
|
||||
@NotNull Number daemonCancelEventCount) {
|
||||
// no assertIsDispatchThread() is necessary
|
||||
Map<PsiFile, HighlightingSession> map = progressIndicator.getUserData(HIGHLIGHTING_SESSION);
|
||||
if (map == null) {
|
||||
map = progressIndicator.putUserDataIfAbsent(HIGHLIGHTING_SESSION, new ConcurrentHashMap<>());
|
||||
}
|
||||
HighlightingSession session = new HighlightingSessionImpl(psiFile, progressIndicator, editorColorsScheme, visibleRange, canChangeFileSilently);
|
||||
HighlightingSessionImpl session = new HighlightingSessionImpl(psiFile, progressIndicator, editorColorsScheme, visibleRange, canChangeFileSilently, daemonCancelEventCount);
|
||||
map.put(psiFile, session);
|
||||
return session;
|
||||
}
|
||||
@@ -129,16 +145,16 @@ public final class HighlightingSessionImpl implements HighlightingSession {
|
||||
@Nullable EditorColorsScheme editorColorsScheme,
|
||||
@NotNull ProperTextRange visibleRange,
|
||||
boolean canChangeFileSilently,
|
||||
@NotNull Runnable runnable) {
|
||||
@NotNull Consumer<? super @NotNull HighlightingSession> runnable) {
|
||||
ApplicationManager.getApplication().assertIsNonDispatchThread();
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
DaemonProgressIndicator indicator = GlobalInspectionContextBase.assertUnderDaemonProgress();
|
||||
HighlightingSessionImpl session =
|
||||
(HighlightingSessionImpl)createHighlightingSession(file, indicator, editorColorsScheme, visibleRange, canChangeFileSilently
|
||||
HighlightingSessionImpl session = createHighlightingSession(file, indicator, editorColorsScheme, visibleRange, canChangeFileSilently
|
||||
? CanISilentlyChange.Result.UH_HUH
|
||||
: CanISilentlyChange.Result.UH_UH);
|
||||
: CanISilentlyChange.Result.UH_UH,
|
||||
0);
|
||||
session.additionalSetupFromBackground(file);
|
||||
runnable.run();
|
||||
runnable.accept(session);
|
||||
}
|
||||
|
||||
static void waitForAllSessionsHighlightInfosApplied(@NotNull DaemonProgressIndicator progressIndicator) {
|
||||
@@ -183,6 +199,9 @@ public final class HighlightingSessionImpl implements HighlightingSession {
|
||||
|
||||
void waitForHighlightInfosApplied() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
for (RunnableFuture<?> request : pendingFileLevelHighlightRequests) {
|
||||
request.run();
|
||||
}
|
||||
}
|
||||
|
||||
static void clearProgressIndicator(@NotNull DaemonProgressIndicator indicator) {
|
||||
@@ -207,9 +226,34 @@ public final class HighlightingSessionImpl implements HighlightingSession {
|
||||
// compute additional stuff in background thread
|
||||
void additionalSetupFromBackground(@NotNull PsiFile psiFile) {
|
||||
ApplicationManager.getApplication().assertIsNonDispatchThread();
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
myIsEssentialHighlightingOnly = HighlightingLevelManager.getInstance(psiFile.getProject()).runEssentialHighlightingOnly(psiFile);
|
||||
VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
myInContent = virtualFile != null && ModuleUtilCore.projectContainsFile(psiFile.getProject(), virtualFile, false);
|
||||
extensionsAllowToChangeFileSilently = virtualFile == null ? ThreeState.UNSURE : SilentChangeVetoer.extensionsAllowToChangeFileSilently(getProject(), virtualFile);
|
||||
}
|
||||
|
||||
public boolean isCanceled() {
|
||||
return myDaemonCancelEventCount.intValue() != myDaemonInitialCancelEventCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFileLevelHighlights(@NotNull List<? extends HighlightInfo> fileLevelHighlights, int group, boolean cleanOldHighlights) {
|
||||
Project project = getProject();
|
||||
DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(project);
|
||||
PsiFile psiFile = getPsiFile();
|
||||
boolean shouldUpdate = !fileLevelHighlights.isEmpty() || codeAnalyzer.hasFileLevelHighlights(group, psiFile);
|
||||
if (shouldUpdate) {
|
||||
Future<?> future = EdtExecutorService.getInstance().submit(() -> {
|
||||
if (project.isDisposed() || isCanceled()) return;
|
||||
if (cleanOldHighlights) {
|
||||
codeAnalyzer.cleanFileLevelHighlights(group, psiFile);
|
||||
}
|
||||
for (HighlightInfo fileLevelInfo : fileLevelHighlights) {
|
||||
codeAnalyzer.addFileLevelHighlight(group, fileLevelInfo, psiFile);
|
||||
}
|
||||
});
|
||||
pendingFileLevelHighlightRequests.add((RunnableFuture<?>)future);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,8 @@ public final class UpdateHighlightersUtil {
|
||||
}
|
||||
|
||||
if (psiFile != null) {
|
||||
HighlightingSession session = HighlightingSessionImpl.createHighlightingSession(psiFile, new DaemonProgressIndicator(), colorsScheme, ProperTextRange.create(startOffset, endOffset), CanISilentlyChange.Result.UH_UH);
|
||||
HighlightingSession session = HighlightingSessionImpl.createHighlightingSession(psiFile, new DaemonProgressIndicator(), colorsScheme, ProperTextRange.create(startOffset, endOffset), CanISilentlyChange.Result.UH_UH,
|
||||
0);
|
||||
setHighlightersInRange(document, range, new ArrayList<>(infos), markup, group, session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +199,7 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
|
||||
|
||||
@Override
|
||||
public void cleanFileLevelHighlights(int group, @NotNull PsiFile psiFile) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
assertMyFile(psiFile.getProject(), psiFile);
|
||||
VirtualFile vFile = BackedVirtualFile.getOriginFileIfBacked(psiFile.getViewProvider().getVirtualFile());
|
||||
for (FileEditor fileEditor : getFileEditorManager().getAllEditors(vFile)) {
|
||||
@@ -206,14 +207,33 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasFileLevelHighlights(int group, @NotNull PsiFile psiFile) {
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
assertMyFile(psiFile.getProject(), psiFile);
|
||||
VirtualFile vFile = BackedVirtualFile.getOriginFileIfBacked(psiFile.getViewProvider().getVirtualFile());
|
||||
for (FileEditor fileEditor : getFileEditorManager().getAllEditors(vFile)) {
|
||||
List<HighlightInfo> infos = fileEditor.getUserData(FILE_LEVEL_HIGHLIGHTS);
|
||||
if (infos != null && !infos.isEmpty()) {
|
||||
for (HighlightInfo info : infos) {
|
||||
if (info.getGroup() == group || group == ANY_GROUP) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final int ANY_GROUP = -409423948;
|
||||
void cleanAllFileLevelHighlights() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
for (FileEditor fileEditor : getFileEditorManager().getAllEditors()) {
|
||||
cleanFileLevelHighlights(fileEditor, ANY_GROUP);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanFileLevelHighlights(@NotNull FileEditor fileEditor, int group) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
List<HighlightInfo> infos = fileEditor.getUserData(FILE_LEVEL_HIGHLIGHTS);
|
||||
if (infos == null || infos.isEmpty()) {
|
||||
return;
|
||||
@@ -237,6 +257,7 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
|
||||
public void addFileLevelHighlight(int group,
|
||||
@NotNull HighlightInfo info,
|
||||
@NotNull PsiFile psiFile) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
assertMyFile(psiFile.getProject(), psiFile);
|
||||
VirtualFile vFile = BackedVirtualFile.getOriginFileIfBacked(psiFile.getViewProvider().getVirtualFile());
|
||||
FileEditorManager fileEditorManager = getFileEditorManager();
|
||||
@@ -1006,7 +1027,6 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
|
||||
@NotNull PsiFile psiFile,
|
||||
int @NotNull [] passesToIgnore) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
int modificationCountBefore = daemonCancelEventCount.get();
|
||||
BackgroundEditorHighlighter highlighter;
|
||||
|
||||
try (AccessToken ignored = ClientId.withClientId(ClientFileEditorManager.getClientId(fileEditor))) {
|
||||
@@ -1032,10 +1052,10 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
|
||||
EditorColorsScheme scheme = editor == null ? null : editor.getColorsScheme();
|
||||
HighlightingSessionImpl session;
|
||||
try (AccessToken ignored = ClientId.withClientId(ClientFileEditorManager.getClientId(fileEditor))) {
|
||||
session = HighlightingSessionImpl.createHighlightingSession(psiFile, editor, scheme, progress);
|
||||
session = HighlightingSessionImpl.createHighlightingSession(psiFile, editor, scheme, progress, daemonCancelEventCount);
|
||||
}
|
||||
JobLauncher.getInstance().submitToJobThread(() ->
|
||||
submitInBackground(fileEditor, document, virtualFile, psiFile, highlighter, passesToIgnore, modificationCountBefore, progress, session),
|
||||
submitInBackground(fileEditor, document, virtualFile, psiFile, highlighter, passesToIgnore, progress, session),
|
||||
// manifest exceptions in EDT to avoid storing them in the Future and abandoning
|
||||
task -> ApplicationManager.getApplication().invokeLater(() -> ConcurrencyUtil.manifestExceptionsIn(task)));
|
||||
return session;
|
||||
@@ -1053,7 +1073,6 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
|
||||
@NotNull PsiFile psiFile,
|
||||
@NotNull BackgroundEditorHighlighter backgroundEditorHighlighter,
|
||||
int @NotNull [] passesToIgnore,
|
||||
int modificationCountBefore,
|
||||
@NotNull DaemonProgressIndicator progress,
|
||||
@NotNull HighlightingSessionImpl session) {
|
||||
ApplicationManager.getApplication().assertIsNonDispatchThread();
|
||||
@@ -1077,7 +1096,7 @@ public final class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implement
|
||||
if (myProject.isDisposed() || !fileEditor.isValid() || !psiFile.isValid()) {
|
||||
return HighlightingPass.EMPTY_ARRAY;
|
||||
}
|
||||
if (daemonCancelEventCount.get() != modificationCountBefore) {
|
||||
if (session.isCanceled()) {
|
||||
// editor or something was changed between commit document notification in EDT and this point in the FJP thread
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.TextRangeScalarUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.SlowOperations;
|
||||
@@ -40,16 +39,15 @@ public class DefaultHighlightInfoProcessor extends HighlightInfoProcessor {
|
||||
@NotNull TextRange restrictRange,
|
||||
int groupId) {
|
||||
PsiFile psiFile = session.getPsiFile();
|
||||
Project project = psiFile.getProject();
|
||||
Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
|
||||
if (document == null) return;
|
||||
Project project = session.getProject();
|
||||
Document document = session.getDocument();
|
||||
long modificationStamp = document.getModificationStamp();
|
||||
TextRange priorityIntersection = priorityRange.intersection(restrictRange);
|
||||
List<HighlightInfo> infoCopy = new ArrayList<>(infos);
|
||||
TextEditorHighlightingPass showAutoImportPass = editor == null ? null : getOrCreateShowAutoImportPass(editor, psiFile, session.getProgressIndicator());
|
||||
MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(document, project, true);
|
||||
if (priorityIntersection != null) {
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersInRange(document, priorityIntersection, infoCopy, markupModel, groupId, session);
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersInRange(priorityIntersection, infoCopy, markupModel, groupId, session);
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
if (editor != null && !editor.isDisposed() && modificationStamp == document.getModificationStamp()) {
|
||||
@@ -105,12 +103,11 @@ public class DefaultHighlightInfoProcessor extends HighlightInfoProcessor {
|
||||
@NotNull TextRange priorityRange,
|
||||
@NotNull TextRange restrictedRange,
|
||||
int groupId) {
|
||||
PsiFile psiFile = session.getPsiFile();
|
||||
Project project = psiFile.getProject();
|
||||
Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
|
||||
if (document == null) return;
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersOutsideRange(document, infos, restrictedRange, priorityRange, groupId, session);
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersOutsideRange(infos, restrictedRange, priorityRange, groupId, session);
|
||||
if (editor != null) {
|
||||
PsiFile psiFile = session.getPsiFile();
|
||||
Project project = session.getProject();
|
||||
Document document = session.getDocument();
|
||||
long modificationStamp = document.getModificationStamp();
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
if (!project.isDisposed() && !editor.isDisposed() && modificationStamp != document.getModificationStamp()) {
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.DocumentListener;
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx;
|
||||
import com.intellij.openapi.editor.impl.DocumentMarkupModel;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -150,19 +152,22 @@ public class ExternalToolPass extends ProgressableTextEditorHighlightingPass {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!documentChanged(modificationStampBefore) && !myProject.isDisposed()) {
|
||||
BackgroundTaskUtil.runUnderDisposeAwareIndicator(myProject, () -> {
|
||||
// run annotators outside the read action because they could start OSProcessHandler
|
||||
runChangeAware(myDocument, ExternalToolPass.this::doAnnotate);
|
||||
ReadAction.run(() -> {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!documentChanged(modificationStampBefore)) {
|
||||
doApply();
|
||||
doFinish(getHighlights());
|
||||
}
|
||||
});
|
||||
});
|
||||
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, ExternalToolPass.this::doAnnotate);
|
||||
ReadAction.run(() -> {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!documentChanged(modificationStampBefore)) {
|
||||
doApply();
|
||||
doFinish(getHighlights());
|
||||
}
|
||||
});
|
||||
}, indicator);
|
||||
}
|
||||
};
|
||||
ExternalAnnotatorManager.getInstance().queue(update);
|
||||
@@ -235,9 +240,9 @@ public class ExternalToolPass extends ProgressableTextEditorHighlightingPass {
|
||||
}
|
||||
|
||||
private void doFinish(@NotNull List<? extends HighlightInfo> highlights) {
|
||||
int start = myRestrictRange.getStartOffset();
|
||||
int end = myRestrictRange.getEndOffset();
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, start, end, highlights, getColorsScheme(), getId());
|
||||
MarkupModelEx markupModel = (MarkupModelEx)DocumentMarkupModel.forDocument(myDocument, myProject, true);
|
||||
// use the method which doesn't retrieve a HighlightingSession from the indicator, because we likely destroyed the one already
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersInRange(myRestrictRange, highlights, markupModel, getId(), myHighlightingSession);
|
||||
DaemonCodeAnalyzerEx.getInstanceEx(myProject).getFileStatusMap().markFileUpToDate(myDocument, getId());
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.editor.impl.DocumentMarkupModel;
|
||||
import com.intellij.openapi.editor.markup.MarkupModel;
|
||||
@@ -59,7 +60,7 @@ public class IdentifierHighlighterPass {
|
||||
|
||||
/**
|
||||
* @param file may be injected fragment, in which case the {@code editor} must be corresponding injected editor and {@code visibleRange} must have consistent offsets inside the injected document.
|
||||
* In both cases, {@link #doCollectInformation()} will produce and apply HighlightInfos to the host file.
|
||||
* In both cases, {@link #doCollectInformation(HighlightingSession)} will produce and apply HighlightInfos to the host file.
|
||||
*/
|
||||
IdentifierHighlighterPass(@NotNull PsiFile file, @NotNull Editor editor, @NotNull TextRange visibleRange) {
|
||||
myFile = file;
|
||||
@@ -68,7 +69,7 @@ public class IdentifierHighlighterPass {
|
||||
myVisibleRange = new ProperTextRange(visibleRange);
|
||||
}
|
||||
|
||||
public void doCollectInformation() {
|
||||
public void doCollectInformation(@NotNull HighlightingSession hostSession) {
|
||||
ApplicationManager.getApplication().assertIsNonDispatchThread();
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
HighlightUsagesHandlerBase<PsiElement> highlightUsagesHandler = HighlightUsagesHandler.createCustomHandler(myEditor, myFile, myVisibleRange);
|
||||
@@ -101,8 +102,7 @@ public class IdentifierHighlighterPass {
|
||||
List<HighlightInfo> infos = virtSpace || isCaretOverCollapsedFoldRegion() ? Collections.emptyList() : getHighlights();
|
||||
PsiFile hostFile = InjectedLanguageManager.getInstance(myFile.getProject()).getTopLevelFile(myFile);
|
||||
Editor hostEditor = InjectedLanguageEditorUtil.getTopLevelEditor(myEditor);
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToSingleEditor(myFile.getProject(), hostEditor, 0, hostFile.getTextLength(), infos,
|
||||
hostEditor.getColorsScheme(), getId());
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersInRange(hostFile.getTextRange(), infos, (MarkupModelEx)hostEditor.getMarkupModel(), getId(), hostSession);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.intellij.openapi.editor.markup.UnmodifiableTextAttributes;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectType;
|
||||
import com.intellij.openapi.project.ProjectTypeService;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
@@ -42,7 +41,6 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedFileViewProvider;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Interner;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -120,7 +118,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
|
||||
ProgressManager.checkCanceled();
|
||||
myInfos = createHighlightsFromContexts(contexts);
|
||||
}
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myRestrictRange.getStartOffset(), myRestrictRange.getEndOffset(), myInfos, getColorsScheme(), getId());
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, getFile(), myDocument, myRestrictRange.getStartOffset(), myRestrictRange.getEndOffset(), myInfos, getId());
|
||||
}
|
||||
|
||||
private static final TextAttributes NONEMPTY_TEXT_ATTRIBUTES = new UnmodifiableTextAttributes(){
|
||||
|
||||
@@ -143,7 +143,8 @@ public class MainPassesRunner {
|
||||
return;
|
||||
}
|
||||
ProperTextRange range = ProperTextRange.create(0, document.getTextLength());
|
||||
HighlightingSessionImpl.createHighlightingSession(psiFile, daemonIndicator, null, range, CanISilentlyChange.Result.UH_UH);
|
||||
HighlightingSessionImpl.createHighlightingSession(psiFile, daemonIndicator, null, range, CanISilentlyChange.Result.UH_UH,
|
||||
0);
|
||||
ProgressManager.getInstance().runProcess(() -> runMainPasses(daemonIndicator, result, psiFile, document), daemonIndicator);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
package com.intellij.codeInsight.highlighting;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightingSessionImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPass;
|
||||
import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPassFactory;
|
||||
import com.intellij.codeInsight.template.Template;
|
||||
@@ -22,10 +24,12 @@ import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.startup.StartupActivity;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -206,29 +210,36 @@ final class BackgroundHighlighter implements StartupActivity, DumbAware {
|
||||
});
|
||||
}
|
||||
|
||||
private static void submitIdentifierHighlighterPass(@NotNull Editor editor,
|
||||
private static void submitIdentifierHighlighterPass(@NotNull Editor hostEditor,
|
||||
int offsetBefore,
|
||||
@NotNull PsiFile newFile,
|
||||
@NotNull Editor newEditor) {
|
||||
ReadAction.nonBlocking(() -> {
|
||||
int textLength = newFile.getTextLength();
|
||||
if (textLength == -1 | editor.isDisposed()) {
|
||||
if (textLength == -1 | hostEditor.isDisposed()) {
|
||||
// sometimes some crazy stuff is returned (EA-248725)
|
||||
return null;
|
||||
}
|
||||
IdentifierHighlighterPass pass = new IdentifierHighlighterPassFactory().
|
||||
createHighlightingPass(newFile, newEditor, TextRange.from(0, textLength));
|
||||
if (pass != null) {
|
||||
pass.doCollectInformation();
|
||||
}
|
||||
ProperTextRange visibleRange = ProperTextRange.from(0, textLength);
|
||||
IdentifierHighlighterPass pass = new IdentifierHighlighterPassFactory().createHighlightingPass(newFile, newEditor, visibleRange);
|
||||
DaemonProgressIndicator indicator = new DaemonProgressIndicator();
|
||||
ProgressManager.getInstance().runProcess(() -> {
|
||||
PsiFile hostPsiFile = PsiDocumentManager.getInstance(newFile.getProject()).getPsiFile(hostEditor.getDocument());
|
||||
if (hostPsiFile == null) return;
|
||||
HighlightingSessionImpl.runInsideHighlightingSession(hostPsiFile, hostEditor.getColorsScheme(), ProperTextRange.create(hostPsiFile.getTextRange()), false, session -> {
|
||||
if (pass != null) {
|
||||
pass.doCollectInformation(session);
|
||||
}
|
||||
});
|
||||
}, indicator);
|
||||
return pass;
|
||||
})
|
||||
.expireWhen(() -> !BackgroundHighlightingUtil.isValidEditor(editor) ||
|
||||
editor.getCaretModel().getOffset() != offsetBefore)
|
||||
.coalesceBy(HighlightIdentifiersKey.class, editor)
|
||||
.finishOnUiThread(ModalityState.stateForComponent(editor.getComponent()), identifierHighlighterPass -> {
|
||||
if (identifierHighlighterPass != null) {
|
||||
identifierHighlighterPass.doAdditionalCodeBlockHighlighting();
|
||||
.expireWhen(() -> !BackgroundHighlightingUtil.isValidEditor(hostEditor) ||
|
||||
hostEditor.getCaretModel().getOffset() != offsetBefore)
|
||||
.coalesceBy(HighlightIdentifiersKey.class, hostEditor)
|
||||
.finishOnUiThread(ModalityState.stateForComponent(hostEditor.getComponent()), pass -> {
|
||||
if (pass != null) {
|
||||
pass.doAdditionalCodeBlockHighlighting();
|
||||
}
|
||||
})
|
||||
.submit(AppExecutorUtil.getAppExecutorService());
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.intellij.codeInsight.highlighting;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
|
||||
import com.intellij.codeInsight.template.impl.TemplateState;
|
||||
import com.intellij.injected.editor.EditorWindow;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -38,6 +39,7 @@ public final class BackgroundHighlightingUtil {
|
||||
@NotNull BiFunction<? super PsiFile, ? super Editor, ? extends T> backgroundProcessor,
|
||||
@NotNull TriConsumer<? super PsiFile, ? super Editor, ? super T> edtProcessor) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
assert !(editor instanceof EditorWindow) : editor;
|
||||
if (!isValidEditor(editor)) return;
|
||||
|
||||
int offsetBefore = editor.getCaretModel().getOffset();
|
||||
|
||||
@@ -73,8 +73,8 @@ final class ChangeSignaturePassFactory implements TextEditorHighlightingPassFact
|
||||
builder.registerFix(action, null, null, null, null);
|
||||
info = builder.createUnconditionally();
|
||||
}
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(),
|
||||
ContainerUtil.createMaybeSingletonList(info), getColorsScheme(), getId());
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myFile, myDocument, 0, myFile.getTextLength(),
|
||||
ContainerUtil.createMaybeSingletonList(info), getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -313,6 +313,7 @@ open class EditorComposite internal constructor(
|
||||
}
|
||||
|
||||
private fun manageTopOrBottomComponent(editor: FileEditor, component: JComponent, top: Boolean, remove: Boolean) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread()
|
||||
val container = (if (top) topComponents.get(editor) else bottomComponents.get(editor))!!
|
||||
selfBorder = false
|
||||
if (remove) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.testFramework.fixtures;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
|
||||
import com.intellij.codeInsight.daemon.impl.*;
|
||||
import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor;
|
||||
import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessors;
|
||||
import com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler;
|
||||
@@ -28,18 +28,17 @@ import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.JBListUpdater;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -56,6 +55,7 @@ import com.intellij.ui.components.JBList;
|
||||
import com.intellij.ui.popup.ComponentPopupBuilderImpl;
|
||||
import com.intellij.ui.speedSearch.NameFilteringListModel;
|
||||
import com.intellij.util.Functions;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -67,6 +67,7 @@ import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
@@ -342,4 +343,22 @@ public final class CodeInsightTestUtil {
|
||||
annotationHolder.assertAllAnnotationsCreated();
|
||||
return List.copyOf(annotationHolder);
|
||||
}
|
||||
|
||||
public static void runIdentifierHighlighterPass(@NotNull PsiFile file, @NotNull Editor editor) {
|
||||
IdentifierHighlighterPass pass = new IdentifierHighlighterPassFactory().createHighlightingPass(file, editor, file.getTextRange());
|
||||
assert pass != null;
|
||||
try {
|
||||
ReadAction.nonBlocking(() -> {
|
||||
DaemonProgressIndicator indicator = new DaemonProgressIndicator();
|
||||
ProgressManager.getInstance().runProcess(() -> {
|
||||
HighlightingSessionImpl.runInsideHighlightingSession(file, editor.getColorsScheme(), ProperTextRange.create(file.getTextRange()), false, session -> {
|
||||
pass.doCollectInformation(session);
|
||||
});
|
||||
}, indicator);
|
||||
}).submit(AppExecutorUtil.getAppExecutorService()).get();
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.codeInsight.daemon.impl.BackgroundUpdateHighlightersUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
|
||||
@@ -18,19 +19,21 @@ import static org.jetbrains.plugins.groovy.annotator.GrReferenceHighlighterFacto
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public class GrReferenceHighlighter extends TextEditorHighlightingPass {
|
||||
private final GroovyFileBase myFile;
|
||||
private final PsiFile myPsiFile;
|
||||
private final GroovyFileBase myGroovyBaseFile;
|
||||
|
||||
GrReferenceHighlighter(@NotNull GroovyFileBase file, @NotNull Document document) {
|
||||
super(file.getProject(), document);
|
||||
myFile = file;
|
||||
GrReferenceHighlighter(@NotNull PsiFile psiFile, @NotNull GroovyFileBase groovyBaseFile, @NotNull Document document) {
|
||||
super(groovyBaseFile.getProject(), document);
|
||||
myPsiFile = psiFile;
|
||||
myGroovyBaseFile = groovyBaseFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCollectInformation(@NotNull ProgressIndicator progress) {
|
||||
if (!shouldHighlight(myFile)) return;
|
||||
if (!shouldHighlight(myGroovyBaseFile)) return;
|
||||
List<HighlightInfo> myInfos = new ArrayList<>();
|
||||
myFile.accept(new InaccessibleElementVisitor(myFile, myProject, (__, info) -> myInfos.add(info)));
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), myInfos, getColorsScheme(), getId());
|
||||
myGroovyBaseFile.accept(new InaccessibleElementVisitor(myGroovyBaseFile, myProject, (__, info) -> myInfos.add(info)));
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myPsiFile, myDocument, 0, myGroovyBaseFile.getTextLength(), myInfos, getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,7 +25,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((GroovyFileBase)groovyFile, editor.getDocument()) : null;
|
||||
return groovyFile instanceof GroovyFileBase ? new GrReferenceHighlighter(file, (GroovyFileBase)groovyFile, editor.getDocument()) : null;
|
||||
}
|
||||
|
||||
static boolean shouldHighlight(@NotNull PsiFile file) {
|
||||
|
||||
@@ -175,7 +175,7 @@ public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
|
||||
}
|
||||
myUnusedDeclarations = unusedDeclarations;
|
||||
List<HighlightInfo> infos = convertUnusedImportsToInfos(unusedDeclarations, unusedImports);
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, myFile.getTextLength(), infos, getColorsScheme(), getId());
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myFile, myDocument, 0, myFile.getTextLength(), infos, getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,14 +33,14 @@ internal class GroovyDeclarationHighlightingPassFactory : TextEditorHighlighting
|
||||
}
|
||||
|
||||
override fun createHighlightingPass(file: PsiFile, editor: Editor): TextEditorHighlightingPass? = file.getGroovyFile()?.let {
|
||||
GroovyDeclarationHighlightingPass(it, editor.document)
|
||||
GroovyDeclarationHighlightingPass(file, it, editor.document)
|
||||
}
|
||||
}
|
||||
|
||||
private class GroovyDeclarationHighlightingPass(file: GroovyFileBase, document: Document) : GroovyHighlightingPass(file, document) {
|
||||
private class GroovyDeclarationHighlightingPass(psiFile: PsiFile, groovyBaseFile: GroovyFileBase, document: Document) : GroovyHighlightingPass(psiFile, groovyBaseFile, document) {
|
||||
|
||||
override fun doCollectInformation(progress: ProgressIndicator) {
|
||||
myFile.accept(object : PsiRecursiveElementWalkingVisitor() {
|
||||
myGroovyBaseFile.accept(object : PsiRecursiveElementWalkingVisitor() {
|
||||
override fun visitElement(element: PsiElement) {
|
||||
if (element is GrReferenceElement<*>) {
|
||||
getReferenceHighlightingAttribute(element)?.let {
|
||||
|
||||
@@ -9,9 +9,10 @@ import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase
|
||||
|
||||
internal abstract class GroovyHighlightingPass(val myFile: PsiFile, document: Document)
|
||||
: TextEditorHighlightingPass(myFile.project, document) {
|
||||
internal abstract class GroovyHighlightingPass(val psiFile: PsiFile, val myGroovyBaseFile: GroovyFileBase, document: Document)
|
||||
: TextEditorHighlightingPass(myGroovyBaseFile.project, document) {
|
||||
|
||||
private val myInfos = mutableListOf<HighlightInfo>()
|
||||
|
||||
@@ -20,9 +21,7 @@ internal abstract class GroovyHighlightingPass(val myFile: PsiFile, document: Do
|
||||
|
||||
internal fun applyInformationInBackground() {
|
||||
if (myInfos.isEmpty()) return
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(
|
||||
myProject, myDocument, 0, myFile.textLength, myInfos, colorsScheme, id
|
||||
)
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, psiFile, myDocument, 0, myGroovyBaseFile.textLength, myInfos, id)
|
||||
}
|
||||
|
||||
protected fun addInfo(element: PsiElement, attribute: TextAttributesKey) {
|
||||
|
||||
@@ -22,14 +22,13 @@ internal class GroovyInlineTransformationHighlightingPassFactory : TextEditorHig
|
||||
}
|
||||
|
||||
override fun createHighlightingPass(file: PsiFile, editor: Editor): TextEditorHighlightingPass? = file.getGroovyFile()?.let {
|
||||
GroovyInlineTransformationHighlightingPass(it, editor.document)
|
||||
GroovyInlineTransformationHighlightingPass(file, it, editor.document)
|
||||
}
|
||||
}
|
||||
|
||||
private class GroovyInlineTransformationHighlightingPass(val file: GroovyFileBase, document: Document) : GroovyHighlightingPass(file, document) {
|
||||
|
||||
private class GroovyInlineTransformationHighlightingPass(psiFile:PsiFile, val groovyBaseFile: GroovyFileBase, document: Document) : GroovyHighlightingPass(psiFile, groovyBaseFile, document) {
|
||||
override fun doCollectInformation(progress: ProgressIndicator) {
|
||||
file.accept(object : GroovyRecursiveElementVisitor() {
|
||||
groovyBaseFile.accept(object : GroovyRecursiveElementVisitor() {
|
||||
|
||||
override fun visitElement(element: GroovyPsiElement) {
|
||||
val performer = getRootInlineTransformationPerformer(element) ?: return super.visitElement(element)
|
||||
|
||||
@@ -63,7 +63,7 @@ abstract class AbstractHighlightingPassBase(
|
||||
for (i in 0 until holder.size()) {
|
||||
result.add(holder.get(i))
|
||||
}
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, file.textLength, result, colorsScheme, id)
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, file, myDocument, 0, file.textLength, result, id)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -54,7 +54,7 @@ class ScriptExternalHighlightingPass(
|
||||
annotation.create()
|
||||
}
|
||||
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, 0, file.textLength, infos, colorsScheme, id)
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(myProject, file, myDocument, 0, file.textLength, infos, id)
|
||||
}
|
||||
|
||||
override fun doApplyInformationToEditor() {
|
||||
|
||||
@@ -47,7 +47,7 @@ class KotlinSemanticHighlightingPass(
|
||||
}
|
||||
}
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(
|
||||
myProject, myDocument, /* startOffset = */ 0, ktFile.textLength, infos, colorsScheme, id
|
||||
myProject, ktFile, myDocument, /* startOffset = */ 0, ktFile.textLength, infos, id
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ class MoveDeclarationsPassFactory : TextEditorHighlightingPassFactory {
|
||||
override fun doCollectInformation(progress: ProgressIndicator) {
|
||||
val info = buildHighlightingInfo()
|
||||
if (info != null) {
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(project, myDocument, 0, file.textLength, listOf(info), colorsScheme, id)
|
||||
BackgroundUpdateHighlightersUtil.setHighlightersToEditor(project, file, myDocument, 0, file.textLength, listOf(info), id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user