From 75b825c7710bd46bf0a8ac546d7ee508b5f8b453 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Tue, 9 Apr 2013 18:02:49 +0400 Subject: [PATCH] Set type eval origin for references in find usages if it isn't set (PY-9047) --- .../python/psi/types/TypeEvalContext.java | 9 +++++++-- .../impl/references/PyQualifiedReference.java | 16 +++++++++++++--- .../rename/renameSelfAndParameterAttribute.py | 17 +++++++++++++++++ .../renameSelfAndParameterAttribute_after.py | 17 +++++++++++++++++ .../python/refactoring/PyRenameTest.java | 5 +++++ 5 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 python/testData/refactoring/rename/renameSelfAndParameterAttribute.py create mode 100644 python/testData/refactoring/rename/renameSelfAndParameterAttribute_after.py diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java index ea5844ecc62b..e7790bec470d 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java @@ -24,7 +24,7 @@ public class TypeEvalContext { private final boolean myAllowStubToAST; private List myTrace; private String myTraceIndent = ""; - private final PsiFile myOrigin; + @Nullable private final PsiFile myOrigin; private final Map myEvaluated = new HashMap(); private final ThreadLocal> myEvaluating = new ThreadLocal>() { @@ -34,7 +34,7 @@ public class TypeEvalContext { } }; - private TypeEvalContext(boolean allowDataFlow, boolean allowStubToAST, PsiFile origin) { + private TypeEvalContext(boolean allowDataFlow, boolean allowStubToAST, @Nullable PsiFile origin) { myAllowDataFlow = allowDataFlow; myAllowStubToAST = allowStubToAST; myOrigin = origin; @@ -139,4 +139,9 @@ public class TypeEvalContext { public boolean maySwitchToAST(@NotNull StubBasedPsiElement element) { return myAllowStubToAST || (element.getStub() == null && (myOrigin == null || myOrigin == element.getContainingFile())); } + + @Nullable + public PsiFile getOrigin() { + return myOrigin; + } } diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java index d1453add6411..234f1ac9b099 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyQualifiedReference.java @@ -388,7 +388,16 @@ public class PyQualifiedReference extends PyReferenceImpl { } } } - for (ResolveResult result : copyWithoutImplicits().multiResolve(false)) { + PyResolveContext resolveContext = myContext.withoutImplicits(); + if (resolveContext.getTypeEvalContext().getOrigin() == null) { + final PsiFile containingFile = myElement.getContainingFile(); + if (containingFile instanceof StubBasedPsiElement) { + assert ((StubBasedPsiElement)containingFile).getStub() == null : "Stub origin for type eval context in isReferenceTo()"; + } + final TypeEvalContext context = TypeEvalContext.fastStubOnly(containingFile); + resolveContext = resolveContext.withTypeEvalContext(context); + } + for (ResolveResult result : copyWithResolveContext(resolveContext).multiResolve(false)) { LOG.assertTrue(!(result instanceof ImplicitResolveResult)); PsiElement resolveResult = result.getElement(); if (isResolvedToResult(element, resolveResult)) { @@ -399,8 +408,9 @@ public class PyQualifiedReference extends PyReferenceImpl { return false; } - protected PyQualifiedReference copyWithoutImplicits() { - return new PyQualifiedReference(myElement, myContext.withoutImplicits()); + @NotNull + protected PyQualifiedReference copyWithResolveContext(PyResolveContext context) { + return new PyQualifiedReference(myElement, context); } private boolean isResolvedToResult(PsiElement element, PsiElement resolveResult) { diff --git a/python/testData/refactoring/rename/renameSelfAndParameterAttribute.py b/python/testData/refactoring/rename/renameSelfAndParameterAttribute.py new file mode 100644 index 000000000000..8ceb06cafdd7 --- /dev/null +++ b/python/testData/refactoring/rename/renameSelfAndParameterAttribute.py @@ -0,0 +1,17 @@ +class С: + def __init__(self, x=None): + if x is None: + self.foo = { + 'A': { + 'x': 0, + 'y': 0, + }, + } + else: # init was given the previous state + assert isinstance(x, С) + self.foo = { + 'A': { + 'x': x.foo['A']['x'], + 'y': x.foo['A']['y'], + }, + } \ No newline at end of file diff --git a/python/testData/refactoring/rename/renameSelfAndParameterAttribute_after.py b/python/testData/refactoring/rename/renameSelfAndParameterAttribute_after.py new file mode 100644 index 000000000000..95c195d89679 --- /dev/null +++ b/python/testData/refactoring/rename/renameSelfAndParameterAttribute_after.py @@ -0,0 +1,17 @@ +class С: + def __init__(self, x=None): + if x is None: + self.bar = { + 'A': { + 'x': 0, + 'y': 0, + }, + } + else: # init was given the previous state + assert isinstance(x, С) + self.bar = { + 'A': { + 'x': x.bar['A']['x'], + 'y': x.bar['A']['y'], + }, + } \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java index adcc14c880d9..cc49848f3162 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java @@ -168,6 +168,11 @@ public class PyRenameTest extends PyTestCase { doMultiFileTest("bar.py"); } + // PY-9047 + public void testRenameSelfAndParameterAttribute() { + doTest("bar"); + } + private void doRenameConflictTest(String newName, String expectedConflict) { myFixture.configureByFile(RENAME_DATA_PATH + getTestName(true) + ".py"); try {