Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cb5ff36

Browse files
committed
More tests, handling nested generics
1 parent a772870 commit cb5ff36

File tree

2 files changed

+62
-23
lines changed

2 files changed

+62
-23
lines changed

src/Analysis/Ast/Impl/Analyzer/Evaluation/ExpressionEval.Generics.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,19 @@ private IReadOnlyList<IMember> EvaluateIndex(IndexExpression expr) {
138138

139139
/// <summary>
140140
/// Given an index argument, will try and resolve it to a forward reference, e.g
141+
/// Forward references are types declared in quotes, e.g 'int' is equivalent to type int
141142
///
142143
/// List['str'] => List[str]
144+
/// 'A[int]' => A[int]
143145
/// </summary>
144146
private IMember GetValueFromForwardRef(IMember index) {
145-
index.TryGetConstant(out string memberName);
146-
if (string.IsNullOrEmpty(memberName)) {
147+
index.TryGetConstant(out string forwardRefStr);
148+
if (string.IsNullOrEmpty(forwardRefStr)) {
147149
return null;
148150
}
149151

150-
return LookupNameInScopes(memberName, out var _, out var _, LookupOptions.Normal);
152+
var forwardRefExpr = TryCreateExpression(forwardRefStr);
153+
return GetValueFromExpression(forwardRefExpr);
151154
}
152155

153156
private IReadOnlyList<IMember> EvaluateCallArgs(CallExpression expr) {

src/Analysis/Ast/Test/GenericsTests.cs

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,32 +1079,34 @@ def get(self) -> _T:
10791079
public async Task GenericForwardRef() {
10801080
const string code = @"
10811081
from typing import List, Dict
1082+
1083+
x = List['A']
1084+
y = Dict['A', 'B']
1085+
10821086
class A:
10831087
def test(self) -> int:
10841088
pass
10851089
class B:
10861090
def test(self) -> int:
10871091
pass
1088-
l = List['A']
1089-
d = Dict['A', 'B']
1092+
z = List['A']
1093+
w = Dict['A', 'B']
10901094
";
10911095
var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X);
1092-
analysis.Should().HaveVariable("l")
1096+
analysis.Should().HaveVariable("x")
10931097
.Which.Should().HaveType("List[A]");
1094-
analysis.Should().HaveVariable("d")
1098+
analysis.Should().HaveVariable("y")
1099+
.Which.Should().HaveType("Dict[A, B]");
1100+
analysis.Should().HaveVariable("z")
1101+
.Which.Should().HaveType("List[A]");
1102+
analysis.Should().HaveVariable("w")
10951103
.Which.Should().HaveType("Dict[A, B]");
10961104
}
10971105

10981106
[TestMethod, Priority(0)]
10991107
public async Task GenericBuiltinTypeForwardRef() {
11001108
const string code = @"
11011109
from typing import List, Dict
1102-
class A:
1103-
def test(self) -> int:
1104-
pass
1105-
class B:
1106-
def test(self) -> int:
1107-
pass
11081110
l = List['int']
11091111
d = Dict['float', 'str']
11101112
";
@@ -1119,15 +1121,16 @@ def test(self) -> int:
11191121
public async Task GenericListForwardRef() {
11201122
const string code = @"
11211123
from typing import List, Dict
1122-
class A: ...
1123-
class B: ...
11241124
11251125
def test() -> 'List[A]':
11261126
pass
11271127
11281128
def test1() -> 'Dict[A, B]':
11291129
pass
11301130
1131+
class A: ...
1132+
class B: ...
1133+
11311134
x = test()
11321135
y = test1()
11331136
";
@@ -1147,23 +1150,55 @@ public async Task GenericClassForwardRef() {
11471150
T = TypeVar('T')
11481151
K = TypeVar('K')
11491152
1150-
class A(Generic[T]):
1151-
def test(self) -> T:
1152-
pass
1153-
11541153
class B(Generic[T, K]):
11551154
def test(self) -> T:
11561155
pass
11571156
11581157
def test1(self) -> K:
11591158
pass
11601159
1160+
b = B['A', 'A']()
1161+
y = b.test()
1162+
z = b.test1()
1163+
1164+
class A(Generic[T]):
1165+
def test(self) -> T:
1166+
pass
1167+
";
1168+
var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X);
1169+
analysis.Should().HaveVariable("b")
1170+
.Which.Should().HaveType("B[A, A]");
1171+
analysis.Should().HaveVariable("y")
1172+
.Which.Should().HaveType("A");
1173+
analysis.Should().HaveVariable("z")
1174+
.Which.Should().HaveType("A");
1175+
}
1176+
1177+
[TestMethod, Priority(0)]
1178+
public async Task GenericClassForwardRefNestedGenerics() {
1179+
const string code = @"
1180+
from typing import Generic, TypeVar
1181+
1182+
T = TypeVar('T')
1183+
K = TypeVar('K')
1184+
11611185
a = A['B']()
11621186
x = a.test()
11631187
1164-
b = B['A', 'A']()
1188+
b = B['A[int]', 'A[str]']()
11651189
y = b.test()
11661190
z = b.test1()
1191+
1192+
class A(Generic[T]):
1193+
def test(self) -> T:
1194+
pass
1195+
1196+
class B(Generic[T, K]):
1197+
def test(self) -> T:
1198+
pass
1199+
1200+
def test1(self) -> K:
1201+
pass
11671202
";
11681203
var analysis = await GetAnalysisAsync(code, PythonVersions.LatestAvailable3X);
11691204
analysis.Should().HaveVariable("a")
@@ -1172,13 +1207,14 @@ def test1(self) -> K:
11721207
.Which.Should().HaveType("B");
11731208

11741209
analysis.Should().HaveVariable("b")
1175-
.Which.Should().HaveType("B[A, A]");
1210+
.Which.Should().HaveType("B[A[int], A[str]]");
11761211
analysis.Should().HaveVariable("y")
1177-
.Which.Should().HaveType("A");
1212+
.Which.Should().HaveType("A[int]");
11781213
analysis.Should().HaveVariable("z")
1179-
.Which.Should().HaveType("A");
1214+
.Which.Should().HaveType("A[str]");
11801215
}
11811216

1217+
11821218
[TestMethod, Priority(0)]
11831219
public async Task GenericFunctionArguments() {
11841220
const string code = @"

0 commit comments

Comments
 (0)