Skip to content

Commit

Permalink
Don't try to follow strings for type definitions in typing.Literal wi…
Browse files Browse the repository at this point in the history
…th strings.
  • Loading branch information
fabioz committed Oct 1, 2023
1 parent b04031d commit 243ff88
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ private void visitListCompGenerators(ListComp node, List<exprType> eltsToVisit)
* @param node
*/
protected void startScope(int newScopeType, SimpleNode node) {
scope.startScope(newScopeType);
scope.startScope(newScopeType, node);
onAfterStartScope(newScopeType, node);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

0 comments on commit 243ff88

Please sign in to comment.