Skip to content

Commit

Permalink
Fixes in semantic analysis to better determine if strings in annotati…
Browse files Browse the repository at this point in the history
…ons should be checked for symbols or not.
  • Loading branch information
fabioz committed Jan 20, 2024
1 parent 0267bdd commit c4bbadd
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
package com.python.pydev.analysis.visitors;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.Document;
Expand Down Expand Up @@ -53,6 +55,7 @@
import org.python.pydev.parser.jython.ast.Raise;
import org.python.pydev.parser.jython.ast.Return;
import org.python.pydev.parser.jython.ast.Str;
import org.python.pydev.parser.jython.ast.Subscript;
import org.python.pydev.parser.jython.ast.While;
import org.python.pydev.parser.jython.ast.Yield;
import org.python.pydev.parser.jython.ast.decoratorsType;
Expand Down Expand Up @@ -249,15 +252,34 @@ public Object visitAssign(Assign node) throws Exception {
return r;
}

private static Set<String> CONTAINER_CLASSES = new HashSet<String>();
static {
CONTAINER_CLASSES.add("list");
CONTAINER_CLASSES.add("List");
CONTAINER_CLASSES.add("typing.List");
CONTAINER_CLASSES.add("tuple");
CONTAINER_CLASSES.add("Tuple");
CONTAINER_CLASSES.add("typing.Tuple");
CONTAINER_CLASSES.add("set");
CONTAINER_CLASSES.add("Set");
CONTAINER_CLASSES.add("typing.Set");
// This means that it's just a str directly in the type annotation.
CONTAINER_CLASSES.add("str");
}

@Override
public Object visitStr(Str node) throws Exception {
if (this.scope.isVisitingTypeAnnotation()) {
String fullRepresentationString = NodeUtils.getFullRepresentationString(scope.currentScope().scopeNode);
String fullRepresentationString = null;

// 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) && !"Literal".equals(fullRepresentationString)) {
if (this.scope.subscripts.size() > 0) {
Subscript lastSubscript = this.scope.subscripts.peek();
fullRepresentationString = NodeUtils.getFullRepresentationString(lastSubscript.value);
}
if (fullRepresentationString == null || CONTAINER_CLASSES.contains(fullRepresentationString)) {
String s = node.s;
IGrammar grammar = PyParser.createGrammar(true, this.nature.getGrammarVersion(), s.toCharArray());
Throwable errorOnParsing = null;
Expand Down Expand Up @@ -453,6 +475,16 @@ public Object visitLambda(Lambda node) throws Exception {
return ret;
}

@Override
public Object visitSubscript(Subscript node) throws Exception {
this.scope.pushSubscript(node);
try {
return super.visitSubscript(node);
} finally {
this.scope.popSubscript(node);
}
}

@Override
public void traverse(SimpleNode node) throws Exception {
if (node instanceof If) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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.Subscript;
import org.python.pydev.parser.jython.ast.TryExcept;
import org.python.pydev.shared_core.string.FastStringBuffer;
import org.python.pydev.shared_core.structure.FastStack;
Expand Down Expand Up @@ -522,4 +523,15 @@ public ScopeItems getPrevScopeItems() {
return scope.get(scope.size() - 2);
}

public final FastStack<Subscript> subscripts = new FastStack<>(3);

public void pushSubscript(Subscript node) {
subscripts.push(node);

}

public void popSubscript(Subscript node) {
subscripts.pop();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ public static List<File> listCondaEnvironments(File condaExecutable) {
null,
encoding);
Log.logInfo(output.o1);
if (output.o2 != null && output.o2.length() > 0) {
Log.logInfo("STDERR when listing conda environments:\n" + output.o2);

}
JsonObject jsonOutput = JsonValue.readFrom(output.o1).asObject();
JsonArray envs = jsonOutput.get("envs").asArray();
Set<File> set = new HashSet<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,32 @@ public void testTypingWithLiterals() {
checkNoError();
}

public void testTypingWithLiteralsShowError() {
doc = new Document("def method() -> 'err':\n"
+ " return 'a'\n"
+ "");
checkError("Undefined variable: err");
}

public void testTypingWithLiterals2() {
doc = new Document("from typing import Annotated, List\n"
+ "class Param:\n"
+ " pass\n"
+ "\n"
+ "def method() -> Annotated[List[str],Param(description=\"\"\"Provides a list (i.e.: ['output.txt', 'gen/my.pdf'])\"\"\")]:\n"
+ " return 'a'\n"
+ "");
checkNoError();
}

public void testTypingWithLiterals3() {
doc = new Document("from typing import Tuple, Literal\n"
+ "def method() -> Tuple[Literal['line', 'call', 'return'], ...]:\n"
+ " return ()\n"
+ "");
checkNoError();
}

public void testOverload() {
doc = new Document("from typing import overload\n"
+ "\n"
Expand Down

0 comments on commit c4bbadd

Please sign in to comment.