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 dea3262307..e5fe60de14 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 @@ -1104,7 +1104,7 @@ private void visitListCompGenerators(ListComp node, List eltsToVisit) * @param node */ protected void startScope(int newScopeType, SimpleNode node) { - scope.startScope(newScopeType); + scope.startScope(newScopeType, node); onAfterStartScope(newScopeType, node); } diff --git a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/OccurrencesVisitor.java b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/OccurrencesVisitor.java index 6a68abf26a..be7f33516b 100644 --- a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/OccurrencesVisitor.java +++ b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/visitors/OccurrencesVisitor.java @@ -58,6 +58,7 @@ import org.python.pydev.parser.jython.ast.decoratorsType; import org.python.pydev.parser.jython.ast.match_caseType; import org.python.pydev.parser.jython.ast.str_typeType; +import org.python.pydev.parser.visitors.NodeUtils; import org.python.pydev.shared_core.callbacks.ICallbackListener; import org.python.pydev.shared_core.model.ErrorDescription; import org.python.pydev.shared_core.structure.FastStack; @@ -251,33 +252,40 @@ public Object visitAssign(Assign node) throws Exception { @Override public Object visitStr(Str node) throws Exception { if (this.scope.isVisitingTypeAnnotation()) { - String s = node.s; - IGrammar grammar = PyParser.createGrammar(true, this.nature.getGrammarVersion(), s.toCharArray()); - Throwable errorOnParsing = null; - int startInternalStrColOffset = getStrOffset(node); - try { - SimpleNode typingNode = grammar.file_input(); - errorOnParsing = grammar.getErrorOnParsing(); - if (errorOnParsing == null) { - new FixLinesVisitor(node.beginLine - 1, node.beginColumn + startInternalStrColOffset - 1) - .traverse(typingNode); - this.scope.startScope(Scope.SCOPE_TYPE_ANNOTATION_STR); - try { - this.traverse(typingNode); - } finally { - this.scope.endScope(); + String fullRepresentationString = NodeUtils.getFullRepresentationString(scope.currentScope().scopeNode); + + // If a string is found inside a typing.Literal, don't parse it for type definitions + // (i.e.: those are considered constants in this case and not class references as in + // generic classes). + if (!"typing.Literal".equals(fullRepresentationString)) { + String s = node.s; + IGrammar grammar = PyParser.createGrammar(true, this.nature.getGrammarVersion(), s.toCharArray()); + Throwable errorOnParsing = null; + int startInternalStrColOffset = getStrOffset(node); + try { + SimpleNode typingNode = grammar.file_input(); + errorOnParsing = grammar.getErrorOnParsing(); + if (errorOnParsing == null) { + new FixLinesVisitor(node.beginLine - 1, node.beginColumn + startInternalStrColOffset - 1) + .traverse(typingNode); + this.scope.startScope(Scope.SCOPE_TYPE_ANNOTATION_STR, node); + try { + this.traverse(typingNode); + } finally { + this.scope.endScope(); + } + } + } catch (Exception e) { + if (errorOnParsing == null) { + errorOnParsing = e; } } - } catch (Exception e) { - if (errorOnParsing == null) { - errorOnParsing = e; + if (errorOnParsing != null) { + IDocument doc = new Document(s); + reportParserError(node, node.beginLine, node.beginColumn + startInternalStrColOffset, doc, + errorOnParsing); } } - if (errorOnParsing != null) { - IDocument doc = new Document(s); - reportParserError(node, node.beginLine, node.beginColumn + startInternalStrColOffset, doc, - errorOnParsing); - } } if (node.fstring && (node.fstring_nodes == null || node.fstring_nodes.length == 0)) { // Note: if fstring_nodes have been pre-processed (i.e.: in cython parsing), we don't parse 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 70101b7337..4ee4d47c71 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 @@ -19,6 +19,7 @@ import org.python.pydev.core.IToken; import org.python.pydev.core.IterTokenEntry; import org.python.pydev.core.TokensList; +import org.python.pydev.parser.jython.SimpleNode; import org.python.pydev.parser.jython.ast.If; import org.python.pydev.parser.jython.ast.TryExcept; import org.python.pydev.shared_core.string.FastStringBuffer; @@ -312,8 +313,9 @@ public ScopeItems getCurrScopeItems() { /** * initializes a new scope + * @param node */ - public void startScope(int scopeType) { + public void startScope(int scopeType, SimpleNode node) { if (scopeType == SCOPE_TYPE_ANNOTATION) { this.visitingTypeAnnotation += 1; } else if (scopeType == SCOPE_TYPE_ANNOTATION_STR) { @@ -335,7 +337,7 @@ public void startScope(int scopeType) { } } } - scope.push(new ScopeItems(newId, scopeType, globalClassOrMethodScopeType)); + scope.push(new ScopeItems(newId, scopeType, globalClassOrMethodScopeType, node)); scopeId.push(newId); } 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 3c2c88c380..7ff5b1f0f7 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 @@ -17,6 +17,7 @@ import java.util.Map; import org.python.pydev.core.IToken; +import org.python.pydev.parser.jython.SimpleNode; import org.python.pydev.parser.jython.ast.If; import org.python.pydev.parser.jython.ast.TryExcept; import org.python.pydev.parser.jython.ast.excepthandlerType; @@ -91,11 +92,13 @@ public ScopeItems.TryExceptInfo getTryExceptImportError() { private final int scopeId; private final int scopeType; public final int globalClassOrMethodScopeType; + public final SimpleNode scopeNode; - public ScopeItems(int scopeId, int scopeType, int globalClassOrMethodScopeType) { + public ScopeItems(int scopeId, int scopeType, int globalClassOrMethodScopeType, SimpleNode node) { this.scopeId = scopeId; this.scopeType = scopeType; this.globalClassOrMethodScopeType = globalClassOrMethodScopeType; + this.scopeNode = node; } 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 757e6a63b1..f91e43ef59 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 @@ -699,4 +699,12 @@ public void testTypingInTypeCheckingUndefinedWithoutFutureImport() { assertEquals(1, messages.length); assertEquals(7, messages[0].getStartLine(doc)); } + + public void testTypingWithLiterals() { + doc = new Document("import typing\n" + + "def method() -> typing.Literal['a', 'b']:\n" + + " return 'a'\n" + + ""); + checkNoError(); + } }