mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
PY-46099 PY-47633 Don't remember usages in non-physical copies of methods in Pull Up/Down
PSI element copies exists in special non-physical files (DummyHolders), and usually references in them cannot be resolved. It led both to exceptions, when the rest of the code insight didn't expect resolve to happen in files other than PyFile (PY-46099), and situations when we failed to resolve a usage in a copy and restore the corresponding import (PY-47633). Switching to processing original declarations also revealed a problem with inserting imports -- we might have tried to insert impossible imports for non-top-level symbols, such as class attributes and methods. Now, these are ignored. GitOrigin-RevId: 6816078596a2c0aced7045a80828b7e83ebee8c0
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f9f34cc7f9
commit
f76600603e
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
@@ -233,10 +234,14 @@ public class PyPsiRefactoringUtil {
|
||||
containingQName = qname.removeLastComponent();
|
||||
importedName = qname.getLastComponent();
|
||||
}
|
||||
else {
|
||||
// See PyClassRefactoringUtil.DynamicNamedElement
|
||||
else if (PyUtil.isTopLevel(element) || element instanceof LightElement) {
|
||||
containingQName = qname;
|
||||
importedName = getOriginalName(element);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
final AddImportHelper.ImportPriority priority = AddImportHelper.getImportPriority(anchor, elementSource);
|
||||
if (preferFromImport && !containingQName.getComponents().isEmpty() || !importingModuleOrPackage) {
|
||||
return AddImportHelper.addOrUpdateFromImportStatement(file, containingQName.toString(), importedName, asName, priority, anchor);
|
||||
|
||||
@@ -105,18 +105,6 @@ public final class PyClassRefactoringUtil {
|
||||
return currentValue.getText();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PyFunction> copyMethods(Collection<? extends PyFunction> methods, PyClass superClass, boolean skipIfExist ) {
|
||||
if (methods.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
for (final PsiElement e : methods) {
|
||||
rememberNamedReferences(e);
|
||||
}
|
||||
final PyFunction[] elements = methods.toArray(PyFunction.EMPTY_ARRAY);
|
||||
return addMethods(superClass, skipIfExist, elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds methods to class.
|
||||
*
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.jetbrains.NotNullPredicate;
|
||||
import com.jetbrains.python.PyNames;
|
||||
@@ -127,20 +128,22 @@ class MethodsManager extends MembersManager<PyFunction> {
|
||||
* @param skipIfExist skip (do not add) if method already exists
|
||||
* @return newly added methods
|
||||
*/
|
||||
static List<PyElement> moveMethods(final PyClass from, final Collection<? extends PyFunction> methodsToMove, final boolean skipIfExist, final PyClass... to) {
|
||||
final List<PyElement> result = new ArrayList<>();
|
||||
for (final PyClass destClass : to) {
|
||||
//We move copies here because there may be several destinations
|
||||
final List<PyFunction> copies = new ArrayList<>(methodsToMove.size());
|
||||
for (final PyFunction element : methodsToMove) {
|
||||
final PyFunction newMethod = (PyFunction)element.copy();
|
||||
copies.add(newMethod);
|
||||
}
|
||||
static List<PyElement> moveMethods(@NotNull PyClass from,
|
||||
@NotNull Collection<? extends PyFunction> methodsToMove,
|
||||
boolean skipIfExist,
|
||||
PyClass @NotNull... to) {
|
||||
if (methodsToMove.isEmpty() || to.length == 0) return Collections.emptyList();
|
||||
|
||||
result.addAll(PyClassRefactoringUtil.copyMethods(copies, destClass, skipIfExist));
|
||||
final List<PyElement> result = new ArrayList<>();
|
||||
for (PyFunction method : methodsToMove) {
|
||||
PyClassRefactoringUtil.rememberNamedReferences(method);
|
||||
}
|
||||
for (PyClass destClass : to) {
|
||||
//We move copies here because there may be several destinations
|
||||
PyFunction[] copies = ContainerUtil.map2Array(methodsToMove, PyFunction.EMPTY_ARRAY, m -> (PyFunction)m.copy());
|
||||
result.addAll(PyClassRefactoringUtil.addMethods(destClass, skipIfExist, copies));
|
||||
}
|
||||
deleteElements(methodsToMove);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class MyClass:
|
||||
def method(self):
|
||||
pass
|
||||
@@ -1,3 +1,5 @@
|
||||
import logging
|
||||
|
||||
from SuperClass import SuperClass
|
||||
|
||||
|
||||
@@ -14,7 +16,7 @@ class AnyClass(SuperClass):
|
||||
|
||||
@new_property.setter
|
||||
def new_property(self, value):
|
||||
pass
|
||||
logging.debug("Setting %s", value)
|
||||
|
||||
@new_property.deleter
|
||||
def new_property(self):
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import logging
|
||||
|
||||
|
||||
class SuperClass(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -8,7 +11,7 @@ class SuperClass(object):
|
||||
|
||||
@new_property.setter
|
||||
def new_property(self, value):
|
||||
pass
|
||||
logging.debug("Setting %s", value)
|
||||
|
||||
@new_property.deleter
|
||||
def new_property(self):
|
||||
|
||||
@@ -16,15 +16,23 @@
|
||||
package com.jetbrains.python;
|
||||
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
|
||||
import com.jetbrains.python.codeInsight.imports.AddImportHelper.ImportPriority;
|
||||
import com.jetbrains.python.fixtures.PyResolveTestCase;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import com.jetbrains.python.refactoring.PyPsiRefactoringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static com.jetbrains.python.codeInsight.imports.AddImportHelper.ImportPriority.*;
|
||||
|
||||
/**
|
||||
@@ -191,6 +199,23 @@ public class PyAddImportTest extends PyTestCase {
|
||||
doTestRelativeImport("foo", "lib", "foo/bar/test");
|
||||
}
|
||||
|
||||
public void testImportForMethodCannotBeAdded() {
|
||||
String testName = getTestName(true);
|
||||
myFixture.copyDirectoryToProject(testName, "");
|
||||
myFixture.configureByFile("main.py");
|
||||
Collection<PyClass> pyClasses = PyClassNameIndex.find("MyClass", myFixture.getProject(), false);
|
||||
PyClass pyClass = assertOneElement(pyClasses);
|
||||
TypeEvalContext typeEvalContext = TypeEvalContext.codeAnalysis(myFixture.getProject(), myFixture.getFile());
|
||||
PyFunction method = pyClass.findMethodByName("method", false, typeEvalContext);
|
||||
assertNotNull(method);
|
||||
Ref<Boolean> inserted = Ref.create();
|
||||
WriteCommandAction.runWriteCommandAction(myFixture.getProject(), () -> {
|
||||
inserted.set(PyPsiRefactoringUtil.insertImport(myFixture.getFile(), method, null));
|
||||
});
|
||||
assertFalse(inserted.get());
|
||||
myFixture.checkResultByFile(testName + "/main.py");
|
||||
}
|
||||
|
||||
private void doAddOrUpdateFromImport(final String path, final String name, final ImportPriority priority) {
|
||||
myFixture.configureByFile(getTestName(true) + ".py");
|
||||
WriteCommandAction.runWriteCommandAction(myFixture.getProject(), () -> {
|
||||
|
||||
Reference in New Issue
Block a user