mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Add async API to XValueMarkerProvider
GitOrigin-RevId: 4a0372dd6f98de71f2ea3dbe8a1b6ebb6849e2fa
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6ab258333a
commit
2da966fb75
+27
-22
@@ -32,6 +32,7 @@ import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.xdebugger.frame.XValueModifier;
|
||||
import com.intellij.xdebugger.frame.XValueNode;
|
||||
@@ -41,6 +42,8 @@ import com.intellij.xdebugger.impl.ui.tree.ValueMarkup;
|
||||
import com.sun.jdi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.concurrency.Promises;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
@@ -575,30 +578,32 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
|
||||
});
|
||||
}
|
||||
|
||||
return ReadAction.nonBlocking(() -> {
|
||||
PsiElement res = null;
|
||||
try {
|
||||
res = getDescriptorEvaluation(context);
|
||||
}
|
||||
catch (NeedMarkException e) {
|
||||
XValueMarkers<?, ?> markers = DebuggerUtilsImpl.getValueMarkers(context.getDebugProcess());
|
||||
if (markers != null) {
|
||||
ValueMarkup existing = markers.getMarkup(value);
|
||||
String name;
|
||||
if (existing != null) {
|
||||
name = existing.getText();
|
||||
}
|
||||
else {
|
||||
name = e.getMarkName();
|
||||
markers.markValue(value, new ValueMarkup(name, new JBColor(0, 0), null));
|
||||
}
|
||||
res = JavaPsiFacade.getElementFactory(myProject)
|
||||
.createExpressionFromText(name + CodeFragmentFactoryContextWrapper.DEBUG_LABEL_SUFFIX,
|
||||
PositionUtil.getContextElement(context));
|
||||
Promise<PsiElement> res;
|
||||
try {
|
||||
res = Promises.resolvedPromise(getDescriptorEvaluation(context));
|
||||
}
|
||||
catch (NeedMarkException e) {
|
||||
XValueMarkers<?, ?> markers = DebuggerUtilsImpl.getValueMarkers(context.getDebugProcess());
|
||||
if (markers != null) {
|
||||
ValueMarkup existing = markers.getMarkup(value);
|
||||
String markName;
|
||||
Promise<Object> promise;
|
||||
if (existing != null) {
|
||||
markName = existing.getText();
|
||||
promise = Promises.resolvedPromise();
|
||||
}
|
||||
else {
|
||||
markName = e.getMarkName();
|
||||
promise = markers.markValueAsync(value, new ValueMarkup(markName, new JBColor(0, 0), null));
|
||||
}
|
||||
res = promise.then(__ -> ReadAction.nonBlocking(() -> JavaPsiFacade.getElementFactory(myProject)
|
||||
.createExpressionFromText(markName + CodeFragmentFactoryContextWrapper.DEBUG_LABEL_SUFFIX,
|
||||
PositionUtil.getContextElement(context))).executeSynchronously());
|
||||
} else {
|
||||
res = Promises.resolvedPromise(null);
|
||||
}
|
||||
return CompletableFuture.completedFuture(res);
|
||||
}).executeSynchronously();
|
||||
}
|
||||
return Promises.asCompletableFuture(res);
|
||||
}
|
||||
|
||||
protected static class NeedMarkException extends EvaluateException {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
package com.intellij.xdebugger.frame;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.concurrency.Promises;
|
||||
|
||||
/**
|
||||
* Provides implementation of 'Mark Object' feature. <p>
|
||||
@@ -54,12 +56,29 @@ public abstract class XValueMarkerProvider<V extends XValue, M> {
|
||||
return getMarker(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Async version of the {@link #markValue(XValue)} method
|
||||
* @return a promise with a marker for {@code value}
|
||||
*/
|
||||
@NotNull
|
||||
public Promise<M> markValueAsync(@NotNull V value) {
|
||||
return Promises.resolvedPromise(markValue(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when 'Unmark Object' action is invoked.
|
||||
*/
|
||||
public void unmarkValue(@NotNull V value, @NotNull M marker) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Async version of the {@link #unmarkValue(XValue, Object)} method
|
||||
*/
|
||||
public Promise<Object> unmarkValueAsync(@NotNull V value, @NotNull M marker) {
|
||||
unmarkValue(value, marker);
|
||||
return Promises.resolvedPromise();
|
||||
}
|
||||
|
||||
public final Class<V> getValueClass() {
|
||||
return myValueClass;
|
||||
}
|
||||
|
||||
+15
-6
@@ -4,6 +4,7 @@ package com.intellij.xdebugger.impl.actions.handlers;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.ui.ComponentUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl;
|
||||
@@ -17,6 +18,7 @@ import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -38,8 +40,9 @@ public class XMarkObjectActionHandler extends MarkObjectActionHandler {
|
||||
XDebuggerTreeState treeState = XDebuggerTreeState.saveState(node.getTree());
|
||||
|
||||
ValueMarkup existing = markers.getMarkup(value);
|
||||
Promise<Object> markPromise;
|
||||
if (existing != null) {
|
||||
markers.unmarkValue(value);
|
||||
markPromise = markers.unmarkValueAsync(value);
|
||||
}
|
||||
else {
|
||||
Component component = event.getData(CONTEXT_COMPONENT);
|
||||
@@ -52,13 +55,19 @@ public class XMarkObjectActionHandler extends MarkObjectActionHandler {
|
||||
dialog.show();
|
||||
ValueMarkup markup = dialog.getConfiguredMarkup();
|
||||
if (dialog.isOK() && markup != null) {
|
||||
markers.markValue(value, markup);
|
||||
markPromise = markers.markValueAsync(value, markup);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (detachedView) {
|
||||
node.getTree().rebuildAndRestore(treeState);
|
||||
}
|
||||
session.rebuildViews();
|
||||
markPromise.onSuccess(__ ->
|
||||
UIUtil.invokeLaterIfNeeded(() -> {
|
||||
if (detachedView) {
|
||||
node.getTree().rebuildAndRestore(treeState);
|
||||
}
|
||||
session.rebuildViews();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,10 +6,15 @@ import com.intellij.xdebugger.frame.XValueMarkerProvider;
|
||||
import com.intellij.xdebugger.impl.ui.tree.ValueMarkup;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.concurrency.Promise;
|
||||
import org.jetbrains.concurrency.Promises;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public final class XValueMarkers<V extends XValue, M> {
|
||||
private final XValueMarkerProvider<V, M> myProvider;
|
||||
@@ -17,7 +22,7 @@ public final class XValueMarkers<V extends XValue, M> {
|
||||
|
||||
private XValueMarkers(@NotNull XValueMarkerProvider<V, M> provider) {
|
||||
myProvider = provider;
|
||||
myMarkers = new HashMap<>();
|
||||
myMarkers = Collections.synchronizedMap(new HashMap<>());
|
||||
}
|
||||
|
||||
public static <V extends XValue, M> XValueMarkers<V, M> createValueMarkers(@NotNull XValueMarkerProvider<V, M> provider) {
|
||||
@@ -45,25 +50,52 @@ public final class XValueMarkers<V extends XValue, M> {
|
||||
return myProvider.canMark(valueClass.cast(value));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void markValue(@NotNull XValue value, @NotNull ValueMarkup markup) {
|
||||
// remove the existing label if any
|
||||
myMarkers.entrySet().stream()
|
||||
.filter(entry -> markup.getText().equals(entry.getValue().getText()))
|
||||
.findFirst()
|
||||
.ifPresent(entry -> myMarkers.remove(entry.getKey()));
|
||||
|
||||
//noinspection unchecked
|
||||
M m = myProvider.markValue((V)value);
|
||||
myMarkers.put(m, markup);
|
||||
try {
|
||||
markValueAsync(value, markup).blockingGet(5, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (TimeoutException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Promise<Object> markValueAsync(@NotNull XValue value, @NotNull ValueMarkup markup) {
|
||||
synchronized (myMarkers) {
|
||||
// remove the existing label if any
|
||||
myMarkers.entrySet().stream()
|
||||
.filter(entry -> markup.getText().equals(entry.getValue().getText()))
|
||||
.findFirst()
|
||||
.ifPresent(entry -> myMarkers.remove(entry.getKey()));
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
Promise<M> promise = myProvider.markValueAsync((V)value);
|
||||
return promise.then(m -> {
|
||||
myMarkers.put(m, markup);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void unmarkValue(@NotNull XValue value) {
|
||||
try {
|
||||
unmarkValueAsync(value).blockingGet(5, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (TimeoutException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Promise<Object> unmarkValueAsync(@NotNull XValue value) {
|
||||
//noinspection unchecked
|
||||
final V v = (V)value;
|
||||
M m = myProvider.getMarker(v);
|
||||
if (m != null) {
|
||||
myProvider.unmarkValue(v, m);
|
||||
myMarkers.remove(m);
|
||||
return myProvider.unmarkValueAsync(v, m)
|
||||
.onSuccess(__ -> myMarkers.remove(m));
|
||||
} else {
|
||||
return Promises.resolvedPromise();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user