From a7668df48fc5e6c2bb6e70d103fe71ece70b2e1b Mon Sep 17 00:00:00 2001 From: Mikhail Khorkov Date: Fri, 10 Jul 2020 16:35:06 +0700 Subject: [PATCH] PY-11858 Fix rename functon parameter along with decorator argument If docorated function has a parameter and the decorator has an argument with the same name as the parameter then we must not rename the argument in case of renaming the parameter. GitOrigin-RevId: ebc5dcf7448080e2762004a2779cd06700c042a8 --- .../psi/impl/references/PyReferenceImpl.java | 2 +- .../rename/renameParameterWithDecorator.py | 22 +++++++++++++++++++ .../renameParameterWithDecorator_after.py | 22 +++++++++++++++++++ .../python/refactoring/PyRenameTest.java | 4 ++++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 python/testData/refactoring/rename/renameParameterWithDecorator.py create mode 100644 python/testData/refactoring/rename/renameParameterWithDecorator_after.py diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java index 8011fbdeee16..3d55548ff32d 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -561,7 +561,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference final PsiElement ourContainer = findContainer(getElement()); final PsiElement theirContainer = findContainer(element); if (ourContainer != null) { - if (ourContainer == theirContainer) { + if (ourContainer == theirContainer && ourScopeOwner == theirScopeOwner) { return true; } if (PsiTreeUtil.isAncestor(theirContainer, ourContainer, true)) { diff --git a/python/testData/refactoring/rename/renameParameterWithDecorator.py b/python/testData/refactoring/rename/renameParameterWithDecorator.py new file mode 100644 index 000000000000..ce00c3238c8d --- /dev/null +++ b/python/testData/refactoring/rename/renameParameterWithDecorator.py @@ -0,0 +1,22 @@ +from functools import wraps + + +def d(x): + def dec(f): + @wraps(f) + def wrapper(*args, **kwargs): + print(f'x = {x}') + return f(*args, **kwargs) + return wrapper + return dec + + +class C: + foo = 0 + + @d(foo) # 2. This is renamed either but it shouldn't + def f(self, foo): # 1. Rename this 'foo' to 'bar' + print(foo) + + +C().f(1) \ No newline at end of file diff --git a/python/testData/refactoring/rename/renameParameterWithDecorator_after.py b/python/testData/refactoring/rename/renameParameterWithDecorator_after.py new file mode 100644 index 000000000000..2281bc46349d --- /dev/null +++ b/python/testData/refactoring/rename/renameParameterWithDecorator_after.py @@ -0,0 +1,22 @@ +from functools import wraps + + +def d(x): + def dec(f): + @wraps(f) + def wrapper(*args, **kwargs): + print(f'x = {x}') + return f(*args, **kwargs) + return wrapper + return dec + + +class C: + foo = 0 + + @d(foo) # 2. This is renamed either but it shouldn't + def f(self, bar): # 1. Rename this 'foo' to 'bar' + print(bar) + + +C().f(1) \ 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 ed476a3a8fa6..63a6b7094992 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyRenameTest.java @@ -43,6 +43,10 @@ public class PyRenameTest extends PyTestCase { doTest("qu"); } + public void testRenameParameterWithDecorator() { // PY-11858 + doTest("bar"); + } + public void testRenameMultipleDefinitionsLocal() { // PY-727 doTest("qu"); }