import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.server.BuildManager;
+import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.extractMethod.PrepareFailedException;
import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler;
+import com.intellij.xdebugger.XDebuggerManager;
+import com.intellij.xdebugger.frame.XSuspendContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.incremental.java.JavaBuilder;
if (Registry.is("debugger.compiling.evaluator") && psiContext != null) {
return ApplicationManager.getApplication().runReadAction((ThrowableComputable<ExpressionEvaluator, EvaluateException>)() -> {
try {
+ boolean useReflection = !Registry.is("debugger.compiling.evaluator.magic.accessor", true);
+ if (!useReflection) {
+ XSuspendContext suspendContext = XDebuggerManager.getInstance(project).getCurrentSession().getSuspendContext();
+ if (suspendContext instanceof SuspendContextImpl) {
+ JavaSdkVersion version =
+ JavaSdkVersion.fromVersionString(((SuspendContextImpl)suspendContext).getDebugProcess().getVirtualMachineProxy().version());
+ useReflection = version != null && version.isAtLeast(JavaSdkVersion.JDK_1_9);
+ }
+ }
+
ExtractLightMethodObjectHandler.ExtractedData data = ExtractLightMethodObjectHandler.extractLightMethodObject(
project,
findPhysicalContext(psiContext),
fragmentFactory.apply(psiContext),
- getGeneratedClassName());
+ getGeneratedClassName(),
+ useReflection);
if (data != null) {
return new CompilingEvaluatorImpl(project, psiContext, data);
}
import com.intellij.refactoring.extractMethod.AbstractExtractDialog;
import com.intellij.refactoring.extractMethod.InputVariables;
import com.intellij.refactoring.extractMethod.PrepareFailedException;
+import com.intellij.refactoring.extractMethodObject.reflect.CompositeReflectionAccessor;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.VariableData;
import com.intellij.usageView.UsageInfo;
@Nullable PsiElement originalContext,
@NotNull final PsiCodeFragment fragment,
final String methodName) throws PrepareFailedException {
+ return extractLightMethodObject(project, originalContext, fragment, methodName, false);
+ }
+
+ @Nullable
+ public static ExtractedData extractLightMethodObject(final Project project,
+ @Nullable PsiElement originalContext,
+ @NotNull final PsiCodeFragment fragment,
+ final String methodName,
+ boolean useReflection) throws PrepareFailedException {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiElement[] elements = completeToStatementArray(fragment, elementFactory);
if (elements == null) {
PsiStatement outStatement = elementFactory.createStatementFromText("System.out.println(" + outputVariables + ");", anchor);
outStatement = (PsiStatement)container.addAfter(outStatement, elementsCopy[elementsCopy.length - 1]);
- copy.accept(new JavaRecursiveElementWalkingVisitor() {
- private void makePublic(PsiMember method) {
- if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
- VisibilityUtil.setVisibility(method.getModifierList(), PsiModifier.PUBLIC);
+ if (!useReflection) {
+ copy.accept(new JavaRecursiveElementWalkingVisitor() {
+ private void makePublic(PsiMember method) {
+ if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
+ VisibilityUtil.setVisibility(method.getModifierList(), PsiModifier.PUBLIC);
+ }
}
- }
- @Override
- public void visitMethod(PsiMethod method) {
- super.visitMethod(method);
- makePublic(method);
- }
+ @Override
+ public void visitMethod(PsiMethod method) {
+ super.visitMethod(method);
+ makePublic(method);
+ }
- @Override
- public void visitField(PsiField field) {
- super.visitField(field);
- makePublic(field);
- }
- });
+ @Override
+ public void visitField(PsiField field) {
+ super.visitField(field);
+ makePublic(field);
+ }
+ });
+ }
final ExtractMethodObjectProcessor extractMethodObjectProcessor = new ExtractMethodObjectProcessor(project, null, elementsCopy, "") {
@Override
}
final int startOffset = startOffsetInContainer + container.getTextRange().getStartOffset();
+
+ final PsiClass inner = extractMethodObjectProcessor.getInnerClass();
+ final PsiMethod[] methods = inner.findMethodsByName("invoke", false);
+
+ if (useReflection && methods.length == 1) {
+ final PsiMethod method = methods[0];
+ CompositeReflectionAccessor.createAccessorToEverything(inner, elementFactory)
+ .accessThroughReflection(method);
+ }
+
final String generatedCall = copy.getText().substring(startOffset, outStatement.getTextOffset());
return new ExtractedData(generatedCall,
(PsiClass)CodeStyleManager.getInstance(project).reformat(extractMethodObjectProcessor.getInnerClass()),
--- /dev/null
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.refactoring.extractMethodObject.reflect;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementFactory;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Vitaliy.Bibaev
+ */
+public class CompositeReflectionAccessor implements ReflectionAccessor {
+ private final List<ReflectionAccessor> myAccessors = new ArrayList<>();
+
+ private CompositeReflectionAccessor() {
+ }
+
+ private void registerAccessor(@NotNull ReflectionAccessor accessor) {
+ myAccessors.add(accessor);
+ }
+
+ public static ReflectionAccessor createAccessorToEverything(@NotNull PsiClass psiClass, @NotNull PsiElementFactory elementFactory) {
+ CompositeReflectionAccessor compositeAccessor = new CompositeReflectionAccessor();
+ compositeAccessor.registerAccessor(new FieldReflectionAccessor(psiClass, elementFactory));
+ compositeAccessor.registerAccessor(new MethodReflectionAccessor(psiClass, elementFactory));
+ compositeAccessor.registerAccessor(new ConstructorReflectionAccessor(psiClass, elementFactory));
+ compositeAccessor.registerAccessor(new MethodReferenceReflectionAccessor(psiClass, elementFactory));
+
+ return compositeAccessor;
+ }
+
+ @Override
+ public void accessThroughReflection(@NotNull PsiElement element) {
+ for (ReflectionAccessor accessor : myAccessors) {
+ accessor.accessThroughReflection(element);
+ }
+ }
+}
debugger.mayBringFrameToFrontOnBreakpoint=true
debugger.batch.evaluation=false
debugger.compiling.evaluator=true
+debugger.compiling.evaluator.magic.accessor=true
debugger.watches.in.variables=true
debugger.auto.fetch.icons=true
debugger.close.dialog.on.navigate=true