From 8a1cc4adf4297ed6bf5f5157e6179d09b6098761 Mon Sep 17 00:00:00 2001 From: Egor Ushakov Date: Thu, 8 Nov 2018 16:01:24 +0300 Subject: [PATCH] IDEA-201942 Do not use compiling evaluator for method references --- .../expression/EvaluatorBuilderImpl.java | 58 ++++++++++++++++++- .../util/resources/misc/registry.properties | 4 ++ 2 files changed, 61 insertions(+), 1 deletion(-) 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 b721950b745b..f6925a41c2ae 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 @@ -18,8 +18,11 @@ import com.intellij.debugger.engine.JVMName; import com.intellij.debugger.engine.JVMNameUtil; import com.intellij.debugger.engine.evaluation.*; import com.intellij.debugger.impl.DebuggerUtilsEx; +import com.intellij.lang.jvm.JvmModifier; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.*; import com.intellij.psi.impl.JavaConstantExpressionEvaluator; import com.intellij.psi.tree.IElementType; @@ -1206,7 +1209,60 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { @Override public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) { - throw new EvaluateRuntimeException(new UnsupportedExpressionException(DebuggerBundle.message("evaluation.error.method.reference.evaluation.not.supported"))); + PsiElement qualifier = expression.getQualifier(); + PsiType interfaceType = expression.getFunctionalInterfaceType(); + if (!Registry.is("debugger.compiling.evaluator.method.refs") && interfaceType != null && qualifier != null) { + PsiElement resolved = expression.resolve(); + if (resolved instanceof PsiMethod) { + try { + PsiMethod method = (PsiMethod)resolved; + PsiClass containingClass = method.getContainingClass(); + if (containingClass != null) { + String methodName = ""; + String findMethodName; + String bind = ""; + if (method.isConstructor()) { + findMethodName = "findConstructor"; + } + else { + methodName = ", \"" + method.getName() + "\""; + if (method.hasModifier(JvmModifier.STATIC)) { + findMethodName = "findStatic"; + } + else { + findMethodName = "findVirtual"; + bind = "mh = mh.bindTo(" + qualifier.getText() + ")\n"; + } + } + String code = + "MethodType mt = MethodType.fromMethodDescriptorString(\"" + JVMNameUtil.getJVMSignature(method) + "\", null);\n" + + "MethodHandle mh = MethodHandles.publicLookup()." + findMethodName + "(" + + containingClass.getQualifiedName() + ".class " + methodName + ", mt);\n" + + bind + + "MethodHandleProxies.asInterfaceInstance(" + interfaceType.getCanonicalText() + ".class, mh);"; + myResult = buildFromJavaCode(code, + "java.lang.invoke.MethodHandle," + + "java.lang.invoke.MethodHandleProxies," + + "java.lang.invoke.MethodHandles," + + "java.lang.invoke.MethodType", + expression); + return; + } + } + catch (Exception e) { + LOG.error(e); + } + } + } + throw new EvaluateRuntimeException( + new UnsupportedExpressionException(DebuggerBundle.message("evaluation.error.method.reference.evaluation.not.supported"))); + } + + private Evaluator buildFromJavaCode(String code, String imports, @NotNull PsiElement context) throws EvaluateException { + TextWithImportsImpl text = new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, code, imports, StdFileTypes.JAVA); + JavaCodeFragment codeFragment = DefaultCodeFragmentFactory.getInstance().createCodeFragment(text, context, context.getProject()); + ExpressionEvaluator evaluator = new Builder(myPosition).buildElement(codeFragment); + return evaluationContext -> evaluator.evaluate(evaluationContext); } @Override diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 1091591fd1c8..4a4b01351cf1 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -393,9 +393,13 @@ debugger.valueTooltipAutoShowOnSelection=false debugger.valueTooltipAutoShowOnSelection.description=Auto show tooltip when editor selection changes debugger.mayBringFrameToFrontOnBreakpoint=true debugger.batch.evaluation=false + debugger.compiling.evaluator=true debugger.compiling.evaluator.magic.accessor=false debugger.compiling.evaluator.reflection.access.with.java8=true +debugger.compiling.evaluator.method.refs=false +debugger.compiling.evaluator.method.refs.description=Use the compiling evaluator for the code with method references + debugger.watches.in.variables=true debugger.auto.fetch.icons=true debugger.close.dialog.on.navigate=true