Skip to content

Commit

Permalink
Fixed issue in code analysis related to bad scoping of type variable …
Browse files Browse the repository at this point in the history
…'def f[T](...)'. #PyDev-1268
  • Loading branch information
fabioz committed Feb 7, 2025
1 parent 3f7e1f2 commit 675597e
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -388,10 +388,6 @@ public Object visitFunctionDef(FunctionDef node) throws Exception {
addToNamesToIgnore(node, false, true);

AbstractScopeAnalyzerVisitor visitor = this;
// visit typed params. i.e.: def func[T](arg: t):
if (node.type_params != null) {
node.type_params.accept(visitor);
}

argumentsType args = node.args;

Expand Down Expand Up @@ -430,6 +426,11 @@ public Object visitFunctionDef(FunctionDef node) throws Exception {
scopeType = Scope.SCOPE_TYPE_ANNOTATION_STR;
}
startScope(scopeType, expr);
if (node.type_params != null) {
// Note: we visit type-params multiple times so that the types are available in
// all required scopes when checking the function (arguments, return and method body).
node.type_params.accept(visitor);
}
expr.accept(visitor);
endScope(expr);
}
Expand All @@ -443,6 +444,11 @@ public Object visitFunctionDef(FunctionDef node) throws Exception {
scopeType = Scope.SCOPE_TYPE_ANNOTATION_STR;
}
startScope(scopeType, node.returns);
if (node.type_params != null) {
// Note: we visit type-params multiple times so that the types are available in
// all required scopes when checking the function (arguments, return and method body).
node.type_params.accept(visitor);
}
node.returns.accept(visitor);
endScope(node.returns);
}
Expand All @@ -453,6 +459,13 @@ public Object visitFunctionDef(FunctionDef node) throws Exception {
startScope(Scope.SCOPE_TYPE_METHOD, node);
this.currentLocalScope.getScopeStack().push(node);

// visit typed params. i.e.: def func[T](arg: t):
if (node.type_params != null) {
// Note: we visit type-params multiple times so that the types are available in
// all required scopes when checking the function (arguments, return and method body).
node.type_params.accept(visitor);
}

scope.isInMethodDefinition = true;
//visit regular args
if (args.args != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.python.pydev.analysis;

import org.eclipse.jface.text.Document;
import org.python.pydev.ast.analysis.messages.IMessage;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.parser.jython.ParseException;

Expand Down Expand Up @@ -72,4 +73,27 @@ def method(arg: Point[int, int]):
checkNoError();
}

public void testTypeAlias2() {
doc = new Document("""
from typing import cast
class C:
def foo[T](self, x: T | None) -> T:
return cast(T, x)
""");
checkNoError();
}

public void testTypeAlias3() {
doc = new Document("""
from typing import cast
class C:
def foo[T](self, x: T = T): # The T as the default value is wrong, T is not defined!
return cast(T, x)
""");
IMessage[] messages = checkError("Undefined variable: T\n");
assertEquals(1, messages.length);
assertEquals(3, messages[0].getStartLine(doc));
assertEquals(29, messages[0].getStartCol(doc));
}

}

0 comments on commit 675597e

Please # to comment.