mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
move inner: outer class reference in hierarchy fixed (IDEA-40651)
This commit is contained in:
@@ -15,17 +15,17 @@
|
||||
*/
|
||||
package com.intellij.refactoring.move;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author ven
|
||||
*/
|
||||
@@ -120,7 +120,7 @@ public class MoveInstanceMembersUtil {
|
||||
if (referencedClass == null) return null;
|
||||
final PsiClass parentClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
|
||||
assert parentClass != null;
|
||||
if (!PsiTreeUtil.isAncestor(referencedClass, parentClass, false)) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(parentClass, referencedClass, false)) {
|
||||
referencedClass = parentClass;
|
||||
}
|
||||
return referencedClass;
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.JavaRefactoringSettings;
|
||||
import com.intellij.refactoring.PackageWrapper;
|
||||
@@ -52,6 +53,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class MoveInnerDialog extends RefactoringDialog {
|
||||
private final Project myProject;
|
||||
@@ -133,7 +136,7 @@ public class MoveInnerDialog extends RefactoringDialog {
|
||||
}
|
||||
|
||||
if (myCbPassOuterClass.isEnabled()) {
|
||||
final boolean thisNeeded = MoveInstanceMembersUtil.getThisClassesToMembers(myInnerClass).containsKey(myOuterClass);
|
||||
boolean thisNeeded = isThisNeeded(myInnerClass, myOuterClass);
|
||||
myCbPassOuterClass.setSelected(thisNeeded);
|
||||
myParameterField.setEnabled(thisNeeded);
|
||||
}
|
||||
@@ -153,6 +156,16 @@ public class MoveInnerDialog extends RefactoringDialog {
|
||||
super.init();
|
||||
}
|
||||
|
||||
public static boolean isThisNeeded(final PsiClass innerClass, final PsiClass outerClass) {
|
||||
final Map<PsiClass, Set<PsiMember>> classesToMembers = MoveInstanceMembersUtil.getThisClassesToMembers(innerClass);
|
||||
for (PsiClass psiClass : classesToMembers.keySet()) {
|
||||
if (InheritanceUtil.isInheritorOrSelf(outerClass, psiClass, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myClassNameField;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package pack1;
|
||||
class D {
|
||||
protected void iAmProtected() {
|
||||
}
|
||||
}
|
||||
|
||||
public class DImpl extends D {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package pack1;
|
||||
|
||||
public class MyRunnable {
|
||||
private DImpl d;
|
||||
|
||||
public MyRunnable(DImpl d) {
|
||||
this.d = d;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
d.iAmProtected();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package pack1;
|
||||
class D {
|
||||
protected void iAmProtected() {
|
||||
}
|
||||
}
|
||||
|
||||
public class DImpl extends D {
|
||||
public class MyRunnable {
|
||||
public void run() {
|
||||
iAmProtected();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
public class D {
|
||||
protected void iAmProtected() {
|
||||
}
|
||||
}
|
||||
|
||||
class DImpl extends D {
|
||||
void f<caret>oo(F f) {
|
||||
class MyRunnable {
|
||||
public void run() {
|
||||
iAmProtected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class F {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
public class D {
|
||||
protected void iAmProtected() {
|
||||
}
|
||||
}
|
||||
|
||||
class DImpl extends D {
|
||||
}
|
||||
|
||||
class F {
|
||||
|
||||
void foo(D d) {
|
||||
class MyRunnable {
|
||||
public void run() {
|
||||
d.iAmProtected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
package com.intellij.refactoring;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.move.moveInner.MoveInnerDialog;
|
||||
import com.intellij.refactoring.move.moveInner.MoveInnerImpl;
|
||||
import com.intellij.refactoring.move.moveInner.MoveInnerProcessor;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -64,6 +65,21 @@ public class MoveInnerTest extends MultiFileTestCase {
|
||||
doTest(createAction("p.A.E", "E", false, null, false, false, null));
|
||||
}
|
||||
|
||||
public void testQualifyThisHierarchy() throws Exception {
|
||||
final String innerClassName = "pack1.DImpl.MyRunnable";
|
||||
doTest(new MyPerformAction(innerClassName, "MyRunnable", false, "d",
|
||||
false, false, null) {
|
||||
@Override
|
||||
protected boolean isPassOuterClass() {
|
||||
final PsiClass outerClass = getJavaFacade().findClass("pack1.DImpl", GlobalSearchScope.moduleScope(myModule));
|
||||
assertNotNull(outerClass);
|
||||
final PsiClass innerClass = getJavaFacade().findClass(innerClassName, GlobalSearchScope.moduleScope(myModule));
|
||||
assertNotNull(innerClass);
|
||||
return MoveInnerDialog.isThisNeeded(innerClass, outerClass);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private PerformAction createAction(@NonNls final String innerClassName,
|
||||
@NonNls final String newClassName,
|
||||
final boolean passOuterClass,
|
||||
@@ -71,28 +87,52 @@ public class MoveInnerTest extends MultiFileTestCase {
|
||||
final boolean searchInComments,
|
||||
final boolean searchInNonJava,
|
||||
@NonNls @Nullable final String packageName) {
|
||||
return new PerformAction() {
|
||||
return new MyPerformAction(innerClassName, newClassName, passOuterClass, parameterName, searchInComments, searchInNonJava, packageName);
|
||||
}
|
||||
|
||||
private class MyPerformAction implements PerformAction {
|
||||
private final String myInnerClassName;
|
||||
private final String myPackageName;
|
||||
private final String myNewClassName;
|
||||
private final boolean myPassOuterClass;
|
||||
private final String myParameterName;
|
||||
private final boolean mySearchInComments;
|
||||
private final boolean mySearchInNonJava;
|
||||
|
||||
public MyPerformAction(String innerClassName, String newClassName, boolean passOuterClass, String parameterName, boolean searchInComments,
|
||||
boolean searchInNonJava,
|
||||
String packageName) {
|
||||
myInnerClassName = innerClassName;
|
||||
myPackageName = packageName;
|
||||
myNewClassName = newClassName;
|
||||
myPassOuterClass = passOuterClass;
|
||||
myParameterName = parameterName;
|
||||
mySearchInComments = searchInComments;
|
||||
mySearchInNonJava = searchInNonJava;
|
||||
}
|
||||
|
||||
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {
|
||||
final JavaPsiFacade manager = getJavaFacade();
|
||||
final PsiClass aClass = manager.findClass(innerClassName, GlobalSearchScope.moduleScope(myModule));
|
||||
final PsiClass aClass = manager.findClass(myInnerClassName, GlobalSearchScope.moduleScope(myModule));
|
||||
final MoveInnerProcessor moveInnerProcessor = new MoveInnerProcessor(myProject, null);
|
||||
final PsiElement targetContainer = packageName != null ? findDirectory(packageName) : MoveInnerImpl.getTargetContainer(aClass, false);
|
||||
final PsiElement targetContainer = myPackageName != null ? findDirectory(myPackageName) : MoveInnerImpl.getTargetContainer(aClass, false);
|
||||
assertNotNull(targetContainer);
|
||||
moveInnerProcessor.setup(aClass, newClassName, passOuterClass, parameterName,
|
||||
searchInComments, searchInNonJava, targetContainer);
|
||||
moveInnerProcessor.setup(aClass, myNewClassName, isPassOuterClass(), myParameterName, mySearchInComments, mySearchInNonJava, targetContainer);
|
||||
moveInnerProcessor.run();
|
||||
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
}
|
||||
|
||||
protected boolean isPassOuterClass() {
|
||||
return myPassOuterClass;
|
||||
}
|
||||
|
||||
private PsiElement findDirectory(final String packageName) {
|
||||
final PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage(packageName);
|
||||
assert aPackage != null;
|
||||
final PsiDirectory[] directories = aPackage.getDirectories();
|
||||
return directories [0];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ public class MoveInstanceMethodTest extends LightCodeInsightTestCase {
|
||||
|
||||
public void testQualifiedThis() throws Exception { doTest(true, 0); }
|
||||
|
||||
public void testQualifyThisHierarchy() throws Exception {doTest(true, 0);}
|
||||
|
||||
public void testTwoParams() throws Exception { doTest(true, 0); }
|
||||
|
||||
public void testNoThisParam() throws Exception { doTest(false, 0); }
|
||||
|
||||
Reference in New Issue
Block a user