@zzzen/pyright-internal 1.2.0-dev.20230101 → 1.2.0-dev.20230108
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyzer/checker.js +17 -11
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/codeFlowEngine.js +19 -4
- package/dist/analyzer/codeFlowEngine.js.map +1 -1
- package/dist/analyzer/importResolver.d.ts +2 -1
- package/dist/analyzer/importResolver.js +18 -3
- package/dist/analyzer/importResolver.js.map +1 -1
- package/dist/analyzer/patternMatching.js +2 -2
- package/dist/analyzer/patternMatching.js.map +1 -1
- package/dist/analyzer/program.d.ts +1 -0
- package/dist/analyzer/program.js +41 -20
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/regions.js +14 -5
- package/dist/analyzer/regions.js.map +1 -1
- package/dist/analyzer/sourceFile.d.ts +1 -1
- package/dist/analyzer/sourceMapper.d.ts +2 -2
- package/dist/analyzer/sourceMapper.js +14 -5
- package/dist/analyzer/sourceMapper.js.map +1 -1
- package/dist/analyzer/typeCacheUtils.d.ts +1 -3
- package/dist/analyzer/typeCacheUtils.js +4 -8
- package/dist/analyzer/typeCacheUtils.js.map +1 -1
- package/dist/analyzer/typeDocStringUtils.d.ts +2 -1
- package/dist/analyzer/typeDocStringUtils.js +18 -7
- package/dist/analyzer/typeDocStringUtils.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +116 -110
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +2 -1
- package/dist/analyzer/typeGuards.d.ts +5 -1
- package/dist/analyzer/typeGuards.js +180 -43
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typeUtils.d.ts +1 -0
- package/dist/analyzer/typeUtils.js +5 -1
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/commands/quickActionCommand.js +1 -1
- package/dist/commands/quickActionCommand.js.map +1 -1
- package/dist/common/collectionUtils.d.ts +1 -0
- package/dist/common/collectionUtils.js +9 -1
- package/dist/common/collectionUtils.js.map +1 -1
- package/dist/common/textEditUtils.d.ts +3 -2
- package/dist/common/textEditUtils.js +11 -10
- package/dist/common/textEditUtils.js.map +1 -1
- package/dist/languageServerBase.d.ts +1 -1
- package/dist/languageService/completionProvider.d.ts +3 -0
- package/dist/languageService/completionProvider.js +212 -159
- package/dist/languageService/completionProvider.js.map +1 -1
- package/dist/languageService/hoverProvider.d.ts +0 -1
- package/dist/languageService/hoverProvider.js +7 -20
- package/dist/languageService/hoverProvider.js.map +1 -1
- package/dist/languageService/indentationUtils.js +1 -1
- package/dist/languageService/indentationUtils.js.map +1 -1
- package/dist/languageService/tooltipUtils.d.ts +5 -1
- package/dist/languageService/tooltipUtils.js +28 -4
- package/dist/languageService/tooltipUtils.js.map +1 -1
- package/dist/tests/completions.test.d.ts +1 -0
- package/dist/tests/completions.test.js +331 -0
- package/dist/tests/completions.test.js.map +1 -0
- package/dist/tests/filesystem.test.js +11 -0
- package/dist/tests/filesystem.test.js.map +1 -1
- package/dist/tests/harness/fourslash/testState.js +1 -1
- package/dist/tests/harness/fourslash/testState.js.map +1 -1
- package/dist/tests/harness/vfs/filesystem.d.ts +2 -2
- package/dist/tests/harness/vfs/filesystem.js +5 -1
- package/dist/tests/harness/vfs/filesystem.js.map +1 -1
- package/dist/tests/hoverProvider.test.d.ts +1 -0
- package/dist/tests/hoverProvider.test.js +247 -0
- package/dist/tests/hoverProvider.test.js.map +1 -0
- package/dist/tests/indentationUtils.ptvs.test.js +1 -1
- package/dist/tests/indentationUtils.test.js +4 -4
- package/dist/tests/typeEvaluator1.test.js +16 -0
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator2.test.js +5 -1
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator3.test.js +4 -0
- package/dist/tests/typeEvaluator3.test.js.map +1 -1
- package/dist/tests/typeEvaluator4.test.js +4 -0
- package/dist/tests/typeEvaluator4.test.js.map +1 -1
- package/dist/tests/typeEvaluator5.test.js +6 -0
- package/dist/tests/typeEvaluator5.test.js.map +1 -1
- package/dist/workspaceMap.js +1 -3
- package/dist/workspaceMap.js.map +1 -1
- package/package.json +6 -6
@@ -163,6 +163,7 @@ export interface PrintTypeOptions {
|
|
163
163
|
export interface TypeEvaluator {
|
164
164
|
runWithCancellationToken<T>(token: CancellationToken, callback: () => T): T;
|
165
165
|
getType: (node: ExpressionNode) => Type | undefined;
|
166
|
+
getTypeResult: (node: ExpressionNode) => TypeResult | undefined;
|
166
167
|
getCachedType: (node: ExpressionNode) => Type | undefined;
|
167
168
|
getTypeOfExpression: (node: ExpressionNode, flags?: EvaluatorFlags, expectedType?: Type) => TypeResult;
|
168
169
|
getTypeOfAnnotation: (node: ExpressionNode, options?: AnnotationTypeOptions) => Type;
|
@@ -237,7 +238,7 @@ export interface TypeEvaluator {
|
|
237
238
|
addUnusedCode: (node: ParseNode, textRange: TextRange) => void;
|
238
239
|
addUnreachableCode: (node: ParseNode, textRange: TextRange) => void;
|
239
240
|
addDeprecated: (message: string, node: ParseNode) => void;
|
240
|
-
addDiagnostic: (diagLevel: DiagnosticLevel, rule: string, message: string, node: ParseNode) => Diagnostic | undefined;
|
241
|
+
addDiagnostic: (diagLevel: DiagnosticLevel, rule: string, message: string, node: ParseNode, range?: TextRange) => Diagnostic | undefined;
|
241
242
|
addDiagnosticForTextRange: (fileInfo: AnalyzerFileInfo, diagLevel: DiagnosticLevel, rule: string, message: string, range: TextRange) => Diagnostic | undefined;
|
242
243
|
printType: (type: Type, options?: PrintTypeOptions) => string;
|
243
244
|
printFunctionParts: (type: FunctionType) => [string[], string];
|
@@ -1,7 +1,11 @@
|
|
1
1
|
import { ExpressionNode } from '../parser/parseNodes';
|
2
2
|
import { TypeEvaluator } from './typeEvaluatorTypes';
|
3
3
|
import { ClassType, Type } from './types';
|
4
|
-
export
|
4
|
+
export interface TypeNarrowingResult {
|
5
|
+
type: Type;
|
6
|
+
isIncomplete: boolean;
|
7
|
+
}
|
8
|
+
export declare type TypeNarrowingCallback = (type: Type) => TypeNarrowingResult | undefined;
|
5
9
|
export declare function getTypeNarrowingCallback(evaluator: TypeEvaluator, reference: ExpressionNode, testExpression: ExpressionNode, isPositiveTest: boolean, recursionCount?: number): TypeNarrowingCallback | undefined;
|
6
10
|
export declare function isIsinstanceFilterSuperclass(evaluator: TypeEvaluator, varType: ClassType, filterType: Type, concreteFilterType: ClassType, isInstanceCheck: boolean): boolean;
|
7
11
|
export declare function isIsinstanceFilterSubclass(evaluator: TypeEvaluator, varType: ClassType, filterType: Type, concreteFilterType: ClassType, isInstanceCheck: boolean): boolean;
|
@@ -72,7 +72,7 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
72
72
|
}
|
73
73
|
if (ParseTreeUtils.isMatchingExpression(reference, leftExpression)) {
|
74
74
|
return (type) => {
|
75
|
-
return narrowTypeForIsNone(evaluator, type, adjIsPositiveTest);
|
75
|
+
return { type: narrowTypeForIsNone(evaluator, type, adjIsPositiveTest), isIncomplete: false };
|
76
76
|
};
|
77
77
|
}
|
78
78
|
if (leftExpression.nodeType === 24 /* Index */ &&
|
@@ -87,11 +87,31 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
87
87
|
const indexValue = leftExpression.items[0].valueExpression.value;
|
88
88
|
if (typeof indexValue === 'number') {
|
89
89
|
return (type) => {
|
90
|
-
return
|
90
|
+
return {
|
91
|
+
type: narrowTupleTypeForIsNone(evaluator, type, adjIsPositiveTest, indexValue),
|
92
|
+
isIncomplete: false,
|
93
|
+
};
|
91
94
|
};
|
92
95
|
}
|
93
96
|
}
|
94
97
|
}
|
98
|
+
// Look for "X is ...", "X is not ...", "X == ...", and "X != ...".
|
99
|
+
if (testExpression.rightExpression.nodeType === 18 /* Ellipsis */) {
|
100
|
+
// Allow the LHS to be either a simple expression or an assignment
|
101
|
+
// expression that assigns to a simple name.
|
102
|
+
let leftExpression = testExpression.leftExpression;
|
103
|
+
if (leftExpression.nodeType === 4 /* AssignmentExpression */) {
|
104
|
+
leftExpression = leftExpression.name;
|
105
|
+
}
|
106
|
+
if (ParseTreeUtils.isMatchingExpression(reference, leftExpression)) {
|
107
|
+
return (type) => {
|
108
|
+
return {
|
109
|
+
type: narrowTypeForIsEllipsis(evaluator, type, adjIsPositiveTest),
|
110
|
+
isIncomplete: false,
|
111
|
+
};
|
112
|
+
};
|
113
|
+
}
|
114
|
+
}
|
95
115
|
// Look for "type(X) is Y" or "type(X) is not Y".
|
96
116
|
if (isOrIsNotOperator && testExpression.leftExpression.nodeType === 9 /* Call */) {
|
97
117
|
if (testExpression.leftExpression.arguments.length === 1 &&
|
@@ -100,10 +120,14 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
100
120
|
if (ParseTreeUtils.isMatchingExpression(reference, arg0Expr)) {
|
101
121
|
const callType = evaluator.getTypeOfExpression(testExpression.leftExpression.leftExpression, 2 /* DoNotSpecialize */).type;
|
102
122
|
if ((0, types_1.isInstantiableClass)(callType) && types_1.ClassType.isBuiltIn(callType, 'type')) {
|
103
|
-
const
|
123
|
+
const classTypeResult = evaluator.getTypeOfExpression(testExpression.rightExpression);
|
124
|
+
const classType = evaluator.makeTopLevelTypeVarsConcrete(classTypeResult.type);
|
104
125
|
if ((0, types_1.isInstantiableClass)(classType)) {
|
105
126
|
return (type) => {
|
106
|
-
return
|
127
|
+
return {
|
128
|
+
type: narrowTypeForTypeIs(evaluator, type, classType, adjIsPositiveTest),
|
129
|
+
isIncomplete: !!classTypeResult.isIncomplete,
|
130
|
+
};
|
107
131
|
};
|
108
132
|
}
|
109
133
|
}
|
@@ -113,13 +137,17 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
113
137
|
// Look for "X is Y" or "X is not Y" where Y is a an enum or bool literal.
|
114
138
|
if (isOrIsNotOperator) {
|
115
139
|
if (ParseTreeUtils.isMatchingExpression(reference, testExpression.leftExpression)) {
|
116
|
-
const
|
140
|
+
const rightTypeResult = evaluator.getTypeOfExpression(testExpression.rightExpression);
|
141
|
+
const rightType = rightTypeResult.type;
|
117
142
|
if ((0, types_1.isClassInstance)(rightType) &&
|
118
143
|
(types_1.ClassType.isEnumClass(rightType) || types_1.ClassType.isBuiltIn(rightType, 'bool')) &&
|
119
144
|
rightType.literalValue !== undefined) {
|
120
145
|
return (type) => {
|
121
|
-
return
|
122
|
-
|
146
|
+
return {
|
147
|
+
type: narrowTypeForLiteralComparison(evaluator, type, rightType, adjIsPositiveTest,
|
148
|
+
/* isIsOperator */ true),
|
149
|
+
isIncomplete: !!rightTypeResult.isIncomplete,
|
150
|
+
};
|
123
151
|
};
|
124
152
|
}
|
125
153
|
}
|
@@ -128,21 +156,29 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
128
156
|
// Look for X == <literal> or X != <literal>
|
129
157
|
const adjIsPositiveTest = testExpression.operator === 12 /* Equals */ ? isPositiveTest : !isPositiveTest;
|
130
158
|
if (ParseTreeUtils.isMatchingExpression(reference, testExpression.leftExpression)) {
|
131
|
-
const
|
159
|
+
const rightTypeResult = evaluator.getTypeOfExpression(testExpression.rightExpression);
|
160
|
+
const rightType = rightTypeResult.type;
|
132
161
|
if ((0, types_1.isClassInstance)(rightType) && rightType.literalValue !== undefined) {
|
133
162
|
return (type) => {
|
134
|
-
return
|
135
|
-
|
163
|
+
return {
|
164
|
+
type: narrowTypeForLiteralComparison(evaluator, type, rightType, adjIsPositiveTest,
|
165
|
+
/* isIsOperator */ false),
|
166
|
+
isIncomplete: !!rightTypeResult.isIncomplete,
|
167
|
+
};
|
136
168
|
};
|
137
169
|
}
|
138
170
|
}
|
139
171
|
// Look for <literal> == X or <literal> != X
|
140
172
|
if (ParseTreeUtils.isMatchingExpression(reference, testExpression.rightExpression)) {
|
141
|
-
const
|
173
|
+
const leftTypeResult = evaluator.getTypeOfExpression(testExpression.leftExpression);
|
174
|
+
const leftType = leftTypeResult.type;
|
142
175
|
if ((0, types_1.isClassInstance)(leftType) && leftType.literalValue !== undefined) {
|
143
176
|
return (type) => {
|
144
|
-
return
|
145
|
-
|
177
|
+
return {
|
178
|
+
type: narrowTypeForLiteralComparison(evaluator, type, leftType, adjIsPositiveTest,
|
179
|
+
/* isIsOperator */ false),
|
180
|
+
isIncomplete: !!leftTypeResult.isIncomplete,
|
181
|
+
};
|
146
182
|
};
|
147
183
|
}
|
148
184
|
}
|
@@ -152,21 +188,29 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
152
188
|
!testExpression.leftExpression.trailingComma &&
|
153
189
|
testExpression.leftExpression.items[0].argumentCategory === 0 /* Simple */ &&
|
154
190
|
ParseTreeUtils.isMatchingExpression(reference, testExpression.leftExpression.baseExpression)) {
|
155
|
-
const
|
191
|
+
const indexTypeResult = evaluator.getTypeOfExpression(testExpression.leftExpression.items[0].valueExpression);
|
192
|
+
const indexType = indexTypeResult.type;
|
156
193
|
if ((0, types_1.isClassInstance)(indexType) && (0, typeUtils_1.isLiteralType)(indexType)) {
|
157
194
|
if (types_1.ClassType.isBuiltIn(indexType, 'str')) {
|
158
195
|
const rightType = evaluator.getTypeOfExpression(testExpression.rightExpression).type;
|
159
196
|
if ((0, types_1.isClassInstance)(rightType) && rightType.literalValue !== undefined) {
|
160
197
|
return (type) => {
|
161
|
-
return
|
198
|
+
return {
|
199
|
+
type: narrowTypeForDiscriminatedDictEntryComparison(evaluator, type, indexType, rightType, adjIsPositiveTest),
|
200
|
+
isIncomplete: !!indexTypeResult.isIncomplete,
|
201
|
+
};
|
162
202
|
};
|
163
203
|
}
|
164
204
|
}
|
165
205
|
else if (types_1.ClassType.isBuiltIn(indexType, 'int')) {
|
166
|
-
const
|
206
|
+
const rightTypeResult = evaluator.getTypeOfExpression(testExpression.rightExpression);
|
207
|
+
const rightType = rightTypeResult.type;
|
167
208
|
if ((0, types_1.isClassInstance)(rightType) && rightType.literalValue !== undefined) {
|
168
209
|
return (type) => {
|
169
|
-
return
|
210
|
+
return {
|
211
|
+
type: narrowTypeForDiscriminatedTupleComparison(evaluator, type, indexType, rightType, adjIsPositiveTest),
|
212
|
+
isIncomplete: !!rightTypeResult.isIncomplete,
|
213
|
+
};
|
170
214
|
};
|
171
215
|
}
|
172
216
|
}
|
@@ -181,12 +225,16 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
181
225
|
testExpression.rightExpression.isInteger) {
|
182
226
|
const arg0Expr = testExpression.leftExpression.arguments[0].valueExpression;
|
183
227
|
if (ParseTreeUtils.isMatchingExpression(reference, arg0Expr)) {
|
184
|
-
const
|
228
|
+
const callTypeResult = evaluator.getTypeOfExpression(testExpression.leftExpression.leftExpression, 2 /* DoNotSpecialize */);
|
229
|
+
const callType = callTypeResult.type;
|
185
230
|
if ((0, types_1.isFunction)(callType) && callType.details.fullName === 'builtins.len') {
|
186
231
|
const tupleLength = testExpression.rightExpression.value;
|
187
232
|
if (typeof tupleLength === 'number') {
|
188
233
|
return (type) => {
|
189
|
-
return
|
234
|
+
return {
|
235
|
+
type: narrowTypeForTupleLength(evaluator, type, tupleLength, adjIsPositiveTest),
|
236
|
+
isIncomplete: !!callTypeResult.isIncomplete,
|
237
|
+
};
|
190
238
|
};
|
191
239
|
}
|
192
240
|
}
|
@@ -196,11 +244,15 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
196
244
|
if (equalsOrNotEqualsOperator &&
|
197
245
|
testExpression.leftExpression.nodeType === 35 /* MemberAccess */ &&
|
198
246
|
ParseTreeUtils.isMatchingExpression(reference, testExpression.leftExpression.leftExpression)) {
|
199
|
-
const
|
247
|
+
const rightTypeResult = evaluator.getTypeOfExpression(testExpression.rightExpression);
|
248
|
+
const rightType = rightTypeResult.type;
|
200
249
|
const memberName = testExpression.leftExpression.memberName;
|
201
250
|
if ((0, types_1.isClassInstance)(rightType) && rightType.literalValue !== undefined) {
|
202
251
|
return (type) => {
|
203
|
-
return
|
252
|
+
return {
|
253
|
+
type: narrowTypeForDiscriminatedLiteralFieldComparison(evaluator, type, memberName.value, rightType, adjIsPositiveTest),
|
254
|
+
isIncomplete: !!rightTypeResult.isIncomplete,
|
255
|
+
};
|
204
256
|
};
|
205
257
|
}
|
206
258
|
}
|
@@ -208,13 +260,17 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
208
260
|
// an enum or bool literal
|
209
261
|
if (testExpression.leftExpression.nodeType === 35 /* MemberAccess */ &&
|
210
262
|
ParseTreeUtils.isMatchingExpression(reference, testExpression.leftExpression.leftExpression)) {
|
211
|
-
const
|
263
|
+
const rightTypeResult = evaluator.getTypeOfExpression(testExpression.rightExpression);
|
264
|
+
const rightType = rightTypeResult.type;
|
212
265
|
const memberName = testExpression.leftExpression.memberName;
|
213
266
|
if ((0, types_1.isClassInstance)(rightType) &&
|
214
267
|
(types_1.ClassType.isEnumClass(rightType) || types_1.ClassType.isBuiltIn(rightType, 'bool')) &&
|
215
268
|
rightType.literalValue !== undefined) {
|
216
269
|
return (type) => {
|
217
|
-
return
|
270
|
+
return {
|
271
|
+
type: narrowTypeForDiscriminatedLiteralFieldComparison(evaluator, type, memberName.value, rightType, adjIsPositiveTest),
|
272
|
+
isIncomplete: !!rightTypeResult.isIncomplete,
|
273
|
+
};
|
218
274
|
};
|
219
275
|
}
|
220
276
|
}
|
@@ -226,27 +282,38 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
226
282
|
testExpression.rightExpression.constType === 26 /* None */) {
|
227
283
|
const memberName = testExpression.leftExpression.memberName;
|
228
284
|
return (type) => {
|
229
|
-
return
|
285
|
+
return {
|
286
|
+
type: narrowTypeForDiscriminatedFieldNoneComparison(evaluator, type, memberName.value, adjIsPositiveTest),
|
287
|
+
isIncomplete: false,
|
288
|
+
};
|
230
289
|
};
|
231
290
|
}
|
232
291
|
}
|
233
292
|
if (testExpression.operator === 41 /* In */ || testExpression.operator === 42 /* NotIn */) {
|
234
293
|
// Look for "x in y" or "x not in y" where y is one of several built-in types.
|
235
294
|
if (ParseTreeUtils.isMatchingExpression(reference, testExpression.leftExpression)) {
|
236
|
-
const
|
295
|
+
const rightTypeResult = evaluator.getTypeOfExpression(testExpression.rightExpression);
|
296
|
+
const rightType = rightTypeResult.type;
|
237
297
|
const adjIsPositiveTest = testExpression.operator === 41 /* In */ ? isPositiveTest : !isPositiveTest;
|
238
298
|
return (type) => {
|
239
|
-
return
|
299
|
+
return {
|
300
|
+
type: narrowTypeForContainerType(evaluator, type, rightType, adjIsPositiveTest),
|
301
|
+
isIncomplete: !!rightTypeResult.isIncomplete,
|
302
|
+
};
|
240
303
|
};
|
241
304
|
}
|
242
305
|
if (ParseTreeUtils.isMatchingExpression(reference, testExpression.rightExpression)) {
|
243
306
|
// Look for <string literal> in y where y is a union that contains
|
244
307
|
// one or more TypedDicts.
|
245
|
-
const
|
308
|
+
const leftTypeResult = evaluator.getTypeOfExpression(testExpression.leftExpression);
|
309
|
+
const leftType = leftTypeResult.type;
|
246
310
|
if ((0, types_1.isClassInstance)(leftType) && types_1.ClassType.isBuiltIn(leftType, 'str') && (0, typeUtils_1.isLiteralType)(leftType)) {
|
247
311
|
const adjIsPositiveTest = testExpression.operator === 41 /* In */ ? isPositiveTest : !isPositiveTest;
|
248
312
|
return (type) => {
|
249
|
-
return
|
313
|
+
return {
|
314
|
+
type: narrowTypeForTypedDictKey(evaluator, type, types_1.ClassType.cloneAsInstantiable(leftType), adjIsPositiveTest),
|
315
|
+
isIncomplete: !!leftTypeResult.isIncomplete,
|
316
|
+
};
|
250
317
|
};
|
251
318
|
}
|
252
319
|
}
|
@@ -261,24 +328,43 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
261
328
|
const arg0Expr = testExpression.arguments[0].valueExpression;
|
262
329
|
const arg1Expr = testExpression.arguments[1].valueExpression;
|
263
330
|
if (ParseTreeUtils.isMatchingExpression(reference, arg0Expr)) {
|
264
|
-
const
|
331
|
+
const callTypeResult = evaluator.getTypeOfExpression(testExpression.leftExpression, 2 /* DoNotSpecialize */);
|
332
|
+
const callType = callTypeResult.type;
|
265
333
|
if ((0, types_1.isFunction)(callType) &&
|
266
334
|
(callType.details.builtInName === 'isinstance' || callType.details.builtInName === 'issubclass')) {
|
267
335
|
const isInstanceCheck = callType.details.builtInName === 'isinstance';
|
268
|
-
const
|
336
|
+
const arg1TypeResult = evaluator.getTypeOfExpression(arg1Expr, 8 /* EvaluateStringLiteralAsType */ |
|
269
337
|
32 /* ParamSpecDisallowed */ |
|
270
|
-
128 /* TypeVarTupleDisallowed */)
|
338
|
+
128 /* TypeVarTupleDisallowed */);
|
339
|
+
const arg1Type = arg1TypeResult.type;
|
271
340
|
const classTypeList = getIsInstanceClassTypes(arg1Type);
|
341
|
+
const isIncomplete = !!callTypeResult.isIncomplete || !!arg1TypeResult.isIncomplete;
|
272
342
|
if (classTypeList) {
|
273
343
|
return (type) => {
|
274
344
|
const narrowedType = narrowTypeForIsInstance(evaluator, type, classTypeList, isInstanceCheck, isPositiveTest,
|
275
345
|
/* allowIntersections */ false, testExpression);
|
276
346
|
if (!(0, types_1.isNever)(narrowedType)) {
|
277
|
-
return
|
347
|
+
return {
|
348
|
+
type: narrowedType,
|
349
|
+
isIncomplete,
|
350
|
+
};
|
278
351
|
}
|
279
352
|
// Try again with intersection types allowed.
|
280
|
-
return
|
281
|
-
|
353
|
+
return {
|
354
|
+
type: narrowTypeForIsInstance(evaluator, type, classTypeList, isInstanceCheck, isPositiveTest,
|
355
|
+
/* allowIntersections */ true, testExpression),
|
356
|
+
isIncomplete,
|
357
|
+
};
|
358
|
+
};
|
359
|
+
}
|
360
|
+
else if (isIncomplete) {
|
361
|
+
// If the type is incomplete, it may include unknowns, which will result
|
362
|
+
// in classTypeList being undefined.
|
363
|
+
return (type) => {
|
364
|
+
return {
|
365
|
+
type,
|
366
|
+
isIncomplete: true,
|
367
|
+
};
|
282
368
|
};
|
283
369
|
}
|
284
370
|
}
|
@@ -288,7 +374,8 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
288
374
|
if (testExpression.arguments.length === 1) {
|
289
375
|
const arg0Expr = testExpression.arguments[0].valueExpression;
|
290
376
|
if (ParseTreeUtils.isMatchingExpression(reference, arg0Expr)) {
|
291
|
-
const
|
377
|
+
const callTypeResult = evaluator.getTypeOfExpression(testExpression.leftExpression, 2 /* DoNotSpecialize */);
|
378
|
+
const callType = callTypeResult.type;
|
292
379
|
if ((0, types_1.isFunction)(callType) && callType.details.builtInName === 'callable') {
|
293
380
|
return (type) => {
|
294
381
|
let narrowedType = narrowTypeForCallable(evaluator, type, isPositiveTest, testExpression,
|
@@ -298,7 +385,7 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
298
385
|
narrowedType = narrowTypeForCallable(evaluator, type, isPositiveTest, testExpression,
|
299
386
|
/* allowIntersections */ true);
|
300
387
|
}
|
301
|
-
return narrowedType;
|
388
|
+
return { type: narrowedType, isIncomplete: !!callTypeResult.isIncomplete };
|
302
389
|
};
|
303
390
|
}
|
304
391
|
}
|
@@ -306,10 +393,14 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
306
393
|
// Look for "bool(X)"
|
307
394
|
if (testExpression.arguments.length === 1 && !testExpression.arguments[0].name) {
|
308
395
|
if (ParseTreeUtils.isMatchingExpression(reference, testExpression.arguments[0].valueExpression)) {
|
309
|
-
const
|
396
|
+
const callTypeResult = evaluator.getTypeOfExpression(testExpression.leftExpression, 2 /* DoNotSpecialize */);
|
397
|
+
const callType = callTypeResult.type;
|
310
398
|
if ((0, types_1.isInstantiableClass)(callType) && types_1.ClassType.isBuiltIn(callType, 'bool')) {
|
311
399
|
return (type) => {
|
312
|
-
return
|
400
|
+
return {
|
401
|
+
type: narrowTypeForTruthiness(evaluator, type, isPositiveTest),
|
402
|
+
isIncomplete: !!callTypeResult.isIncomplete,
|
403
|
+
};
|
313
404
|
};
|
314
405
|
}
|
315
406
|
}
|
@@ -325,7 +416,8 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
325
416
|
(0, types_1.isClassInstance)(type.details.declaredReturnType) &&
|
326
417
|
types_1.ClassType.isBuiltIn(type.details.declaredReturnType, ['TypeGuard', 'StrictTypeGuard']));
|
327
418
|
};
|
328
|
-
const
|
419
|
+
const callTypeResult = evaluator.getTypeOfExpression(testExpression.leftExpression, 2 /* DoNotSpecialize */);
|
420
|
+
const callType = callTypeResult.type;
|
329
421
|
if ((0, types_1.isFunction)(callType) && isFunctionReturnTypeGuard(callType)) {
|
330
422
|
isPossiblyTypeGuard = true;
|
331
423
|
}
|
@@ -335,14 +427,19 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
335
427
|
}
|
336
428
|
if (isPossiblyTypeGuard) {
|
337
429
|
// Evaluate the type guard call expression.
|
338
|
-
const
|
430
|
+
const functionReturnTypeResult = evaluator.getTypeOfExpression(testExpression);
|
431
|
+
const functionReturnType = functionReturnTypeResult.type;
|
339
432
|
if ((0, types_1.isClassInstance)(functionReturnType) &&
|
340
433
|
types_1.ClassType.isBuiltIn(functionReturnType, 'bool') &&
|
341
434
|
functionReturnType.typeGuardType) {
|
342
435
|
const isStrictTypeGuard = !!functionReturnType.isStrictTypeGuard;
|
343
436
|
const typeGuardType = functionReturnType.typeGuardType;
|
437
|
+
const isIncomplete = !!callTypeResult.isIncomplete || !!functionReturnTypeResult.isIncomplete;
|
344
438
|
return (type) => {
|
345
|
-
return
|
439
|
+
return {
|
440
|
+
type: narrowTypeForUserDefinedTypeGuard(evaluator, type, typeGuardType, isPositiveTest, isStrictTypeGuard),
|
441
|
+
isIncomplete,
|
442
|
+
};
|
346
443
|
};
|
347
444
|
}
|
348
445
|
}
|
@@ -351,7 +448,10 @@ function getTypeNarrowingCallback(evaluator, reference, testExpression, isPositi
|
|
351
448
|
}
|
352
449
|
if (ParseTreeUtils.isMatchingExpression(reference, testExpression)) {
|
353
450
|
return (type) => {
|
354
|
-
return
|
451
|
+
return {
|
452
|
+
type: narrowTypeForTruthiness(evaluator, type, isPositiveTest),
|
453
|
+
isIncomplete: false,
|
454
|
+
};
|
355
455
|
};
|
356
456
|
}
|
357
457
|
// Is this a reference to an aliased conditional expression (a local variable
|
@@ -557,6 +657,38 @@ function narrowTypeForIsNone(evaluator, type, isPositiveTest) {
|
|
557
657
|
return undefined;
|
558
658
|
});
|
559
659
|
}
|
660
|
+
// Handle type narrowing for expressions of the form "x is ..." and "x is not ...".
|
661
|
+
function narrowTypeForIsEllipsis(evaluator, type, isPositiveTest) {
|
662
|
+
const expandedType = (0, typeUtils_1.mapSubtypes)(type, (subtype) => {
|
663
|
+
return (0, typeUtils_1.transformPossibleRecursiveTypeAlias)(subtype);
|
664
|
+
});
|
665
|
+
return evaluator.mapSubtypesExpandTypeVars(expandedType,
|
666
|
+
/* conditionFilter */ undefined, (subtype, unexpandedSubtype) => {
|
667
|
+
if ((0, types_1.isAnyOrUnknown)(subtype)) {
|
668
|
+
// We need to assume that "Any" is always both None and not None,
|
669
|
+
// so it matches regardless of whether the test is positive or negative.
|
670
|
+
return subtype;
|
671
|
+
}
|
672
|
+
// If this is a TypeVar that isn't constrained, use the unexpanded
|
673
|
+
// TypeVar. For all other cases (including constrained TypeVars),
|
674
|
+
// use the expanded subtype.
|
675
|
+
const adjustedSubtype = (0, types_1.isTypeVar)(unexpandedSubtype) && unexpandedSubtype.details.constraints.length === 0
|
676
|
+
? unexpandedSubtype
|
677
|
+
: subtype;
|
678
|
+
// See if it's a match for object.
|
679
|
+
if ((0, types_1.isClassInstance)(subtype) && types_1.ClassType.isBuiltIn(subtype, 'object')) {
|
680
|
+
return isPositiveTest
|
681
|
+
? (0, typeUtils_1.addConditionToType)(types_1.NoneType.createInstance(), subtype.condition)
|
682
|
+
: adjustedSubtype;
|
683
|
+
}
|
684
|
+
const isEllipsis = (0, types_1.isClassInstance)(subtype) && types_1.ClassType.isBuiltIn(subtype, 'ellipsis');
|
685
|
+
// See if it's a match for "...".
|
686
|
+
if (isEllipsis === isPositiveTest) {
|
687
|
+
return subtype;
|
688
|
+
}
|
689
|
+
return undefined;
|
690
|
+
});
|
691
|
+
}
|
560
692
|
// The "isinstance" and "issubclass" calls support two forms - a simple form
|
561
693
|
// that accepts a single class, and a more complex form that accepts a tuple
|
562
694
|
// of classes (including arbitrarily-nested tuples). This method determines
|
@@ -881,7 +1013,12 @@ function narrowTypeForIsInstance(evaluator, type, classTypeList, isInstanceCheck
|
|
881
1013
|
}
|
882
1014
|
if (isInstanceCheck) {
|
883
1015
|
if ((0, types_1.isNoneInstance)(subtype)) {
|
884
|
-
const containsNoneType = classTypeList.some((t) =>
|
1016
|
+
const containsNoneType = classTypeList.some((t) => {
|
1017
|
+
if ((0, types_1.isNoneTypeClass)(t)) {
|
1018
|
+
return true;
|
1019
|
+
}
|
1020
|
+
return (0, types_1.isInstantiableClass)(t) && types_1.ClassType.isBuiltIn(t, 'NoneType');
|
1021
|
+
});
|
885
1022
|
if (isPositiveTest) {
|
886
1023
|
return containsNoneType ? subtype : undefined;
|
887
1024
|
}
|