Skip to content

Commit 1742c57

Browse files
committed
Added helper function to wrap type evaluator functions that cannot be safely interrupted by a cancellation exception.
1 parent 807b160 commit 1742c57

File tree

2 files changed

+21
-31
lines changed

2 files changed

+21
-31
lines changed

packages/pyright-internal/src/analyzer/typeEvaluator.ts

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
import { CancellationToken } from 'vscode-languageserver';
1818

19-
import { OperationCanceledException, throwIfCancellationRequested } from '../common/cancellationUtils';
19+
import { invalidateTypeCacheIfCanceled, throwIfCancellationRequested } from '../common/cancellationUtils';
2020
import { appendArray } from '../common/collectionUtils';
2121
import { DiagnosticLevel } from '../common/configOptions';
2222
import { ConsoleInterface } from '../common/console';
@@ -14330,7 +14330,7 @@ export function createTypeEvaluator(
1433014330
let functionType = FunctionType.createInstance('', '', '', FunctionTypeFlags.PartiallyEvaluated);
1433114331
functionType.details.typeVarScopeId = ParseTreeUtils.getScopeIdForNode(node);
1433214332

14333-
try {
14333+
return invalidateTypeCacheIfCanceled(() => {
1433414334
// Pre-cache the incomplete function type in case the evaluation of the
1433514335
// lambda depends on itself.
1433614336
writeTypeCache(node, { type: functionType, isIncomplete: true }, EvaluatorFlags.None);
@@ -14494,15 +14494,7 @@ export function createTypeEvaluator(
1449414494
}
1449514495

1449614496
return { type: functionType, isIncomplete, typeErrors };
14497-
} catch (e) {
14498-
if (OperationCanceledException.is(e)) {
14499-
// If the work was canceled before the function type was updated, the
14500-
// function type in the type cache is in an invalid, partially-constructed state.
14501-
e.isTypeCacheInvalid = true;
14502-
}
14503-
14504-
throw e;
14505-
}
14497+
});
1450614498
}
1450714499

1450814500
function getTypeOfComprehension(
@@ -16523,7 +16515,7 @@ export function createTypeEvaluator(
1652316515
classType.details.flags |= ClassTypeFlags.PartiallyEvaluated;
1652416516
classType.details.declaration = classDecl;
1652516517

16526-
try {
16518+
return invalidateTypeCacheIfCanceled(() => {
1652716519
writeTypeCache(node, { type: classType }, /* flags */ undefined);
1652816520
writeTypeCache(node.name, { type: classType }, /* flags */ undefined);
1652916521

@@ -17225,15 +17217,7 @@ export function createTypeEvaluator(
1722517217
writeTypeCache(node, { type: decoratedType }, EvaluatorFlags.None);
1722617218

1722717219
return { classType, decoratedType };
17228-
} catch (e) {
17229-
if (OperationCanceledException.is(e)) {
17230-
// If the work was canceled before the class types were updated, the
17231-
// class type in the type cache is in an invalid, partially-constructed state.
17232-
e.isTypeCacheInvalid = true;
17233-
}
17234-
17235-
throw e;
17236-
}
17220+
});
1723717221
}
1723817222

1723917223
// Determines whether the type parameters has a default that refers to another
@@ -17888,7 +17872,7 @@ export function createTypeEvaluator(
1788817872
setSymbolResolutionPartialType(functionSymbol.symbol, functionDecl, functionType);
1788917873
}
1789017874

17891-
try {
17875+
return invalidateTypeCacheIfCanceled(() => {
1789217876
writeTypeCache(node.name, { type: functionType }, /* flags */ undefined);
1789317877

1789417878
// Is this an "__init__" method within a pseudo-generic class? If so,
@@ -18275,15 +18259,7 @@ export function createTypeEvaluator(
1827518259
writeTypeCache(node.name, { type: functionType }, EvaluatorFlags.None);
1827618260

1827718261
return functionType;
18278-
} catch (e) {
18279-
if (OperationCanceledException.is(e)) {
18280-
// If the work was canceled before the function type was updated, the
18281-
// function type in the type cache is in an invalid, partially-constructed state.
18282-
e.isTypeCacheInvalid = true;
18283-
}
18284-
18285-
throw e;
18286-
}
18262+
});
1828718263
}
1828818264

1828918265
function markParamAccessed(param: ParameterNode) {

packages/pyright-internal/src/common/cancellationUtils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,20 @@ export function setCancellationFolderName(folderName?: string) {
2727
cancellationFolderName = folderName;
2828
}
2929

30+
export function invalidateTypeCacheIfCanceled<T>(cb: () => T): T {
31+
try {
32+
return cb();
33+
} catch (e: any) {
34+
if (OperationCanceledException.is(e)) {
35+
// If the work was canceled before the function type was updated, the
36+
// function type in the type cache is in an invalid, partially-constructed state.
37+
e.isTypeCacheInvalid = true;
38+
}
39+
40+
throw e;
41+
}
42+
}
43+
3044
export class OperationCanceledException extends ResponseError<void> {
3145
// If true, indicates that the cancellation may have left the type cache
3246
// in an invalid state.

0 commit comments

Comments
 (0)