correct isReferenceTo() for variables used in nested functions (part of PY-3118)

This commit is contained in:
Dmitry Jemerov
2011-03-21 19:43:18 +01:00
parent bbe17ef421
commit 45abd45806
4 changed files with 40 additions and 3 deletions
@@ -1,6 +1,5 @@
package com.jetbrains.python.codeInsight.controlflow;
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
import com.jetbrains.python.psi.PyElement;
/**
@@ -314,8 +314,27 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
if (element instanceof PyParameter || element instanceof PyTargetExpression) {
PsiElement ourContainer = PsiTreeUtil.getParentOfType(getElement(), PsiNamedElement.class, PyLambdaExpression.class, PyComprehensionElement.class);
PsiElement theirContainer = PsiTreeUtil.getParentOfType(element, PsiNamedElement.class, PyLambdaExpression.class, PyComprehensionElement.class);
if (ourContainer != null && ourContainer == theirContainer) {
return true;
if (ourContainer != null) {
if (ourContainer == theirContainer) {
return true;
}
if (PsiTreeUtil.isAncestor(theirContainer, ourContainer, true)) {
ScopeOwner ourScopeOwner = PsiTreeUtil.getParentOfType(getElement(), ScopeOwner.class);
ScopeOwner theirScopeOwner = PsiTreeUtil.getParentOfType(element, ScopeOwner.class);
if (ourScopeOwner != theirScopeOwner) {
boolean shadowsName = false;
while(ourScopeOwner != theirScopeOwner && ourScopeOwner != null) {
if (ControlFlowCache.getScope(ourScopeOwner).containsDeclaration(elementName)) {
shadowsName = true;
break;
}
ourScopeOwner = PsiTreeUtil.getParentOfType(ourScopeOwner, ScopeOwner.class);
}
if (!shadowsName) {
return true;
}
}
}
}
}
final PsiElement resolveResult = resolve();
@@ -0,0 +1,10 @@
xyzzy = False
def foo():
if xyzzy:
b<caret>ar = {}
else:
bar = []
def x():
for y in enumerate(bar):
pass
@@ -64,6 +64,15 @@ public class PyFindUsagesTest extends PyLightFixtureTestCase {
assertUsages(usages, "import <caret>re", "<caret>re.compile");
}
public void testNestedFunctions() { // PY-3118
final Collection<UsageInfo> usages = doTest();
assertUsages(usages, "<caret>bar = {}", "<caret>bar = []", "enumerate(<caret>bar)");
}
private Collection<UsageInfo> doTest() {
return myFixture.testFindUsages("findUsages/" + getTestName(false) + ".py");
}
private void assertUsages(Collection<UsageInfo> usages, String... usageTexts) {
assertEquals(usageTexts.length, usages.size());
List<UsageInfo> sortedUsages = new ArrayList<UsageInfo>(usages);