IDEA-132210 Debugger: Evaluate fails on this and super references in lambda

This commit is contained in:
Egor.Ushakov
2016-02-24 15:32:24 +03:00
parent 0078c22016
commit eed9e7e7fb
3 changed files with 113 additions and 3 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
@@ -49,6 +50,7 @@ import com.intellij.refactoring.classMembers.MemberInfoBase;
import com.intellij.refactoring.extractMethod.AbstractExtractDialog;
import com.intellij.refactoring.extractMethod.ExtractMethodProcessor;
import com.intellij.refactoring.ui.MemberSelectionPanel;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.refactoring.util.duplicates.Match;
@@ -85,6 +87,8 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
private boolean myChangeReturnType;
private Runnable myCopyMethodToInner;
private static final Key<Boolean> GENERATED_RETURN = new Key<Boolean>("GENERATED_RETURN");
public ExtractMethodObjectProcessor(Project project, Editor editor, PsiElement[] elements, final String innerClassName) {
super(project);
myInnerClassName = innerClassName;
@@ -305,7 +309,9 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
public void visitReturnStatement(final PsiReturnStatement statement) {
super.visitReturnStatement(statement);
try {
replacementMap.put(statement, myElementFactory.createStatementFromText("return this;", statement));
PsiStatement returnThisStatement = myElementFactory.createStatementFromText("return this;", statement);
returnThisStatement.putCopyableUserData(GENERATED_RETURN, true);
replacementMap.put(statement, returnThisStatement);
}
catch (IncorrectOperationException e) {
LOG.error(e);
@@ -522,11 +528,46 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
LOG.assertTrue(replacedMethodBody != null);
final PsiCodeBlock methodBody = getMethod().getBody();
LOG.assertTrue(methodBody != null);
if (isCreateInnerClass()) {
adjustTargetClassReferences(methodBody);
}
replacedMethodBody.replace(methodBody);
PsiUtil.setModifierProperty(newMethod, PsiModifier.STATIC, myInnerClass.hasModifierProperty(PsiModifier.STATIC) && notHasGeneratedFields());
myInnerMethod = (PsiMethod)myInnerClass.add(newMethod);
}
private void adjustTargetClassReferences(final PsiElement body) throws IncorrectOperationException {
PsiManager manager = PsiManager.getInstance(myProject);
PsiClass targetClass = getMethod().getContainingClass();
body.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitReturnStatement(PsiReturnStatement statement) {
if (statement.getCopyableUserData(GENERATED_RETURN) == null) { // do not modify our generated returns
super.visitReturnStatement(statement);
}
}
@Override
public void visitThisExpression(PsiThisExpression expression) {
if (expression.getQualifier() == null) {
expression.replace(RefactoringChangeUtil.createThisExpression(manager, targetClass));
}
}
@Override
public void visitSuperExpression(PsiSuperExpression expression) {
if (expression.getQualifier() == null) {
expression.replace(RefactoringChangeUtil.createSuperExpression(manager, targetClass));
}
}
@Override
public void visitClass(PsiClass aClass) {
// do not visit sub classes
}
});
}
private boolean notHasGeneratedFields() {
return !myMultipleExitPoints && getMethod().getParameterList().getParametersCount() == 0;
}

View File

@@ -0,0 +1,28 @@
public class Sample extends Base {
public static void main(String[] args) {
new Sample().foo();
}
void foo() {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
list.for<caret>Each(i -> {
new Runnable() {
int xxx = 0;
@Override
public void run() {
this.xxx = 5; // this stays the same
}
}.run();
this.a++; // have to be qualified
super.foo(); // have to be qualified
a++;
foo();
});
System.out.println(a);
}
}
class Base {
void foo() {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -214,6 +214,47 @@ public class ExtractMethodObject4DebuggerTest extends LightRefactoringTestCase {
" }", false);
}
public void testThisAndSuperReferences() throws Exception {
doTest("list.forEach(i -> {\n" +
" new Runnable() {\n" +
" int xxx = 0;\n" +
" @Override\n" +
" public void run() {\n" +
" this.xxx = 5; // this stays the same\n" +
" }\n" +
" }.run();\n" +
" this.a++; // have to be qualified\n" +
" super.foo(); // have to be qualified\n" +
" a++;\n" +
" foo();\n" +
" });",
"new Test(list).invoke();",
"public class Test {\n" +
" private List<Integer> list;\n" +
"\n" +
" public Test(List<Integer> list) {\n" +
" this.list = list;\n" +
" }\n" +
"\n" +
" public void invoke() {\n" +
" list.forEach(i -> {\n" +
" new Runnable() {\n" +
" int xxx = 0;\n" +
"\n" +
" @Override\n" +
" public void run() {\n" +
" this.xxx = 5; // this stays the same\n" +
" }\n" +
" }.run();\n" +
" Sample.this.a++; // have to be qualified\n" +
" Sample.super.foo(); // have to be qualified\n" +
" a++;\n" +
" foo();\n" +
" });\n" +
" }\n" +
" }", false);
}
public void testOnClosingBrace() throws Exception {
doTest(" foo()", "int result = new Test().invoke();",