From 02dd01217af1c6fae90d4f2c3934276cfda8f0a0 Mon Sep 17 00:00:00 2001 From: Maksim Zuev Date: Mon, 18 Aug 2025 13:06:54 +0200 Subject: [PATCH] [rd debugger] Convert ViewAsGroup to Kotlin GitOrigin-RevId: 5c96c7ee669763cbb68aaf6d7d53801154e38aa4 --- .../intellij/debugger/actions/ViewAsGroup.kt | 276 ++++++++---------- 1 file changed, 123 insertions(+), 153 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.kt b/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.kt index d4619a781b78..ec2d4fe208e5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.kt +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.kt @@ -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 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 values = getSelectedValues(e); - final List 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 { 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 values = getSelectedValues(e); + val values = getSelectedValues(e) if (!values.isEmpty()) { - CompletableFuture> 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>() + 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 rs = ProgressIndicatorUtils.awaitWithCheckCanceled(future); + val rs = ProgressIndicatorUtils.awaitWithCheckCanceled(future) if (ContainerUtil.isEmpty(rs)) { - return EMPTY_ARRAY; + return EMPTY_ARRAY } - List 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() + 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> getApplicableRenderers(List values, DebugProcessImpl process) { - List>> futures = new ArrayList<>(values.size()); - for (JavaValue value : values) { - CompletableFuture> 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 res = null; - for (CompletableFuture> future : futures) { - List 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): CompletableFuture> { + val futures = mutableListOf>>() + for (value in values) { + val completedFuture = getApplicableNodeRenderers(value) + futures.add(completedFuture) } - return ContainerUtil.notNullize(res); - }); - } - @ApiStatus.Internal - public static CompletableFuture> 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? = 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> { + 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 getSelectedValues(@NotNull AnActionEvent event) { - List selectedNodes = XDebuggerTree.getSelectedNodes(event.getDataContext()); - return StreamEx.of(selectedNodes) - .map(XValueNodeImpl::getValueContainer) - .select(JavaValue.class) - .toList(); + @JvmStatic + fun getSelectedValues(event: AnActionEvent): List { + val selectedNodes = XDebuggerTree.getSelectedNodes(event.dataContext) + return StreamEx.of(selectedNodes) + .map { obj -> obj.valueContainer } + .select(JavaValue::class.java) + .toList() + } } }