/*
- * 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.
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;
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;
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;
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);
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;
}
/*
- * 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.
" }", 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();",