From a624b1e931c20e70ab0d65775d4815c583a35605 Mon Sep 17 00:00:00 2001 From: Maksim Zuev Date: Tue, 22 Oct 2024 12:43:10 +0200 Subject: [PATCH] [spring debugger] IDEA-357571 Provide icon to show in the additional context element completion GitOrigin-RevId: 91839d39666ea5fb617476592fe0efd5e4d36d65 --- .../JavaEvaluationContextWrapper.kt | 13 ++-------- ...MarkedObjectAdditionalContextProvider.java | 2 +- .../expression/EvaluatorBuilderImpl.java | 6 ++--- .../evaluation/EvaluationContextWrapper.kt | 25 ++++++++++++++++++- java/java-impl/src/META-INF/JavaPlugin.xml | 1 + 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/JavaEvaluationContextWrapper.kt b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/JavaEvaluationContextWrapper.kt index 760aa8497fc0..8e6988e32df5 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/JavaEvaluationContextWrapper.kt +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/JavaEvaluationContextWrapper.kt @@ -3,20 +3,13 @@ package com.intellij.debugger.engine.evaluation import com.intellij.debugger.impl.DebuggerUtilsEx import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Key import com.intellij.psi.JavaPsiFacade import com.intellij.psi.JavaRecursiveElementVisitor import com.intellij.psi.PsiElement import com.intellij.psi.PsiLocalVariable -import com.sun.jdi.Value import java.util.regex.Pattern internal class JavaEvaluationContextWrapper : EvaluationContextWrapper { - companion object { - @JvmField - val SYNTHETIC_VARIABLE_VALUE_KEY = Key.create<(EvaluationContext) -> Value>("SYNTHETIC_VARIABLE_VALUE_KEY") - } - override fun wrapContext(project: Project, context: PsiElement?, additionalElements: List): PsiElement? { if (additionalElements.isEmpty()) return context val elementsByName = additionalElements.groupBy { it.name }.mapValues { (_, v) -> v[0] } @@ -28,10 +21,8 @@ internal class JavaEvaluationContextWrapper : EvaluationContextWrapper { fragment.accept(object : JavaRecursiveElementVisitor() { override fun visitLocalVariable(variable: PsiLocalVariable) { val name = variable.name - val computeValue = elementsByName[name]?.value - if (computeValue != null) { - variable.putUserData(SYNTHETIC_VARIABLE_VALUE_KEY, computeValue) - } + val element = elementsByName[name] ?: return + variable.putUserData(AdditionalContextProvider.ADDITIONAL_CONTEXT_ELEMENT_KEY, element) } }) return fragment diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/MarkedObjectAdditionalContextProvider.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/MarkedObjectAdditionalContextProvider.java index c1556a32a14a..874e52a64842 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/MarkedObjectAdditionalContextProvider.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/MarkedObjectAdditionalContextProvider.java @@ -57,7 +57,7 @@ class MarkedObjectAdditionalContextProvider implements AdditionalContextProvider try { labelName += CodeFragmentFactoryContextWrapper.DEBUG_LABEL_SUFFIX; Type type = objectRef.type(); - result.add(new AdditionalContextElement(labelName, type.signature(), type.name(), __ -> objectRef)); + result.add(new AdditionalContextElement(labelName, type.signature(), type.name(), /* icon */ null, __ -> objectRef)); } catch (ObjectCollectedException e) { //it.remove(); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java index 16c93ef64145..86bcc3554c42 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java @@ -819,12 +819,12 @@ public final class EvaluatorBuilderImpl implements EvaluatorBuilder { PsiElement element = resolveResult.getElement(); if (element instanceof PsiLocalVariable || element instanceof PsiParameter) { - var computeSyntheticValue = element.getUserData(JavaEvaluationContextWrapper.SYNTHETIC_VARIABLE_VALUE_KEY); - if (computeSyntheticValue != null) { + var contextElement = element.getUserData(AdditionalContextProvider.getADDITIONAL_CONTEXT_ELEMENT_KEY()); + if (contextElement != null) { myResult = new Evaluator() { @Override public Object evaluate(EvaluationContextImpl context) { - return computeSyntheticValue.invoke(context); + return contextElement.getValue().invoke(context); } }; return; diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluationContextWrapper.kt b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluationContextWrapper.kt index 68e917987864..6f0cad5bf890 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluationContextWrapper.kt +++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/EvaluationContextWrapper.kt @@ -1,11 +1,16 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.debugger.engine.evaluation +import com.intellij.debugger.engine.evaluation.AdditionalContextProvider +import com.intellij.ide.IconProvider import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.project.DumbAware import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement import com.sun.jdi.Value import org.jetbrains.annotations.ApiStatus +import javax.swing.Icon /** * Language-specific wrapper that can add variables into an evaluation context. @@ -24,6 +29,9 @@ interface AdditionalContextProvider { companion object { private val EP_NAME = ExtensionPointName.create("com.intellij.debugger.additionalContextProvider") + @JvmStatic + @ApiStatus.Internal + val ADDITIONAL_CONTEXT_ELEMENT_KEY = Key.create("ADDITIONAL_CONTEXT_ELEMENT_KEY") @JvmStatic fun getAllAdditionalContextElements(project: Project, context: PsiElement?): List { @@ -43,6 +51,21 @@ interface AdditionalContextProvider { * @property jvmSignature Object type signature, for example `Ljava/lang/Object;`. * @property jvmTypeName Object type name, for example `java.lang.Object`. * @property value A lambda function returning a [Value] type used for evaluation. + * @property icon Icon to be shown during completion of the element or null, if no custom icon is needed. + * + * Not all languages support icon rendering! Currently only supported for Java. */ @ApiStatus.Internal -data class AdditionalContextElement(val name: String, val jvmSignature: String, val jvmTypeName: String, val value: (EvaluationContext) -> Value) +data class AdditionalContextElement(val name: String, val jvmSignature: String, val jvmTypeName: String, + val icon: Icon? = null, val value: (EvaluationContext) -> Value) + +/** + * This icon provider works only for elements with [AdditionalContextProvider.ADDITIONAL_CONTEXT_ELEMENT_KEY] set, + * so it should be only elements suggested in evaluation. + */ +private class AdditionalContextIconProvider : IconProvider(), DumbAware { + override fun getIcon(element: PsiElement, flags: Int): Icon? { + val contextElement = element.getUserData(AdditionalContextProvider.ADDITIONAL_CONTEXT_ELEMENT_KEY) ?: return null + return contextElement.icon + } +} diff --git a/java/java-impl/src/META-INF/JavaPlugin.xml b/java/java-impl/src/META-INF/JavaPlugin.xml index 16f82f1ef291..a925b32b8fa5 100644 --- a/java/java-impl/src/META-INF/JavaPlugin.xml +++ b/java/java-impl/src/META-INF/JavaPlugin.xml @@ -578,6 +578,7 @@ +