extract super class: check for conflicts under progress; skip check for superclass inheritors mismatch - as no actual members would go there

This commit is contained in:
unknown
2010-07-05 14:55:33 +04:00
committed by anna
parent 5b9cce7e4a
commit f87d17b2a3
9 changed files with 110 additions and 10 deletions
@@ -29,6 +29,7 @@ import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.psi.*;
@@ -124,7 +125,7 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
}
public boolean checkConflicts(ExtractSuperclassDialog dialog) {
public boolean checkConflicts(final ExtractSuperclassDialog dialog) {
final MemberInfo[] infos = ArrayUtil.toObjectArray(dialog.getSelectedMemberInfos(), MemberInfo.class);
final PsiDirectory targetDirectory = dialog.getTargetDirectory();
final PsiPackage targetPackage;
@@ -134,8 +135,14 @@ public class ExtractSuperclassHandler implements RefactoringActionHandler, Extra
else {
targetPackage = null;
}
final MultiMap<PsiElement,String> conflicts =
PullUpConflictsUtil.checkConflicts(infos, mySubclass, mySubclass.getSuperClass(), targetPackage, targetDirectory, dialog.getContainmentVerifier());
final MultiMap<PsiElement,String> conflicts = new MultiMap<PsiElement, String>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
public void run() {
final PsiClass superClass = mySubclass.getExtendsListTypes().length > 0 ? mySubclass.getSuperClass() : null;
conflicts.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier(), false));
}
}, "Detecting possible conflicts...", true, myProject)) return false;
if (!conflicts.isEmpty()) {
ConflictsDialog conflictsDialog = new ConflictsDialog(myProject, conflicts);
conflictsDialog.show();
@@ -60,6 +60,16 @@ public class PullUpConflictsUtil {
PsiPackage targetPackage,
PsiDirectory targetDirectory,
final InterfaceContainmentVerifier interfaceContainmentVerifier) {
return checkConflicts(infos, subclass, superClass, targetPackage, targetDirectory, interfaceContainmentVerifier, true);
}
public static MultiMap<PsiElement, String> checkConflicts(final MemberInfo[] infos,
PsiClass subclass,
@Nullable PsiClass superClass,
PsiPackage targetPackage,
PsiDirectory targetDirectory,
final InterfaceContainmentVerifier interfaceContainmentVerifier,
boolean movedMembers2Super) {
final Set<PsiMember> movedMembers = new HashSet<PsiMember>();
final Set<PsiMethod> abstractMethods = new HashSet<PsiMethod>();
final boolean isInterfaceTarget;
@@ -98,7 +108,7 @@ public class PullUpConflictsUtil {
}
}
RefactoringConflictsUtil.analyzeAccessibilityConflicts(movedMembers, superClass, conflicts, null, targetRepresentativeElement, abstrMethods);
if (superClass != null) {
if (superClass != null && movedMembers2Super) {
checkSuperclassMembers(superClass, infos, conflicts);
if (isInterfaceTarget) {
checkInterfaceTarget(infos, conflicts);
@@ -0,0 +1,5 @@
public class Test {
void x() {
foo();
}
}
@@ -0,0 +1,4 @@
public class TestSubclass extends Test {
private void foo(){}
}
@@ -0,0 +1,7 @@
public class Test {
void x() {
foo();
}
private void foo(){}
}
@@ -0,0 +1,7 @@
import java.util.ArrayList;
public class Test extends ArrayList {
void x() {
removeRange(0, 0);
}
}
@@ -0,0 +1,2 @@
public class TestSubclass extends Test {
}
@@ -0,0 +1,6 @@
import java.util.*;
public class Test extends ArrayList {
void x() {
removeRange(0, 0);
}
}
@@ -9,20 +9,24 @@ import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.search.ProjectScope;
import com.intellij.refactoring.extractSuperclass.ExtractSuperClassProcessor;
import com.intellij.refactoring.memberPullUp.PullUpConflictsUtil;
import com.intellij.refactoring.memberPullUp.PullUpHelper;
import com.intellij.refactoring.util.DocCommentPolicy;
import com.intellij.refactoring.util.classMembers.InterfaceContainmentVerifier;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
/**
* @author yole
@@ -37,6 +41,18 @@ public class ExtractSuperClassTest extends CodeInsightTestCase {
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("x", PsiField.class));
}
public void testConflictUsingPrivateMethod() throws Exception {
doTest("Test", "TestSubclass",
new String[] {"Method <b><code>Test.foo()</code></b> is private and will not be accessible from method <b><code>x()</code></b>.",
"Method <b><code>x()</code></b> uses method <b><code>Test.foo()</code></b>, which is not moved to the superclass"},
new RefactoringTestUtil.MemberDescriptor("x", PsiMethod.class));
}
public void testNoConflictUsingProtectedMethodFromSuper() throws Exception {
doTest("Test", "TestSubclass",
new RefactoringTestUtil.MemberDescriptor("x", PsiMethod.class));
}
public void testParameterNameEqualsFieldName() throws Exception { // IDEADEV-10629
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("a", PsiField.class));
}
@@ -79,18 +95,54 @@ public class ExtractSuperClassTest extends CodeInsightTestCase {
private void doTest(@NonNls final String className, @NonNls final String newClassName,
RefactoringTestUtil.MemberDescriptor... membersToFind) throws Exception {
doTest(className, newClassName, null, membersToFind);
}
private void doTest(@NonNls final String className, @NonNls final String newClassName,
String[] conflicts,
RefactoringTestUtil.MemberDescriptor... membersToFind) throws Exception {
String rootBefore = getRoot() + "/before";
PsiTestUtil.removeAllRoots(myModule, JavaSdkImpl.getMockJdk14());
final VirtualFile rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, rootBefore, myFilesToDelete);
PsiClass psiClass = myJavaFacade.findClass(className, ProjectScope.getAllScope(myProject));
assertNotNull(psiClass);
final MemberInfo[] members = RefactoringTestUtil.findMembers(psiClass, membersToFind);
final PsiDirectory targetDirectory = psiClass.getContainingFile().getContainingDirectory();
ExtractSuperClassProcessor processor = new ExtractSuperClassProcessor(myProject,
psiClass.getContainingFile().getContainingDirectory(),
targetDirectory,
newClassName,
psiClass, members,
false,
new DocCommentPolicy(DocCommentPolicy.ASIS));
new DocCommentPolicy<PsiComment>(DocCommentPolicy.ASIS));
final PsiPackage targetPackage;
if (targetDirectory != null) {
targetPackage = JavaDirectoryService.getInstance().getPackage(targetDirectory);
}
else {
targetPackage = null;
}
final PsiClass superClass = psiClass.getExtendsListTypes().length > 0 ? psiClass.getSuperClass() : null;
final MultiMap<PsiElement, String> conflictsMap =
PullUpConflictsUtil.checkConflicts(members, psiClass, superClass, targetPackage, targetDirectory, new InterfaceContainmentVerifier() {
public boolean checkedInterfacesContain(PsiMethod psiMethod) {
return PullUpHelper.checkedInterfacesContain(Arrays.asList(members), psiMethod);
}
}, false);
if (conflicts != null) {
if (conflictsMap.isEmpty()) {
fail("Conflicts were not detected");
}
final HashSet<String> expectedConflicts = new HashSet<String>(Arrays.asList(conflicts));
final HashSet<String> actualConflicts = new HashSet<String>(conflictsMap.values());
assertEquals(expectedConflicts.size(), actualConflicts.size());
for (String actualConflict : actualConflicts) {
if (!expectedConflicts.contains(actualConflict)) {
fail("Unexpected conflict: " + actualConflict);
}
}
} else if (!conflictsMap.isEmpty()) {
fail("Unexpected conflicts!!!");
}
processor.run();
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
FileDocumentManager.getInstance().saveAllDocuments();