mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
rename refactoring handles class inheritance (PY-1236)
This commit is contained in:
@@ -13,14 +13,20 @@ public class PySuperMethodsSearch extends ExtensibleQueryFactory<PsiElement, PyS
|
||||
|
||||
public static class SearchParameters {
|
||||
private final PyFunction myDerivedMethod;
|
||||
private final boolean myDeepSearch;
|
||||
|
||||
public SearchParameters(final PyFunction derivedMethod) {
|
||||
public SearchParameters(final PyFunction derivedMethod, boolean deepSearch) {
|
||||
myDerivedMethod = derivedMethod;
|
||||
myDeepSearch = deepSearch;
|
||||
}
|
||||
|
||||
public PyFunction getDerivedMethod() {
|
||||
return myDerivedMethod;
|
||||
}
|
||||
|
||||
public boolean isDeepSearch() {
|
||||
return myDeepSearch;
|
||||
}
|
||||
}
|
||||
|
||||
private PySuperMethodsSearch() {
|
||||
@@ -28,7 +34,12 @@ public class PySuperMethodsSearch extends ExtensibleQueryFactory<PsiElement, PyS
|
||||
}
|
||||
|
||||
public static Query<PsiElement> search(final PyFunction derivedMethod) {
|
||||
final SearchParameters parameters = new SearchParameters(derivedMethod);
|
||||
final SearchParameters parameters = new SearchParameters(derivedMethod, false);
|
||||
return INSTANCE.createUniqueResultsQuery(parameters);
|
||||
}
|
||||
|
||||
public static Query<PsiElement> search(final PyFunction derivedMethod, boolean deepSearch) {
|
||||
final SearchParameters parameters = new SearchParameters(derivedMethod, deepSearch);
|
||||
return INSTANCE.createUniqueResultsQuery(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,16 @@ public class PySuperMethodsSearchExecutor implements QueryExecutor<PsiElement, P
|
||||
Set<PyClass> foundMethodContainingClasses = new HashSet<PyClass>();
|
||||
if (name != null && containingClass != null) {
|
||||
for (PyClass superClass : containingClass.iterateAncestors()) {
|
||||
boolean isAlreadyFound = false;
|
||||
for (PyClass alreadyFound : foundMethodContainingClasses) {
|
||||
if (alreadyFound.isSubclass(superClass)) {
|
||||
isAlreadyFound = true;
|
||||
if (!queryParameters.isDeepSearch()) {
|
||||
boolean isAlreadyFound = false;
|
||||
for (PyClass alreadyFound : foundMethodContainingClasses) {
|
||||
if (alreadyFound.isSubclass(superClass)) {
|
||||
isAlreadyFound = true;
|
||||
}
|
||||
}
|
||||
if (isAlreadyFound) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (isAlreadyFound) {
|
||||
continue;
|
||||
}
|
||||
PyFunction superMethod = superClass.findMethodByName(name, false);
|
||||
if (superMethod != null) {
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
package com.jetbrains.python.refactoring.rename;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor;
|
||||
import com.intellij.util.Processor;
|
||||
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.search.PyOverridingMethodsSearch;
|
||||
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -38,4 +48,41 @@ public class RenamePyFunctionProcessor extends RenamePsiElementProcessor {
|
||||
public void setToSearchForTextOccurrences(PsiElement element, boolean enabled) {
|
||||
PyCodeInsightSettings.getInstance().RENAME_SEARCH_NON_CODE_FOR_FUNCTION = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement substituteElementToRename(PsiElement element, Editor editor) {
|
||||
PyFunction function = (PyFunction) element;
|
||||
final PyClass containingClass = function.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return function;
|
||||
}
|
||||
final List<PsiElement> superMethods = new ArrayList<PsiElement>(PySuperMethodsSearch.search(function, true).findAll());
|
||||
if (superMethods.size() > 0) {
|
||||
// TODO this is not exactly right for multiple inheritance
|
||||
final PyFunction deepestSuperMethod = (PyFunction) superMethods.get(superMethods.size()-1);
|
||||
String message = "Method " + function.getName() + " of class " + containingClass.getQualifiedName() + "\noverrides method of class "
|
||||
+ deepestSuperMethod.getContainingClass().getQualifiedName() + ".\nDo you want to rename the base method?";
|
||||
int rc = Messages.showYesNoCancelDialog(element.getProject(), message, "Rename", Messages.getQuestionIcon());
|
||||
if (rc == 0) {
|
||||
return deepestSuperMethod;
|
||||
}
|
||||
if (rc == 1) {
|
||||
return function;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareRenaming(PsiElement element, final String newName, final Map<PsiElement, String> allRenames) {
|
||||
PyFunction function = (PyFunction) element;
|
||||
PyOverridingMethodsSearch.search(function, true).forEach(new Processor<PyFunction>() {
|
||||
@Override
|
||||
public boolean process(PyFunction pyFunction) {
|
||||
allRenames.put(pyFunction, newName);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class A:
|
||||
def f<caret>oo(self): pass
|
||||
|
||||
class B(A):
|
||||
def foo(self): pass
|
||||
@@ -0,0 +1,5 @@
|
||||
class A:
|
||||
def qu(self): pass
|
||||
|
||||
class B(A):
|
||||
def qu(self): pass
|
||||
@@ -8,13 +8,11 @@ import com.jetbrains.python.fixtures.PyLightFixtureTestCase;
|
||||
* @author yole
|
||||
*/
|
||||
public class PyRenameTest extends PyLightFixtureTestCase {
|
||||
public void testRenameField() throws Exception { // PY-457
|
||||
myFixture.configureByFile("refactoring/rename/" + getTestName(true) + ".py");
|
||||
myFixture.renameElementAtCaret("qu");
|
||||
myFixture.checkResultByFile("refactoring/rename/" + getTestName(true) + "_after.py");
|
||||
public void testRenameField() { // PY-457
|
||||
doTest("qu");
|
||||
}
|
||||
|
||||
public void testSearchInStrings() throws Exception { // PY-670
|
||||
public void testSearchInStrings() { // PY-670
|
||||
myFixture.configureByFile("refactoring/rename/" + getTestName(true) + ".py");
|
||||
final PsiElement element = TargetElementUtilBase.findTargetElement(myFixture.getEditor(), TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED |
|
||||
TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
|
||||
@@ -23,15 +21,21 @@ public class PyRenameTest extends PyLightFixtureTestCase {
|
||||
myFixture.checkResultByFile("refactoring/rename/" + getTestName(true) + "_after.py");
|
||||
}
|
||||
|
||||
public void testRenameParameter() throws Exception { // PY-385
|
||||
myFixture.configureByFile("refactoring/rename/" + getTestName(true) + ".py");
|
||||
myFixture.renameElementAtCaret("qu");
|
||||
myFixture.checkResultByFile("refactoring/rename/" + getTestName(true) + "_after.py");
|
||||
public void testRenameParameter() { // PY-385
|
||||
doTest("qu");
|
||||
}
|
||||
|
||||
public void testRenameMultipleDefinitionsLocal() throws Exception { // PY-727
|
||||
public void testRenameMultipleDefinitionsLocal() { // PY-727
|
||||
doTest("qu");
|
||||
}
|
||||
|
||||
public void testRenameInheritors() {
|
||||
doTest("qu");
|
||||
}
|
||||
|
||||
private void doTest(final String newName) {
|
||||
myFixture.configureByFile("refactoring/rename/" + getTestName(true) + ".py");
|
||||
myFixture.renameElementAtCaret("qu");
|
||||
myFixture.renameElementAtCaret(newName);
|
||||
myFixture.checkResultByFile("refactoring/rename/" + getTestName(true) + "_after.py");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user