Resolve to locally defined 'global' variables (PY-5617)

This commit is contained in:
Andrey Vlasovskikh
2012-03-21 19:41:16 +04:00
parent 2e59b1b534
commit ff640ae52d
5 changed files with 41 additions and 13 deletions

View File

@@ -120,7 +120,19 @@ public class ScopeImpl implements Scope {
if (myNamedElements == null) {
collectDeclarations();
}
return myNamedElements.get(name);
final PsiNamedElement element = myNamedElements.get(name);
if (element != null) {
return element;
}
if (isGlobal(name)) {
for (Scope scope : myNestedScopes) {
final PsiNamedElement global = scope.getNamedElement(name);
if (global != null) {
return global;
}
}
}
return null;
}
@NotNull
@@ -150,7 +162,9 @@ public class ScopeImpl implements Scope {
@Override
public void visitPyGlobalStatement(PyGlobalStatement node) {
for (PyTargetExpression expression : node.getGlobals()) {
globals.add(expression.getReferencedName());
final String name = expression.getReferencedName();
globals.add(name);
namedElements.put(name, expression);
}
super.visitPyGlobalStatement(node);
}

View File

@@ -216,13 +216,16 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
if (definers.isEmpty()) {
final ScopeOwner originalOwner = ScopeUtil.getResolveScopeOwner(realContext);
final ScopeOwner owner = ScopeUtil.getScopeOwner(uexpr);
if (owner != null && owner == originalOwner) {
final ResolveResultList latest = resolveToLatestDefs(owner, myElement, referencedName);
if (!latest.isEmpty()) {
return latest;
}
if (!isCythonLevel(myElement)) {
uexpr = null;
if (owner != null) {
final Scope scope = ControlFlowCache.getScope(owner);
if (owner == originalOwner && !scope.isGlobal(referencedName)) {
final ResolveResultList latest = resolveToLatestDefs(owner, myElement, referencedName);
if (!latest.isEmpty()) {
return latest;
}
if (!isCythonLevel(myElement)) {
uexpr = null;
}
}
}
}

View File

@@ -39,10 +39,6 @@ public class GlobalAnnotator extends PyAnnotator {
if (paramNames.contains(expr_name)) {
holder.createErrorAnnotation(expr.getTextRange(), PyBundle.message("ANN.$0.both.global.and.param", expr_name));
}
PsiElement resolvedElement = expr.getReference().resolve();
if (resolvedElement != null && resolvedElement != expr && PsiTreeUtil.isAncestor(function, resolvedElement, true)) {
getHolder().createWarningAnnotation(expr.getTextRange(),PyBundle.message("ANN.$0.both.global.and.param", expr_name));
}
}
}
}

View File

@@ -0,0 +1,8 @@
def f():
global xx
xx = 1
f()
print(x<ref>x)

View File

@@ -150,6 +150,13 @@ public class PyResolveTest extends PyResolveTestCase {
assertTrue(targetElement.getParent() instanceof PyAssignmentStatement);
}
public void testGlobalDefinedLocally() {
final PsiElement element = resolve();
assertInstanceOf(element, PyTargetExpression.class);
final PsiElement parent = element.getParent();
assertInstanceOf(parent, PyAssignmentStatement.class);
}
public void testLambda() {
PsiElement targetElement = resolve();
assertTrue(targetElement instanceof PyNamedParameter);