diff --git a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/scopeanalysis/AbstractScopeAnalyzerVisitor.java b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/scopeanalysis/AbstractScopeAnalyzerVisitor.java index cd3a7ef8b5..0d0e104009 100644 --- a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/scopeanalysis/AbstractScopeAnalyzerVisitor.java +++ b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/scopeanalysis/AbstractScopeAnalyzerVisitor.java @@ -299,7 +299,7 @@ public Object visitClassDef(ClassDef node) throws Exception { * used so that the token is added to the names to ignore... */ protected void addToNamesToIgnore(SimpleNode node, boolean finishClassScope, boolean checkBuiltins) { - SourceToken token = AbstractVisitor.makeToken(node, "", nature, this.current); + final SourceToken token = AbstractVisitor.makeToken(node, "", nature, this.current); if (checkBuiltins) { if (checkCurrentScopeForAssignmentsToBuiltins()) { @@ -311,9 +311,9 @@ protected void addToNamesToIgnore(SimpleNode node, boolean finishClassScope, boo } } - ScopeItems currScopeItems = scope.getCurrScopeItems(); + final ScopeItems currScopeItems = scope.getCurrScopeItems(); - Found found = new Found(token, token, scope.getCurrScopeId(), scope.getCurrScopeItems()); + final Found found = new Found(token, token, scope.getCurrScopeId(), scope.getCurrScopeItems()); org.python.pydev.shared_core.structure.Tuple tup = new org.python.pydev.shared_core.structure.Tuple( token, found); addToNamesToIgnore(token, currScopeItems, tup); @@ -324,22 +324,25 @@ protected void addToNamesToIgnore(SimpleNode node, boolean finishClassScope, boo Found n = it.next(); GenAndTok single = n.getSingle(); - int foundScopeType = single.scopeFound.getScopeType(); + final ScopeItems scopeFound = single.scopeFound; + final int foundScopeType = scopeFound.getScopeType(); + final int globalClassOrMethodScopeType = scopeFound.globalClassOrMethodScopeType; //ok, if we are in a scope method, we may not get things that were defined in a class scope. - if (((foundScopeType & Scope.ACCEPTED_METHOD_AND_LAMBDA) != 0) + if (((globalClassOrMethodScopeType & Scope.ACCEPTED_METHOD_AND_LAMBDA) != 0) && scope.getCurrScopeItems().getScopeType() == Scope.SCOPE_TYPE_CLASS) { continue; } - IToken tok = single.tok; - String firstPart = FullRepIterable.getFirstPart(tok.getRepresentation()); + final IToken tok = single.tok; + final String firstPart = FullRepIterable.getFirstPart(tok.getRepresentation()); if (firstPart.equals(token.getRepresentation())) { //found match in names to ignore... - if (finishClassScope && scope.getCurrScopeId() < single.scopeFound.getScopeId() + if (finishClassScope && scope.getCurrScopeId() < scopeFound.getScopeId() && !(foundScopeType == Scope.SCOPE_TYPE_ANNOTATION_STR) - && (!futureAnnotationsImported && foundScopeType == Scope.SCOPE_TYPE_CLASS || - (!futureAnnotationsImported && foundScopeType == Scope.SCOPE_TYPE_ANNOTATION))) { + && (!futureAnnotationsImported && (globalClassOrMethodScopeType == Scope.SCOPE_TYPE_CLASS + || foundScopeType == Scope.SCOPE_TYPE_ANNOTATION) + && (globalClassOrMethodScopeType & Scope.ACCEPTED_METHOD_AND_LAMBDA) == 0)) { it.remove(); onAddUndefinedMessage(tok, found); } else { diff --git a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/Scope.java b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/Scope.java index 644ff67336..3c5611ad29 100644 --- a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/Scope.java +++ b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/Scope.java @@ -86,6 +86,14 @@ public final class Scope implements Iterable { public static final int ACCEPTED_ALL_SCOPES = SCOPE_TYPE_GLOBAL | SCOPE_TYPE_METHOD | SCOPE_TYPE_LAMBDA | SCOPE_TYPE_CLASS | SCOPE_TYPE_LIST_COMP | SCOPE_TYPE_ANNOTATION | SCOPE_TYPE_ANNOTATION_STR; + /** + * The scopes which may be considered a parent (because when we're in an annotation or list comp, etc + * we still want to know whether we're in the global/method/lamba/class scope). + */ + public static final int ACCEPTED_GLOBAL_CLASS_OR_METHOD_SCOPE_TYPES = SCOPE_TYPE_GLOBAL | SCOPE_TYPE_METHOD + | SCOPE_TYPE_LAMBDA + | SCOPE_TYPE_CLASS; + /** * Constant defining that method and lambda are accepted. */ @@ -306,9 +314,23 @@ public void startScope(int scopeType) { this.visitingStrTypeAnnotation += 1; } int newId = getNewId(); - scope.push(new ScopeItems(newId, scopeType)); - scopeId.push(newId); + int globalClassOrMethodScopeType = 0; + if ((scopeType & ACCEPTED_GLOBAL_CLASS_OR_METHOD_SCOPE_TYPES) != 0) { + globalClassOrMethodScopeType = scopeType; + + } else { + for (int i = scope.size() - 1; i >= 0; i--) { + ScopeItems parent = scope.get(i); + int found = parent.getScopeType(); + if ((found & ACCEPTED_GLOBAL_CLASS_OR_METHOD_SCOPE_TYPES) != 0) { + globalClassOrMethodScopeType = found; + break; + } + } + } + scope.push(new ScopeItems(newId, scopeType, globalClassOrMethodScopeType)); + scopeId.push(newId); } public int getCurrScopeId() { diff --git a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/ScopeItems.java b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/ScopeItems.java index e6f82538b5..92bafa766c 100644 --- a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/ScopeItems.java +++ b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/ScopeItems.java @@ -81,16 +81,18 @@ public ScopeItems.TryExceptInfo getTryExceptImportError() { /** * Stack for names that should not generate warnings, such as builtins, method names, etc. */ - public Map> namesToIgnore = new HashMap>(); + public final Map> namesToIgnore = new HashMap>(); public int ifSubScope = 0; - public FastStack tryExceptSubScope = new FastStack(10); - private int scopeId; - private int scopeType; + public final FastStack tryExceptSubScope = new FastStack(10); + private final int scopeId; + private final int scopeType; + public final int globalClassOrMethodScopeType; - public ScopeItems(int scopeId, int scopeType) { + public ScopeItems(int scopeId, int scopeType, int globalClassOrMethodScopeType) { this.scopeId = scopeId; this.scopeType = scopeType; + this.globalClassOrMethodScopeType = globalClassOrMethodScopeType; } public Found getLastAppearance(String rep) { diff --git a/plugins/org.python.pydev/tests_analysis/com/python/pydev/analysis/OccurrencesAnalyzerPy310Test.java b/plugins/org.python.pydev/tests_analysis/com/python/pydev/analysis/OccurrencesAnalyzerPy310Test.java index 396f417ad9..bf7e41db87 100644 --- a/plugins/org.python.pydev/tests_analysis/com/python/pydev/analysis/OccurrencesAnalyzerPy310Test.java +++ b/plugins/org.python.pydev/tests_analysis/com/python/pydev/analysis/OccurrencesAnalyzerPy310Test.java @@ -568,6 +568,17 @@ public void testTypingInfoInStrOk() { checkNoError(); } + public void testTypingInfoOk() { + doc = new Document("" + + "def method(): \n" + + " a: SomeClass\n" + + " print(a)\n" + + "class SomeClass:\n" + + " pass \n" + + ""); + checkNoError(); + } + public void testTypingInfoInStrOk2() { doc = new Document("" + ""