mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[dfa debugger] extract common presentation code to allow reuse in PHP dfa debugger implementation
related to WI-70670, review IJ-CR-102855 GitOrigin-RevId: 0d58dcc3e53f6d4955dcec4cec9630fb9a63bd5a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e470f9c3c8
commit
294181000b
@@ -5,6 +5,7 @@ import com.intellij.codeInspection.dataFlow.lang.DfaListener;
|
||||
import com.intellij.codeInspection.dataFlow.lang.ir.ControlFlow;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.xdebugger.impl.dfaassist.DfaHint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
+2
-15
@@ -24,13 +24,13 @@ import com.intellij.debugger.jdi.StackFrameProxyEx;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.concurrency.annotations.RequiresReadLock;
|
||||
import com.intellij.xdebugger.impl.dfaassist.DfaResult;
|
||||
import com.sun.jdi.*;
|
||||
import one.util.streamex.EntryStream;
|
||||
import one.util.streamex.StreamEx;
|
||||
@@ -63,7 +63,7 @@ public class DebuggerDfaRunner {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DebuggerDfaRunner.DfaResult computeHints() {
|
||||
public DfaResult computeHints() {
|
||||
if (PsiModificationTracker.getInstance(myProject).getModificationCount() != myModificationStamp) {
|
||||
return DfaResult.EMPTY;
|
||||
}
|
||||
@@ -346,17 +346,4 @@ public class DebuggerDfaRunner {
|
||||
}
|
||||
return constraint;
|
||||
}
|
||||
|
||||
public static class DfaResult {
|
||||
static final @NotNull DfaResult EMPTY = new DfaResult(null, Map.of(), Set.of());
|
||||
public final @Nullable PsiFile file;
|
||||
public final @NotNull Map<PsiElement, DfaHint> hints;
|
||||
public final @NotNull Collection<TextRange> unreachable;
|
||||
|
||||
DfaResult(@Nullable PsiFile file, @NotNull Map<PsiElement, DfaHint> hints, @NotNull Collection<TextRange> unreachable) {
|
||||
this.file = file;
|
||||
this.hints = hints;
|
||||
this.unreachable = unreachable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
// 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.debugger.engine.dfaassist;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.hints.presentation.MenuOnClickPresentation;
|
||||
import com.intellij.codeInsight.hints.presentation.PresentationFactory;
|
||||
import com.intellij.codeInsight.hints.presentation.PresentationRenderer;
|
||||
import com.intellij.debugger.JavaDebuggerBundle;
|
||||
import com.intellij.debugger.SourcePosition;
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
@@ -18,69 +13,47 @@ import com.intellij.debugger.impl.DebuggerStateManager;
|
||||
import com.intellij.debugger.jdi.StackFrameProxyEx;
|
||||
import com.intellij.debugger.jdi.StackFrameProxyImpl;
|
||||
import com.intellij.debugger.settings.ViewsGeneralSettings;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.Inlay;
|
||||
import com.intellij.openapi.editor.InlayModel;
|
||||
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.EditorImpl;
|
||||
import com.intellij.openapi.editor.markup.HighlighterLayer;
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.SmartPointerManager;
|
||||
import com.intellij.psi.SmartPsiElementPointer;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.concurrency.EdtScheduledExecutorService;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebugSessionListener;
|
||||
import com.intellij.xdebugger.impl.dfaassist.DfaAssistBase;
|
||||
import com.intellij.xdebugger.impl.dfaassist.DfaResult;
|
||||
import com.sun.jdi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.CancellablePromise;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class DfaAssist implements DebuggerContextListener, Disposable {
|
||||
import static com.intellij.xdebugger.impl.dfaassist.DfaAssistBase.AssistMode.*;
|
||||
|
||||
public final class DfaAssist extends DfaAssistBase implements DebuggerContextListener {
|
||||
private static final int CLEANUP_DELAY_MILLIS = 300;
|
||||
private final @NotNull Project myProject;
|
||||
// modified from EDT only
|
||||
private DfaAssistMarkup myMarkup = new DfaAssistMarkup(null, Collections.emptyList(), Collections.emptyList());
|
||||
private volatile CancellablePromise<?> myComputation;
|
||||
private volatile ScheduledFuture<?> myScheduledCleanup;
|
||||
private final DebuggerStateManager myManager;
|
||||
private volatile AssistMode myMode;
|
||||
|
||||
private DfaAssist(@NotNull Project project, @NotNull DebuggerStateManager manager) {
|
||||
myProject = project;
|
||||
super(project);
|
||||
myManager = manager;
|
||||
updateFromSettings();
|
||||
}
|
||||
|
||||
private void updateFromSettings() {
|
||||
AssistMode newMode = AssistMode.fromSettings();
|
||||
AssistMode newMode = fromSettings();
|
||||
if (myMode != newMode) {
|
||||
myMode = newMode;
|
||||
if (newMode == AssistMode.NONE) {
|
||||
if (newMode == NONE) {
|
||||
cleanUp();
|
||||
}
|
||||
else {
|
||||
@@ -92,40 +65,13 @@ public final class DfaAssist implements DebuggerContextListener, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class DfaAssistMarkup implements Disposable {
|
||||
private final @NotNull List<Inlay<?>> myInlays;
|
||||
private final @NotNull List<RangeHighlighter> myRanges;
|
||||
|
||||
private DfaAssistMarkup(@Nullable Editor editor, @NotNull List<Inlay<?>> inlays, @NotNull List<RangeHighlighter> ranges) {
|
||||
myInlays = inlays;
|
||||
myRanges = ranges;
|
||||
if (editor != null) {
|
||||
editor.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void beforeDocumentChange(@NotNull DocumentEvent event) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> Disposer.dispose(DfaAssistMarkup.this));
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
myInlays.forEach(Disposer::dispose);
|
||||
myInlays.clear();
|
||||
myRanges.forEach(RangeHighlighter::dispose);
|
||||
myRanges.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeEvent(@NotNull DebuggerContextImpl newContext, DebuggerSession.Event event) {
|
||||
if (event == DebuggerSession.Event.DISPOSE) {
|
||||
Disposer.dispose(this);
|
||||
return;
|
||||
}
|
||||
if (myMode == AssistMode.NONE) return;
|
||||
if (myMode == NONE) return;
|
||||
if (event == DebuggerSession.Event.DETACHED) {
|
||||
cleanUp();
|
||||
return;
|
||||
@@ -165,7 +111,7 @@ public final class DfaAssist implements DebuggerContextListener, Disposable {
|
||||
}
|
||||
myComputation = ReadAction.nonBlocking(() -> {
|
||||
DebuggerDfaRunner runner = runnerPupa.transform();
|
||||
return runner == null ? DebuggerDfaRunner.DfaResult.EMPTY : runner.computeHints();
|
||||
return runner == null ? DfaResult.EMPTY : runner.computeHints();
|
||||
})
|
||||
.withDocumentsCommitted(myProject)
|
||||
.coalesceBy(DfaAssist.this)
|
||||
@@ -192,51 +138,10 @@ public final class DfaAssist implements DebuggerContextListener, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanUp() {
|
||||
@Override
|
||||
protected void cleanUp() {
|
||||
cancelComputation();
|
||||
UIUtil.invokeLaterIfNeeded(() -> {
|
||||
Disposer.dispose(myMarkup);
|
||||
});
|
||||
}
|
||||
|
||||
private void displayInlays(DebuggerDfaRunner.DfaResult result) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
cleanUp();
|
||||
Map<PsiElement, DfaHint> hints = result.hints;
|
||||
Collection<TextRange> unreachable = result.unreachable;
|
||||
if (result.file == null) return;
|
||||
EditorImpl editor = ObjectUtils.tryCast(FileEditorManager.getInstance(myProject).getSelectedTextEditor(), EditorImpl.class);
|
||||
if (editor == null) return;
|
||||
VirtualFile expectedFile = result.file.getVirtualFile();
|
||||
if (expectedFile == null || !expectedFile.equals(editor.getVirtualFile())) return;
|
||||
List<Inlay<?>> newInlays = new ArrayList<>();
|
||||
List<RangeHighlighter> ranges = new ArrayList<>();
|
||||
AssistMode mode = myMode;
|
||||
if (!hints.isEmpty() && mode.displayInlays()) {
|
||||
InlayModel model = editor.getInlayModel();
|
||||
AnAction turnOffDfaProcessor = new TurnOffDfaProcessorAction();
|
||||
hints.forEach((expr, hint) -> {
|
||||
Segment range = expr.getTextRange();
|
||||
if (range == null) return;
|
||||
PresentationFactory factory = new PresentationFactory(editor);
|
||||
MenuOnClickPresentation presentation = new MenuOnClickPresentation(
|
||||
factory.roundWithBackground(factory.smallText(hint.getTitle())), myProject,
|
||||
() -> Collections.singletonList(turnOffDfaProcessor));
|
||||
newInlays.add(model.addInlineElement(range.getEndOffset(), new PresentationRenderer(presentation)));
|
||||
});
|
||||
}
|
||||
if (!unreachable.isEmpty() && mode.displayGrayOut()) {
|
||||
MarkupModelEx model = editor.getMarkupModel();
|
||||
for (TextRange range : unreachable) {
|
||||
RangeHighlighter highlighter = model.addRangeHighlighter(HighlightInfoType.UNUSED_SYMBOL.getAttributesKey(),
|
||||
range.getStartOffset(), range.getEndOffset(), HighlighterLayer.ERROR + 1,
|
||||
HighlighterTargetArea.EXACT_RANGE);
|
||||
ranges.add(highlighter);
|
||||
}
|
||||
}
|
||||
if (!newInlays.isEmpty() || !ranges.isEmpty()) {
|
||||
myMarkup = new DfaAssistMarkup(editor, newInlays, ranges);
|
||||
}
|
||||
super.cleanUp();
|
||||
}
|
||||
|
||||
public static @Nullable DebuggerDfaRunner createDfaRunner(@NotNull StackFrameProxyEx proxy,
|
||||
@@ -271,18 +176,6 @@ public final class DfaAssist implements DebuggerContextListener, Disposable {
|
||||
return pupa;
|
||||
}
|
||||
|
||||
private final class TurnOffDfaProcessorAction extends AnAction {
|
||||
private TurnOffDfaProcessorAction() {
|
||||
super(JavaDebuggerBundle.message("action.TurnOffDfaAssist.text"),
|
||||
JavaDebuggerBundle.message("action.TurnOffDfaAssist.description"), AllIcons.Actions.Cancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent evt) {
|
||||
Disposer.dispose(DfaAssist.this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install dataflow assistant to the specified debugging session
|
||||
*
|
||||
@@ -306,29 +199,17 @@ public final class DfaAssist implements DebuggerContextListener, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private enum AssistMode {
|
||||
NONE, INLAYS, GRAY_OUT, BOTH;
|
||||
|
||||
boolean displayInlays() {
|
||||
return this == INLAYS || this == BOTH;
|
||||
private static AssistMode fromSettings() {
|
||||
ViewsGeneralSettings settings = ViewsGeneralSettings.getInstance();
|
||||
if (settings.USE_DFA_ASSIST && settings.USE_DFA_ASSIST_GRAY_OUT) {
|
||||
return BOTH;
|
||||
}
|
||||
|
||||
boolean displayGrayOut() {
|
||||
return this == GRAY_OUT || this == BOTH;
|
||||
if (settings.USE_DFA_ASSIST) {
|
||||
return INLAYS;
|
||||
}
|
||||
|
||||
static AssistMode fromSettings() {
|
||||
ViewsGeneralSettings settings = ViewsGeneralSettings.getInstance();
|
||||
if (settings.USE_DFA_ASSIST && settings.USE_DFA_ASSIST_GRAY_OUT) {
|
||||
return BOTH;
|
||||
}
|
||||
if (settings.USE_DFA_ASSIST) {
|
||||
return INLAYS;
|
||||
}
|
||||
if (settings.USE_DFA_ASSIST_GRAY_OUT) {
|
||||
return GRAY_OUT;
|
||||
}
|
||||
return NONE;
|
||||
if (settings.USE_DFA_ASSIST_GRAY_OUT) {
|
||||
return GRAY_OUT;
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import com.intellij.codeInspection.dataFlow.types.DfType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfTypes;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
||||
import com.intellij.debugger.engine.dfaassist.DebuggerDfaListener;
|
||||
import com.intellij.debugger.engine.dfaassist.DfaHint;
|
||||
import com.intellij.xdebugger.impl.dfaassist.DfaHint;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
|
||||
@@ -444,8 +444,6 @@ action.AnActionButton.text.import=Import
|
||||
action.AnActionButton.description.import=Import
|
||||
action.AnActionButton.text.export=Export
|
||||
action.AnActionButton.description.export=Export
|
||||
action.TurnOffDfaAssist.text=Turn Off Data Flow Assist
|
||||
action.TurnOffDfaAssist.description=Switch off data flow aided debugging for this session
|
||||
warning.0=WARNING! {0}
|
||||
instances.window.show.history=InstancesWindow.ShowHistory
|
||||
select.stack.frame=Select stack frame
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<orderEntry type="library" name="ASM" level="project" />
|
||||
<orderEntry type="library" name="org.codehaus.groovy:groovy" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.java.impl.refactorings" />
|
||||
<orderEntry type="module" module-name="intellij.platform.debugger.impl" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.intellij.psi.SmartPointerManager;
|
||||
import com.intellij.psi.SmartPsiElementPointer;
|
||||
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.xdebugger.impl.dfaassist.DfaHint;
|
||||
import com.intellij.xdebugger.impl.dfaassist.DfaResult;
|
||||
import one.util.streamex.EntryStream;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -57,7 +59,7 @@ public abstract class DfaAssistTest extends LightPlatformCodeInsightTestCase {
|
||||
|
||||
DebuggerDfaRunner runner = runnerRef.get();
|
||||
assertNotNull(context, runner);
|
||||
DebuggerDfaRunner.DfaResult dfaResult = runner.computeHints();
|
||||
DfaResult dfaResult = runner.computeHints();
|
||||
Map<PsiElement, DfaHint> hints = dfaResult.hints;
|
||||
|
||||
String fileText = filteredText.replace("<caret>", "");
|
||||
|
||||
@@ -304,4 +304,7 @@ notification.group.debugger.messages=Debugger messages
|
||||
debugger.frame.list.help.title=Reset Frame
|
||||
debugger.frame.list.help.description=Go back to the previous frame. This will reset local variables, but the global state will not be changed.
|
||||
|
||||
XDebugger.Attach.Dialog.Settings.text=Attach dialog settings
|
||||
XDebugger.Attach.Dialog.Settings.text=Attach dialog settings
|
||||
|
||||
action.TurnOffDfaAssist.text=Turn Off Data Flow Assist
|
||||
action.TurnOffDfaAssist.description=Switch off data flow aided debugging for this session
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
// 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.xdebugger.impl.dfaassist;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
|
||||
import com.intellij.codeInsight.hints.presentation.MenuOnClickPresentation;
|
||||
import com.intellij.codeInsight.hints.presentation.PresentationFactory;
|
||||
import com.intellij.codeInsight.hints.presentation.PresentationRenderer;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.Inlay;
|
||||
import com.intellij.openapi.editor.InlayModel;
|
||||
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.EditorImpl;
|
||||
import com.intellij.openapi.editor.markup.HighlighterLayer;
|
||||
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Segment;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.xdebugger.XDebuggerBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class DfaAssistBase implements Disposable {
|
||||
|
||||
protected final Project myProject;
|
||||
protected volatile AssistMode myMode;
|
||||
// modified from EDT only
|
||||
private DfaAssistMarkup myMarkup = new DfaAssistMarkup(null, Collections.emptyList(), Collections.emptyList());
|
||||
|
||||
public DfaAssistBase(Project project) {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@RequiresEdt
|
||||
protected void displayInlays(DfaResult result) {
|
||||
cleanUp();
|
||||
Map<PsiElement, DfaHint> hints = result.hints;
|
||||
Collection<TextRange> unreachable = result.unreachable;
|
||||
if (result.file == null) return;
|
||||
EditorImpl editor = ObjectUtils.tryCast(FileEditorManager.getInstance(myProject).getSelectedTextEditor(), EditorImpl.class);
|
||||
if (editor == null) return;
|
||||
VirtualFile expectedFile = result.file.getVirtualFile();
|
||||
if (expectedFile == null || !expectedFile.equals(editor.getVirtualFile())) return;
|
||||
List<Inlay<?>> newInlays = new ArrayList<>();
|
||||
List<RangeHighlighter> ranges = new ArrayList<>();
|
||||
AssistMode mode = myMode;
|
||||
if (!hints.isEmpty() && mode.displayInlays()) {
|
||||
InlayModel model = editor.getInlayModel();
|
||||
AnAction turnOffDfaProcessor = new TurnOffDfaProcessorAction();
|
||||
hints.forEach((expr, hint) -> {
|
||||
Segment range = expr.getTextRange();
|
||||
if (range == null) return;
|
||||
PresentationFactory factory = new PresentationFactory(editor);
|
||||
MenuOnClickPresentation presentation = new MenuOnClickPresentation(
|
||||
factory.roundWithBackground(factory.smallText(hint.getTitle())), myProject,
|
||||
() -> Collections.singletonList(turnOffDfaProcessor));
|
||||
newInlays.add(model.addInlineElement(range.getEndOffset(), new PresentationRenderer(presentation)));
|
||||
});
|
||||
}
|
||||
if (!unreachable.isEmpty() && mode.displayGrayOut()) {
|
||||
MarkupModelEx model = editor.getMarkupModel();
|
||||
for (TextRange range : unreachable) {
|
||||
RangeHighlighter highlighter = model.addRangeHighlighter(HighlightInfoType.UNUSED_SYMBOL.getAttributesKey(),
|
||||
range.getStartOffset(), range.getEndOffset(), HighlighterLayer.ERROR + 1,
|
||||
HighlighterTargetArea.EXACT_RANGE);
|
||||
ranges.add(highlighter);
|
||||
}
|
||||
}
|
||||
if (!newInlays.isEmpty() || !ranges.isEmpty()) {
|
||||
myMarkup = new DfaAssistMarkup(editor, newInlays, ranges);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
protected void cleanUp() {
|
||||
UIUtil.invokeLaterIfNeeded(() -> {
|
||||
Disposer.dispose(myMarkup);
|
||||
});
|
||||
}
|
||||
|
||||
private static final class DfaAssistMarkup implements Disposable {
|
||||
private final @NotNull List<Inlay<?>> myInlays;
|
||||
private final @NotNull List<RangeHighlighter> myRanges;
|
||||
|
||||
private DfaAssistMarkup(@Nullable Editor editor, @NotNull List<Inlay<?>> inlays, @NotNull List<RangeHighlighter> ranges) {
|
||||
myInlays = inlays;
|
||||
myRanges = ranges;
|
||||
if (editor != null) {
|
||||
editor.getDocument().addDocumentListener(new DocumentListener() {
|
||||
@Override
|
||||
public void beforeDocumentChange(@NotNull DocumentEvent event) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> Disposer.dispose(DfaAssistMarkup.this));
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
myInlays.forEach(Disposer::dispose);
|
||||
myInlays.clear();
|
||||
myRanges.forEach(RangeHighlighter::dispose);
|
||||
myRanges.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private final class TurnOffDfaProcessorAction extends AnAction {
|
||||
private TurnOffDfaProcessorAction() {
|
||||
super(XDebuggerBundle.message("action.TurnOffDfaAssist.text"),
|
||||
XDebuggerBundle.message("action.TurnOffDfaAssist.description"), AllIcons.Actions.Cancel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent evt) {
|
||||
Disposer.dispose(DfaAssistBase.this);
|
||||
}
|
||||
}
|
||||
|
||||
public enum AssistMode {
|
||||
NONE, INLAYS, GRAY_OUT, BOTH;
|
||||
|
||||
boolean displayInlays() {
|
||||
return this == INLAYS || this == BOTH;
|
||||
}
|
||||
|
||||
boolean displayGrayOut() {
|
||||
return this == GRAY_OUT || this == BOTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// 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.debugger.engine.dfaassist;
|
||||
package com.intellij.xdebugger.impl.dfaassist;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -0,0 +1,25 @@
|
||||
// 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.xdebugger.impl.dfaassist;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class DfaResult {
|
||||
public static final @NotNull DfaResult EMPTY = new DfaResult(null, Map.of(), Set.of());
|
||||
public final @Nullable PsiFile file;
|
||||
public final @NotNull Map<PsiElement, DfaHint> hints;
|
||||
public final @NotNull Collection<TextRange> unreachable;
|
||||
|
||||
public DfaResult(@Nullable PsiFile file, @NotNull Map<PsiElement, DfaHint> hints, @NotNull Collection<TextRange> unreachable) {
|
||||
this.file = file;
|
||||
this.hints = hints;
|
||||
this.unreachable = unreachable;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -11,7 +11,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaValue
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue
|
||||
import com.intellij.debugger.engine.dfaassist.DebuggerDfaListener
|
||||
import com.intellij.debugger.engine.dfaassist.DfaAssistProvider
|
||||
import com.intellij.debugger.engine.dfaassist.DfaHint
|
||||
import com.intellij.xdebugger.impl.dfaassist.DfaHint
|
||||
import com.intellij.debugger.jdi.StackFrameProxyEx
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
|
||||
Reference in New Issue
Block a user