diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceImpl.java index ed268b3ffc96..975099ed2e26 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceImpl.java @@ -166,17 +166,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference // Use real context here to enable correct completion and resolve in case of PyExpressionCodeFragment!!! final PsiElement realContext = PyPsiUtils.getRealContext(myElement); - PsiElement roof = null; - if (PyUtil.isClassPrivateName(referencedName)) { - // a class-private name; limited by either class or this file - PsiElement one = myElement; - do { - one = PyUtil.getConcealingParent(one); - } - while (one instanceof PyFunction); - if (one instanceof PyClass) roof = one; - } - if (roof == null) roof = realContext.getContainingFile(); + PsiElement roof = findResolveRoof(referencedName, realContext); PsiElement uexpr = PyResolveUtil.treeCrawlUp(processor, false, realContext, roof); if ((uexpr != null)) { if ((uexpr instanceof PyClass)) { @@ -216,9 +206,10 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference uexpr = bfile.getElementNamed(referencedName); } } - if (uexpr == null) { + if (uexpr == null && !(myElement instanceof PyTargetExpression)) { //uexpr = PyResolveUtil.resolveOffContext(this); - uexpr = PyUtil.turnDirIntoInit(PyResolveUtil.scanOuterContext(new ResolveProcessor(referencedName), realContext)); + final PsiElement outerContextElement = PyResolveUtil.scanOuterContext(new ResolveProcessor(referencedName), realContext); + uexpr = PyUtil.turnDirIntoInit(outerContextElement); } if (uexpr != null) { ret.add(new ImportedResolveResult(uexpr, getRate(uexpr), processor.getDefiners())); @@ -227,6 +218,28 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference return ret; } + private PsiElement findResolveRoof(String referencedName, PsiElement realContext) { + if (PyUtil.isClassPrivateName(referencedName)) { + // a class-private name; limited by either class or this file + PsiElement one = myElement; + do { + one = PyUtil.getConcealingParent(one); + } + while (one instanceof PyFunction); + if (one instanceof PyClass) { + return one; + } + } + + if (myElement instanceof PyTargetExpression) { + final ScopeOwner scopeOwner = PsiTreeUtil.getParentOfType(myElement, ScopeOwner.class); + if (scopeOwner != null && !scopeOwner.getScope().isGlobal(myElement.getName())) { + return scopeOwner; + } + } + return realContext.getContainingFile(); + } + private boolean isSuperClassExpression(PyClass cls) { if (myElement.getContainingFile() != cls.getContainingFile()) { // quick check to avoid unnecessary tree loading return false; diff --git a/python/testData/findUsages/NonGlobalUsages.py b/python/testData/findUsages/NonGlobalUsages.py new file mode 100644 index 000000000000..42e4b87b3c8c --- /dev/null +++ b/python/testData/findUsages/NonGlobalUsages.py @@ -0,0 +1,4 @@ +a = 0 +def b(): + a = 1 + print a diff --git a/python/testSrc/com/jetbrains/python/PyFindUsagesTest.java b/python/testSrc/com/jetbrains/python/PyFindUsagesTest.java index 156849f2521e..9aa18685cfb5 100644 --- a/python/testSrc/com/jetbrains/python/PyFindUsagesTest.java +++ b/python/testSrc/com/jetbrains/python/PyFindUsagesTest.java @@ -43,4 +43,9 @@ public class PyFindUsagesTest extends PyLightFixtureTestCase { final Collection usages = myFixture.testFindUsages("findUsages/GlobalUsages2.py"); assertEquals(3, usages.size()); } + + public void testNonGlobalUsages() { // PY-1179 + final Collection usages = myFixture.testFindUsages("findUsages/NonGlobalUsages.py"); + assertEquals(1, usages.size()); + } }