mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
Resolve to locally defined 'global' variables (PY-5617)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
8
python/testData/resolve/GlobalDefinedLocally.py
Normal file
8
python/testData/resolve/GlobalDefinedLocally.py
Normal file
@@ -0,0 +1,8 @@
|
||||
def f():
|
||||
global xx
|
||||
xx = 1
|
||||
|
||||
f()
|
||||
|
||||
print(x<ref>x)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user