Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

Commit 4afc1ef

Browse files
author
Mikhail Arkhipov
authored
Resolve issue when specific types shared data after creation off generic template (#600)
* Buildable * Part 14 * First passing test * Simplify configuration * Style * Fix test and move code to folders * Builtins import * Fix #470 * Fluents * Add search path * Import analysis, part I * Simplify builtins handling * Remove IMember * Handle import specific * More tests * Add typeshed * Renames * Make sure lazy modules are loaded * Renames * Move/rename * Rework importing * Derivation rework * Part 2 * Part 3 * Buildable * Module members * Async walk * Imports test pass * Remove lazy types * Fix from import * Stubs * Double overloads * Fix datetime test * Couple more tests + fluents * Few more tests * Additionl test + union type * Built-in scrape tests * Full stdlib scrape test * Complete async AST walker * Conditional defines test + variable loc cleanup * More stub tests Fix stub loading for packages (port from DDG) Split walker into multiple files * Add some (broken mostly) tests from DDG * Move document tests * Function arg eval, part I * Instance/factory * Builds * Test fixes * Fix static and instance call eval * More tests * More ported tests * Specialize builtin functions * Make walkers common and handle nested functions * Moar tests * Parser fixes + more tests * Handle negative numbers * Fix null ref * Basic list support * Few more list tests * Basic iterators * Support __iter__ * Iterators * Fix couple of tests * Add decorator test * Generics, part I * Generics, part 2 * Generics, part 3 * Basic TypeVar test * Typings, part 4 * Fix test * Generics, part 6 * Generics, part 7 * More tests (failing) * Forward ref fixes * Reorg * Improve symbol resolution + test fixes * Test fixes * Dictionary, part I * Part 11 * Fix test * Tests * Tests * More dict work * List ctor * Skip some tests for now * Fix iterators * Tuple slicing * Polish type comparo in return types * Add Mapping and tests * Add Iterable * Fix typo * Add Iterator[T] + test * Simplify typing types * Class reduction * Fix tests * Test fix * Handle 'with' statement * Handle try-except * Class method inheritance + NewType * Container types * Containers test * Tests * Handle generic type alias * Named tuple * Global/non-local * Handle tuples in for Handle custom iterators * Basic generator * Any/AnyStr * Test fixes * Type/Optional/etc handling * Proper doc population * Tests + range * Argument match * Basic argset and diagnostics * Argset tests * Exclude WIP * Exclude WIP * Arg eval * Arg match, part 2 * Tests and generic arg comparisons * Function eval with arguments * Baselines * Fix test * Undo AST formatting change and update baseline * LS cleanup 1 * Fix list ctor argument unpacking * Cleanup 2 * Builds * Partial completions * Partial * Partial * Simple test * Tests * Basic startup * Clean up a bit * Remove debug code * Port formatter tests * Fix tokenizer crash * Async fixes * Hover * Basic hover * Adjust expression options * Basic signature help * Fix class/instance * Update test * Fix builtin creation exception * Fix tests * Actually provide declared module * Completion test (partial) * Undo * Fix null await Fix override completions + test * Exports filtering Prevent augmenting imported types * Filter variables & exports * Ported tests * Test fixes * More ported tests * Fix exception completions * Import completions * Scope completions * With completions * Test fixes * WIP * Test fix * Better arg match * Temp disable WIP * First cut * Fix type leak * WIP * Remove ConfigureAwait and handle canceled and failed in the analysis notifications * WIP * Generic class base * Generic forward reference resolution * Suppress completion in strings + test * Prevent recursion on generic resolution Better match arguments * Handle call expression in generics * Relax condition as it happens in tensorflow * Fix typeshed version search Make writing cached modules async Fix module doc fetching * Hover tests * Fix prom import hover * Hover tests * Synchronize test cache writing * First cut * Test * Fixes * Add tests for os.path Null ref fix * Fix cache check * Improve resolution of builtins and typing in stubs * Merge tests * Add ntst for requests * Handle typeshed better * Fix custom stub handling * Better sync * Move files * Fix parameter locations * Hover improvement * PEP hints * One more test for PEP hints * Better handle hover over import as * Text based generic constraints * Handle with better with generic stubs * Undo debug * Handle non-binary open() Temporary fix 'with' handler since we haven't specialized IO/TextIO/BinaryIO yet. * Output syntax errors * Properly clear * - Fix async issue with analysis completion - Clean up diagnostics service interface - Use real DS in tests * Use proper scope when analyzing module * Severity mapping and reporting * Add publishing test Add NSubstitute Move all services to the same namespace. * Unused var * Test forced publish on close * Fix typo * Update test framework * Import location * Remove incorrect reference * Diagnostic severity mapping test Fix post-mortem earlier PR comment * Minor fixes * Better handle return types in classes created from templates. * Move interface to the main class part * Dynamic return type * Add hover and signature tests * Baseline update * Flicker reduction * - Correct reported unresolved import name - Add tests * PR feedback * Resolve merge issues * Fix completion doc + test * Restore formatting * Bunch of null checks * Fix generic base classes Add tests and changes to couple more cases * PR feedback
1 parent 0b458d6 commit 4afc1ef

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+637
-240
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ public async Task<IMember> GetValueFromFunctionTypeAsync(IPythonFunctionType fn,
157157
if (instanceType == null || fn.DeclaringType == null || fn.IsSpecialized ||
158158
instanceType.IsSpecialized || fn.DeclaringType.IsSpecialized ||
159159
instanceType.Equals(fn.DeclaringType) ||
160-
fn.IsStub || !string.IsNullOrEmpty(fn.Overloads[args.OverloadIndex].ReturnDocumentation)) {
160+
fn.IsStub || !string.IsNullOrEmpty(fn.Overloads[args.OverloadIndex].GetReturnDocumentation(null))) {
161161

162162
if (fn.IsSpecialized && fn is PythonFunctionType ft) {
163163
foreach (var module in ft.Dependencies) {
@@ -218,7 +218,7 @@ private async Task<ArgumentSet> FindOverloadAsync(IPythonFunctionType fn, IPytho
218218
var result = noErrorsMatches.Any()
219219
? noErrorsMatches.FirstOrDefault(args => IsMatch(args, fn.Overloads[args.OverloadIndex].Parameters))
220220
: null;
221-
221+
222222
// Optimistically pick the best available.
223223
return result ?? orderedSets.FirstOrDefault();
224224
}

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public async Task<IMember> GetValueFromIndexAsync(IndexExpression expr, Cancella
3131
}
3232

3333
var target = await GetValueFromExpressionAsync(expr.Target, cancellationToken);
34-
// Try generics
34+
// Try generics first since this may be an expression like Dict[int, str]
3535
var result = await GetValueFromGenericAsync(target, expr, cancellationToken);
3636
if (result != null) {
3737
return result;
@@ -48,7 +48,9 @@ public async Task<IMember> GetValueFromIndexAsync(IndexExpression expr, Cancella
4848
instance = new PythonInstance(type);
4949
}
5050
var index = await GetValueFromExpressionAsync(expr.Index, cancellationToken);
51-
return type.Index(instance, index);
51+
if (index != null) {
52+
return type.Index(instance, index);
53+
}
5254
}
5355

5456
return UnknownType;
@@ -93,7 +95,7 @@ public async Task<IMember> GetValueFromSetAsync(SetExpression expression, Cancel
9395

9496
public async Task<IMember> GetValueFromGeneratorAsync(GeneratorExpression expression, CancellationToken cancellationToken = default) {
9597
var iter = expression.Iterators.OfType<ComprehensionFor>().FirstOrDefault();
96-
if(iter != null) {
98+
if (iter != null) {
9799
return await GetValueFromExpressionAsync(iter.List, cancellationToken) ?? UnknownType;
98100
}
99101
return UnknownType;

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

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313
// See the Apache Version 2.0 License for specific language governing
1414
// permissions and limitations under the License.
1515

16-
using System;
1716
using System.Collections.Generic;
1817
using System.Linq;
1918
using System.Threading;
2019
using System.Threading.Tasks;
2120
using Microsoft.Python.Analysis.Specializations.Typing;
2221
using Microsoft.Python.Analysis.Specializations.Typing.Types;
2322
using Microsoft.Python.Analysis.Types;
23+
using Microsoft.Python.Analysis.Values;
2424
using Microsoft.Python.Core;
2525
using Microsoft.Python.Parsing.Ast;
2626

@@ -47,8 +47,10 @@ private async Task<IMember> GetValueFromGenericAsync(IMember target, Expression
4747
// rather than specific type instantiation as in List[str].
4848

4949
IPythonType[] specificTypes;
50+
var returnInstance = false;
5051
switch (expr) {
51-
case IndexExpression indexExpr: {
52+
// Indexing returns type as from A[int]
53+
case IndexExpression indexExpr:
5254
// Generic[T1, T2, ...] or A[type]()
5355
var indices = await EvaluateIndexAsync(indexExpr, cancellationToken);
5456
// See which ones are generic parameters as defined by TypeVar()
@@ -66,6 +68,7 @@ private async Task<IMember> GetValueFromGenericAsync(IMember target, Expression
6668
if (genericTypeArgs.Length > 0 && genericTypeArgs.Length != indices.Count) {
6769
// TODO: report that some type arguments are not declared with TypeVar.
6870
}
71+
6972
if (specificTypes.Length > 0 && specificTypes.Length != indices.Count) {
7073
// TODO: report that arguments are not specific types or are not declared.
7174
}
@@ -84,20 +87,21 @@ private async Task<IMember> GetValueFromGenericAsync(IMember target, Expression
8487

8588
if (specificTypes.Length > 0) {
8689
// If target is a generic type and indexes are specific types, create specific class
87-
return await gt.CreateSpecificTypeAsync(new ArgumentSet(specificTypes), Module, GetLoc(expr), cancellationToken);
90+
return gt.CreateSpecificType(new ArgumentSet(specificTypes), Module, GetLoc(expr));
8891
} else {
8992
// TODO: report too few type arguments for the Generic[].
9093
return UnknownType;
9194
}
9295
}
93-
9496
break;
95-
}
97+
9698
case CallExpression callExpr:
9799
// Alternative instantiation:
98100
// class A(Generic[T]): ...
99101
// x = A(1234)
100-
specificTypes = (await EvaluateICallArgsAsync(callExpr, cancellationToken)).Select(x => x.GetPythonType()).ToArray();
102+
specificTypes = (await EvaluateCallArgsAsync(callExpr, cancellationToken)).Select(x => x.GetPythonType()).ToArray();
103+
// Callable returns instance (as opposed to a type with index expression)
104+
returnInstance = true;
101105
break;
102106

103107
default:
@@ -109,9 +113,12 @@ private async Task<IMember> GetValueFromGenericAsync(IMember target, Expression
109113
// as we resolve classes on demand. Therefore we don't know if class is generic
110114
// or not at the time of the PythonClassType creation.
111115
// TODO: figure out if we could make GenericClassType: PythonClassType, IGenericType instead.
112-
return target is PythonClassType cls
113-
? await cls.CreateSpecificTypeAsync(new ArgumentSet(specificTypes), Module, GetLoc(expr), cancellationToken)
114-
: null;
116+
if (target is PythonClassType cls) {
117+
var location = GetLoc(expr);
118+
var type = cls.CreateSpecificType(new ArgumentSet(specificTypes), Module, location);
119+
return returnInstance ? new PythonInstance(type, GetLoc(expr)) : (IMember)type;
120+
}
121+
return null;
115122
}
116123

117124
private async Task<IReadOnlyList<IMember>> EvaluateIndexAsync(IndexExpression expr, CancellationToken cancellationToken = default) {
@@ -124,16 +131,16 @@ private async Task<IReadOnlyList<IMember>> EvaluateIndexAsync(IndexExpression ex
124131
}
125132
} else {
126133
var index = await GetValueFromExpressionAsync(expr.Index, cancellationToken);
127-
indices.Add(index);
134+
indices.Add(index ?? UnknownType);
128135
}
129136
return indices;
130137
}
131138

132-
private async Task<IReadOnlyList<IMember>> EvaluateICallArgsAsync(CallExpression expr, CancellationToken cancellationToken = default) {
139+
private async Task<IReadOnlyList<IMember>> EvaluateCallArgsAsync(CallExpression expr, CancellationToken cancellationToken = default) {
133140
var indices = new List<IMember>();
134141
cancellationToken.ThrowIfCancellationRequested();
135-
foreach (var e in expr.Args.Select(a => a.Expression).ExcludeDefault()) {
136-
var value = await GetValueFromExpressionAsync(e, cancellationToken);
142+
foreach (var e in expr.Args.Select(a => a.Expression)) {
143+
var value = await GetValueFromExpressionAsync(e, cancellationToken) ?? UnknownType;
137144
indices.Add(value);
138145
}
139146
return indices;

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ private async Task<IMember> GetValueFromUnaryOpAsync(UnaryExpression expr, Cance
3939
case PythonOperator.Pos:
4040
return await GetValueFromUnaryOpAsync(expr, "__pos__", cancellationToken);
4141
}
42-
return null;
42+
return UnknownType;
4343
}
4444

4545
private async Task<IMember> GetValueFromUnaryOpAsync(UnaryExpression expr, string op, CancellationToken cancellationToken = default) {
@@ -57,7 +57,7 @@ private async Task<IMember> GetValueFromUnaryOpAsync(UnaryExpression expr, strin
5757
? new PythonConstant(-value, c.Type, GetLoc(expr))
5858
: instance;
5959
}
60-
return null;
60+
return UnknownType;
6161
}
6262

6363
private async Task<IMember> GetValueFromBinaryOpAsync(Expression expr, CancellationToken cancellationToken = default) {
@@ -87,8 +87,8 @@ private async Task<IMember> GetValueFromBinaryOpAsync(Expression expr, Cancellat
8787
return Interpreter.GetBuiltinType(BuiltinTypeId.Bool);
8888
}
8989

90-
var left = await GetValueFromExpressionAsync(binop.Left, cancellationToken);
91-
var right = await GetValueFromExpressionAsync(binop.Right, cancellationToken);
90+
var left = await GetValueFromExpressionAsync(binop.Left, cancellationToken) ?? UnknownType;
91+
var right = await GetValueFromExpressionAsync(binop.Right, cancellationToken) ?? UnknownType;
9292

9393
switch (binop.Operator) {
9494
case PythonOperator.Divide:

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ private async Task<IMember> GetValueFromMemberAsync(MemberExpression expr, Cance
192192
}
193193

194194
instance = instance ?? m as IPythonInstance;
195-
var type = m.GetPythonType(); // Try inner type
195+
var type = m?.GetPythonType(); // Try inner type
196196
var value = type?.GetMember(expr.Name);
197197

198198
// Class type GetMember returns a type. However, class members are
@@ -226,7 +226,7 @@ private async Task<IMember> GetValueFromConditionalAsync(ConditionalExpression e
226226
var trueValue = await GetValueFromExpressionAsync(expr.TrueExpression, cancellationToken);
227227
var falseValue = await GetValueFromExpressionAsync(expr.FalseExpression, cancellationToken);
228228

229-
return trueValue ?? falseValue;
229+
return trueValue ?? falseValue ?? UnknownType;
230230
}
231231

232232
public void ReportDiagnostics(Uri documentUri, DiagnosticsEntry entry) {

src/Analysis/Ast/Impl/Analyzer/Handlers/AssignmentHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public async Task HandleAssignmentAsync(AssignmentStatement node, CancellationTo
3232
return;
3333
}
3434

35-
var value = await Eval.GetValueFromExpressionAsync(node.Right, cancellationToken);
35+
var value = await Eval.GetValueFromExpressionAsync(node.Right, cancellationToken) ?? Eval.UnknownType;
3636
// Check PEP hint first
3737
var valueType = Eval.GetTypeFromPepHint(node.Right);
3838
if (valueType != null) {

src/Analysis/Ast/Impl/Analyzer/Handlers/TryExceptHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public async Task<bool> HandleTryExceptAsync(TryStatement node, CancellationToke
2828
foreach (var handler in node.Handlers.MaybeEnumerate()) {
2929
if (handler.Test != null && handler.Target is NameExpression nex) {
3030
var value = await Eval.GetValueFromExpressionAsync(handler.Test, cancellationToken);
31-
Eval.DeclareVariable(nex.Name, value, VariableSource.Declaration, nex);
31+
Eval.DeclareVariable(nex.Name, value ?? Eval.UnknownType, VariableSource.Declaration, nex);
3232
}
3333
await handler.Body.WalkAsync(Walker, cancellationToken);
3434
}

src/Analysis/Ast/Impl/Analyzer/Handlers/TupleExpressionHandler.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
using Microsoft.Python.Parsing.Ast;
2323

2424
namespace Microsoft.Python.Analysis.Analyzer.Handlers {
25-
internal sealed class TupleExpressionHandler: StatementHandler {
26-
public TupleExpressionHandler(AnalysisWalker walker): base(walker) { }
25+
internal sealed class TupleExpressionHandler : StatementHandler {
26+
public TupleExpressionHandler(AnalysisWalker walker) : base(walker) { }
2727

2828
public async Task HandleTupleAssignmentAsync(TupleExpression lhs, Expression rhs, IMember value, CancellationToken cancellationToken = default) {
2929
cancellationToken.ThrowIfCancellationRequested();
@@ -34,9 +34,7 @@ public async Task HandleTupleAssignmentAsync(TupleExpression lhs, Expression rhs
3434
for (var i = 0; i < Math.Min(names.Length, returnedExpressions.Length); i++) {
3535
if (returnedExpressions[i] != null && !string.IsNullOrEmpty(names[i])) {
3636
var v = await Eval.GetValueFromExpressionAsync(returnedExpressions[i], cancellationToken);
37-
if (v != null) {
38-
Eval.DeclareVariable(names[i], v, VariableSource.Declaration, returnedExpressions[i]);
39-
}
37+
Eval.DeclareVariable(names[i], v ?? Eval.UnknownType, VariableSource.Declaration, returnedExpressions[i]);
4038
}
4139
}
4240
return;

src/Analysis/Ast/Impl/Analyzer/Handlers/WithHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public async Task HandleWithAsync(WithStatement node, CancellationToken cancella
2828
cancellationToken.ThrowIfCancellationRequested();
2929
foreach (var item in node.Items.Where(x => x.Variable != null)) {
3030
var contextManager = await Eval.GetValueFromExpressionAsync(item.ContextManager, cancellationToken);
31-
var cmType = contextManager.GetPythonType();
31+
var cmType = contextManager?.GetPythonType();
3232

3333
var enter = cmType?.GetMember(node.IsAsync ? @"__aenter__" : @"__enter__")?.GetPythonType<IPythonFunctionType>();
3434
if (enter != null) {

src/Analysis/Ast/Impl/Analyzer/Symbols/FunctionEvaluator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public override async Task EvaluateAsync(CancellationToken cancellationToken = d
8787
}
8888

8989
public override async Task<bool> WalkAsync(AssignmentStatement node, CancellationToken cancellationToken = default) {
90-
var value = await Eval.GetValueFromExpressionAsync(node.Right, cancellationToken);
90+
var value = await Eval.GetValueFromExpressionAsync(node.Right, cancellationToken) ?? Eval.UnknownType;
9191

9292
foreach (var lhs in node.Left) {
9393
switch (lhs) {
@@ -180,7 +180,7 @@ private async Task DeclareParameterAsync(Parameter p, int index, ParameterInfo p
180180
} else {
181181
var defaultValue = await Eval.GetValueFromExpressionAsync(p.DefaultValue, cancellationToken) ?? Eval.UnknownType;
182182

183-
paramType = defaultValue.GetPythonType();
183+
paramType = defaultValue?.GetPythonType();
184184
if (!paramType.IsUnknown()) {
185185
pi?.SetDefaultValueType(paramType);
186186
}

src/Analysis/Ast/Impl/Extensions/AnalysisExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ private static PythonFunctionType GetOrCreateFunction(this IDocumentAnalysis ana
5454
// 'type()' in code is a function call, not a type class instantiation.
5555
if (!(analysis.GlobalScope.Variables[name]?.Value is PythonFunctionType f)) {
5656
f = PythonFunctionType.ForSpecialization(name, analysis.Document);
57-
f.AddOverload(new PythonFunctionOverload(name, analysis.Document, LocationInfo.Empty));
57+
f.AddOverload(new PythonFunctionOverload(name, analysis.Document, _ => LocationInfo.Empty));
5858
analysis.GlobalScope.DeclareVariable(name, f, VariableSource.Declaration, LocationInfo.Empty);
5959
}
6060
return f;

src/Analysis/Ast/Impl/Extensions/MemberExtensions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
using Microsoft.Python.Analysis.Specializations.Typing;
1717
using Microsoft.Python.Analysis.Types;
1818
using Microsoft.Python.Analysis.Values;
19-
using Microsoft.Python.Parsing.Ast;
2019

2120
namespace Microsoft.Python.Analysis {
2221
public static class MemberExtensions {

src/Analysis/Ast/Impl/Specializations/Specialized.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ namespace Microsoft.Python.Analysis.Specializations {
1919
internal static class Specialized {
2020
public static IPythonPropertyType Property(string name, IPythonModule declaringModule, IPythonType declaringType, IMember returnValue) {
2121
var prop = new PythonPropertyType(name, declaringModule, declaringType, false, LocationInfo.Empty);
22-
var o = new PythonFunctionOverload(prop.Name, declaringModule, LocationInfo.Empty);
22+
var o = new PythonFunctionOverload(prop.Name, declaringModule, _ => LocationInfo.Empty);
2323
o.AddReturnValue(returnValue);
2424
prop.AddOverload(o);
2525
return prop;
2626
}
2727

2828
public static IPythonFunctionType Function(string name, IPythonModule declaringModule, IPythonType declaringType, string documentation, IMember returnValue) {
2929
var prop = new PythonFunctionType(name, declaringModule, declaringType, documentation, LocationInfo.Empty);
30-
var o = new PythonFunctionOverload(prop.Name, declaringModule, LocationInfo.Empty);
30+
var o = new PythonFunctionOverload(prop.Name, declaringModule, _ => LocationInfo.Empty);
3131
o.AddReturnValue(returnValue);
3232
prop.AddOverload(o);
3333
return prop;

src/Analysis/Ast/Impl/Specializations/Typing/Definitions/IGenericClassBaseType.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414
// permissions and limitations under the License.
1515

1616
using System.Collections.Generic;
17+
using Microsoft.Python.Analysis.Types;
1718

1819
namespace Microsoft.Python.Analysis.Specializations.Typing {
1920
/// <summary>
2021
/// Represents Generic[T1, T2, ...]. Used as a base class to generic classes.
2122
/// </summary>
22-
public interface IGenericClassBaseType {
23+
public interface IGenericClassBaseType: IPythonType {
2324
IReadOnlyList<IGenericTypeParameter> TypeArgs { get; }
2425
}
2526
}

src/Analysis/Ast/Impl/Specializations/Typing/Types/GenericClassBaseType.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
using Microsoft.Python.Analysis.Types;
1818

1919
namespace Microsoft.Python.Analysis.Specializations.Typing.Types {
20+
/// <summary>
21+
/// Represents Generic[T1, T2, ...]
22+
/// </summary>
2023
internal sealed class GenericClassBaseType: PythonClassType, IGenericClassBaseType {
2124
internal GenericClassBaseType(IReadOnlyList<IGenericTypeParameter> typeArgs, IPythonModule declaringModule, LocationInfo location)
2225
: base("Generic", declaringModule, location) {

0 commit comments

Comments
 (0)