mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[rd debugger] Convert ViewAsGroup to Kotlin
GitOrigin-RevId: 5c96c7ee669763cbb68aaf6d7d53801154e38aa4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a830f04615
commit
02dd01217a
@@ -1,211 +1,181 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.actions;
|
||||
package com.intellij.debugger.actions
|
||||
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
|
||||
import com.intellij.debugger.engine.JavaValue;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsAsync;
|
||||
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
|
||||
import com.intellij.debugger.ui.tree.render.NodeRenderer;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
|
||||
import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import com.intellij.debugger.engine.JavaValue
|
||||
import com.intellij.debugger.engine.SuspendContextImpl
|
||||
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl
|
||||
import com.intellij.debugger.impl.DebuggerUtilsAsync
|
||||
import com.intellij.debugger.ui.tree.render.NodeRenderer
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorUtils
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree
|
||||
import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase
|
||||
import one.util.streamex.StreamEx
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ViewAsGroup extends ActionGroup implements DumbAware {
|
||||
private static final Logger LOG = Logger.getInstance(ViewAsGroup.class);
|
||||
|
||||
public ViewAsGroup() {
|
||||
super(Presentation.NULL_STRING, true);
|
||||
class ViewAsGroup : ActionGroup(Presentation.NULL_STRING, true), DumbAware {
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.BGT
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ActionUpdateThread getActionUpdateThread() {
|
||||
return ActionUpdateThread.BGT;
|
||||
}
|
||||
|
||||
private static class RendererAction extends ToggleAction {
|
||||
private final NodeRenderer myNodeRenderer;
|
||||
|
||||
RendererAction(NodeRenderer nodeRenderer) {
|
||||
super(nodeRenderer.getName());
|
||||
myNodeRenderer = nodeRenderer;
|
||||
getTemplatePresentation().setKeepPopupOnPerform(KeepPopupOnPerform.IfRequested);
|
||||
private class RendererAction(private val nodeRenderer: NodeRenderer) : ToggleAction(nodeRenderer.getName()) {
|
||||
init {
|
||||
getTemplatePresentation().setKeepPopupOnPerform(KeepPopupOnPerform.IfRequested)
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected(@NotNull AnActionEvent e) {
|
||||
List<JavaValue> values = getSelectedValues(e);
|
||||
override fun isSelected(e: AnActionEvent): Boolean {
|
||||
val values = getSelectedValues(e)
|
||||
if (values.isEmpty()) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
for (JavaValue value : values) {
|
||||
if (value.getDescriptor().getLastRenderer() != myNodeRenderer) {
|
||||
return false;
|
||||
for (value in values) {
|
||||
if (value.descriptor.lastRenderer !== nodeRenderer) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ActionUpdateThread getActionUpdateThread() {
|
||||
return ActionUpdateThread.EDT;
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
return ActionUpdateThread.EDT
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(final @NotNull AnActionEvent e, final boolean state) {
|
||||
if (!state) return;
|
||||
override fun setSelected(e: AnActionEvent, state: Boolean) {
|
||||
if (!state) return
|
||||
|
||||
final DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext());
|
||||
final List<JavaValue> values = getSelectedValues(e);
|
||||
final List<XValueNodeImpl> selectedNodes = XDebuggerTreeActionBase.getSelectedNodes(e.getDataContext());
|
||||
val debuggerContext = DebuggerAction.getDebuggerContext(e.dataContext)
|
||||
val values = getSelectedValues(e)
|
||||
val selectedNodes = XDebuggerTreeActionBase.getSelectedNodes(e.dataContext)
|
||||
|
||||
LOG.assertTrue(!values.isEmpty());
|
||||
LOG.assertTrue(!values.isEmpty())
|
||||
|
||||
DebuggerManagerThreadImpl managerThread = debuggerContext.getManagerThread();
|
||||
if (managerThread == null) {
|
||||
return;
|
||||
}
|
||||
val managerThread = debuggerContext.getManagerThread() ?: return
|
||||
|
||||
managerThread.schedule(new DebuggerContextCommandImpl(debuggerContext) {
|
||||
@Override
|
||||
public void threadAction(@NotNull SuspendContextImpl suspendContext) {
|
||||
for (XValueNodeImpl node : selectedNodes) {
|
||||
XValue container = node.getValueContainer();
|
||||
if (container instanceof JavaValue javaValue) {
|
||||
javaValue.setRenderer(myNodeRenderer, node);
|
||||
managerThread.schedule(object : DebuggerContextCommandImpl(debuggerContext) {
|
||||
override fun threadAction(suspendContext: SuspendContextImpl) {
|
||||
for (node in selectedNodes) {
|
||||
val container = node.valueContainer
|
||||
if (container is JavaValue) {
|
||||
container.setRenderer(nodeRenderer, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnAction @NotNull [] getChildren(final @Nullable AnActionEvent e) {
|
||||
override fun getChildren(e: AnActionEvent?): Array<AnAction> {
|
||||
if (e == null) {
|
||||
return EMPTY_ARRAY;
|
||||
return EMPTY_ARRAY
|
||||
}
|
||||
DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext());
|
||||
DebugProcessImpl process = debuggerContext.getDebugProcess();
|
||||
if (process == null) {
|
||||
return EMPTY_ARRAY;
|
||||
val debuggerContext = DebuggerAction.getDebuggerContext(e.dataContext)
|
||||
if (debuggerContext.debugProcess == null) {
|
||||
return EMPTY_ARRAY
|
||||
}
|
||||
|
||||
List<JavaValue> values = getSelectedValues(e);
|
||||
val values = getSelectedValues(e)
|
||||
if (!values.isEmpty()) {
|
||||
CompletableFuture<List<NodeRenderer>> future = new CompletableFuture<>();
|
||||
boolean scheduled = Objects.requireNonNull(debuggerContext.getManagerThread()).schedule(new DebuggerContextCommandImpl(debuggerContext) {
|
||||
@Override
|
||||
public void threadAction(@NotNull SuspendContextImpl suspendContext) {
|
||||
getApplicableRenderers(values, process)
|
||||
.whenComplete((renderers, throwable) -> DebuggerUtilsAsync.completeFuture(renderers, throwable, future));
|
||||
val future = CompletableFuture<List<NodeRenderer>>()
|
||||
val scheduled = debuggerContext.getManagerThread()!!.schedule(object : DebuggerContextCommandImpl(debuggerContext) {
|
||||
override fun threadAction(suspendContext: SuspendContextImpl) {
|
||||
getApplicableRenderers(values)
|
||||
.whenComplete { renderers, throwable ->
|
||||
DebuggerUtilsAsync.completeFuture(renderers, throwable, future)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void commandCancelled() {
|
||||
future.cancel(false);
|
||||
override fun commandCancelled() {
|
||||
future.cancel(false)
|
||||
}
|
||||
});
|
||||
})
|
||||
if (scheduled) {
|
||||
List<NodeRenderer> rs = ProgressIndicatorUtils.awaitWithCheckCanceled(future);
|
||||
val rs = ProgressIndicatorUtils.awaitWithCheckCanceled(future)
|
||||
if (ContainerUtil.isEmpty(rs)) {
|
||||
return EMPTY_ARRAY;
|
||||
return EMPTY_ARRAY
|
||||
}
|
||||
List<AnAction> children = new ArrayList<>();
|
||||
ActionManager actionManager = ActionManager.getInstance();
|
||||
AnAction[] viewAsActions = ((DefaultActionGroup)actionManager.getAction("Debugger.Representation"))
|
||||
.getChildren(actionManager);
|
||||
for (AnAction viewAsAction : viewAsActions) {
|
||||
if (viewAsAction instanceof AutoRendererAction) {
|
||||
if (rs.size() > 1) {
|
||||
children.add(viewAsAction);
|
||||
val children = mutableListOf<AnAction>()
|
||||
val actionManager = ActionManager.getInstance()
|
||||
val viewAsActions = (actionManager.getAction("Debugger.Representation") as DefaultActionGroup)
|
||||
.getChildren(actionManager)
|
||||
for (viewAsAction in viewAsActions) {
|
||||
if (viewAsAction is AutoRendererAction) {
|
||||
if (rs.size > 1) {
|
||||
children.add(viewAsAction)
|
||||
}
|
||||
}
|
||||
else {
|
||||
children.add(viewAsAction);
|
||||
children.add(viewAsAction)
|
||||
}
|
||||
}
|
||||
|
||||
if (!children.isEmpty()) {
|
||||
children.add(Separator.getInstance());
|
||||
children.add(Separator.getInstance())
|
||||
}
|
||||
children.addAll(ContainerUtil.map(rs, RendererAction::new));
|
||||
|
||||
return children.toArray(EMPTY_ARRAY);
|
||||
children.addAll(rs.map { nodeRenderer -> RendererAction(nodeRenderer) })
|
||||
return children.toTypedArray()
|
||||
}
|
||||
}
|
||||
return EMPTY_ARRAY;
|
||||
return EMPTY_ARRAY
|
||||
}
|
||||
|
||||
private static @NotNull CompletableFuture<List<NodeRenderer>> getApplicableRenderers(List<JavaValue> values, DebugProcessImpl process) {
|
||||
List<CompletableFuture<List<NodeRenderer>>> futures = new ArrayList<>(values.size());
|
||||
for (JavaValue value : values) {
|
||||
CompletableFuture<List<NodeRenderer>> completedFuture = getApplicableNodeRenderers(value);
|
||||
futures.add(completedFuture);
|
||||
override fun update(event: AnActionEvent) {
|
||||
val debuggerContext = DebuggerAction.getDebuggerContext(event.dataContext)
|
||||
if (getSelectedValues(event).isEmpty() || debuggerContext.debugProcess == null) {
|
||||
event.presentation.setEnabledAndVisible(false)
|
||||
return
|
||||
}
|
||||
event.presentation.setEnabledAndVisible(true)
|
||||
}
|
||||
|
||||
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenApply(__ -> {
|
||||
List<NodeRenderer> res = null;
|
||||
for (CompletableFuture<List<NodeRenderer>> future : futures) {
|
||||
List<NodeRenderer> list = future.join();
|
||||
if (res == null) {
|
||||
res = list;
|
||||
}
|
||||
else {
|
||||
res.retainAll(list);
|
||||
}
|
||||
companion object {
|
||||
private val LOG = Logger.getInstance(ViewAsGroup::class.java)
|
||||
|
||||
private fun getApplicableRenderers(values: List<JavaValue>): CompletableFuture<List<NodeRenderer>> {
|
||||
val futures = mutableListOf<CompletableFuture<List<NodeRenderer>>>()
|
||||
for (value in values) {
|
||||
val completedFuture = getApplicableNodeRenderers(value)
|
||||
futures.add(completedFuture)
|
||||
}
|
||||
return ContainerUtil.notNullize(res);
|
||||
});
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static CompletableFuture<List<NodeRenderer>> getApplicableNodeRenderers(JavaValue value) {
|
||||
if (value instanceof JavaReferringObjectsValue) { // disable for any referrers at all
|
||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||
return CompletableFuture.allOf(*futures.toTypedArray()).thenApply {
|
||||
var res: MutableList<NodeRenderer>? = null
|
||||
for (future in futures) {
|
||||
val list = future.join()
|
||||
if (res == null) {
|
||||
res = list.toMutableList()
|
||||
}
|
||||
else {
|
||||
res.retainAll(list)
|
||||
}
|
||||
}
|
||||
res ?: emptyList()
|
||||
}
|
||||
}
|
||||
ValueDescriptorImpl valueDescriptor = value.getDescriptor();
|
||||
if (!valueDescriptor.isValueValid()) {
|
||||
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||
}
|
||||
DebugProcessImpl process = value.getEvaluationContext().getDebugProcess();
|
||||
return process.getApplicableRenderers(valueDescriptor.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final @NotNull AnActionEvent event) {
|
||||
DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(event.getDataContext());
|
||||
if (getSelectedValues(event).isEmpty() || debuggerContext.getDebugProcess() == null) {
|
||||
event.getPresentation().setEnabledAndVisible(false);
|
||||
return;
|
||||
@ApiStatus.Internal
|
||||
fun getApplicableNodeRenderers(value: JavaValue): CompletableFuture<List<NodeRenderer>> {
|
||||
if (value is JavaReferringObjectsValue) { // disable for any referrers at all
|
||||
return CompletableFuture.completedFuture(emptyList())
|
||||
}
|
||||
val valueDescriptor = value.descriptor
|
||||
if (!valueDescriptor.isValueValid) {
|
||||
return CompletableFuture.completedFuture(emptyList())
|
||||
}
|
||||
val process = value.evaluationContext.debugProcess
|
||||
return process.getApplicableRenderers(valueDescriptor.getType())
|
||||
}
|
||||
event.getPresentation().setEnabledAndVisible(true);
|
||||
}
|
||||
|
||||
public static @NotNull List<JavaValue> getSelectedValues(@NotNull AnActionEvent event) {
|
||||
List<XValueNodeImpl> selectedNodes = XDebuggerTree.getSelectedNodes(event.getDataContext());
|
||||
return StreamEx.of(selectedNodes)
|
||||
.map(XValueNodeImpl::getValueContainer)
|
||||
.select(JavaValue.class)
|
||||
.toList();
|
||||
@JvmStatic
|
||||
fun getSelectedValues(event: AnActionEvent): List<JavaValue> {
|
||||
val selectedNodes = XDebuggerTree.getSelectedNodes(event.dataContext)
|
||||
return StreamEx.of(selectedNodes)
|
||||
.map { obj -> obj.valueContainer }
|
||||
.select(JavaValue::class.java)
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user