Skip to content

Commit ab40f5e

Browse files
authored
Avoid caching resolved signatures for language service requests like signature help (#52679)
1 parent f23dd7a commit ab40f5e

File tree

3 files changed

+54
-11
lines changed

3 files changed

+54
-11
lines changed

src/compiler/checker.ts

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,9 +1637,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
16371637
getResolvedSignature: (node, candidatesOutArray, argumentCount) =>
16381638
getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal),
16391639
getResolvedSignatureForStringLiteralCompletions: (call, editingArgument, candidatesOutArray) =>
1640-
getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions, editingArgument),
1640+
runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions)),
16411641
getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) =>
1642-
getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp),
1642+
runWithoutResolvedSignatureCaching(node, () => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp)),
16431643
getExpandedParameters,
16441644
hasEffectiveRestParameter,
16451645
containsArgumentsReference,
@@ -1814,36 +1814,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
18141814
isTypeParameterPossiblyReferenced,
18151815
};
18161816

1817-
function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, fn: () => T): T {
1817+
function runWithoutResolvedSignatureCaching<T>(node: Node | undefined, fn: () => T): T {
18181818
const containingCall = findAncestor(node, isCallLikeExpression);
18191819
const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature;
1820+
if (containingCall) {
1821+
getNodeLinks(containingCall).resolvedSignature = undefined;
1822+
}
1823+
const result = fn();
1824+
if (containingCall) {
1825+
getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
1826+
}
1827+
return result;
1828+
}
1829+
1830+
function runWithInferenceBlockedFromSourceNode<T>(node: Node | undefined, fn: () => T): T {
1831+
const containingCall = findAncestor(node, isCallLikeExpression);
18201832
if (containingCall) {
18211833
let toMarkSkip = node!;
18221834
do {
18231835
getNodeLinks(toMarkSkip).skipDirectInference = true;
18241836
toMarkSkip = toMarkSkip.parent;
18251837
} while (toMarkSkip && toMarkSkip !== containingCall);
1826-
getNodeLinks(containingCall).resolvedSignature = undefined;
18271838
}
1828-
const result = fn();
1839+
const result = runWithoutResolvedSignatureCaching(node, fn);
18291840
if (containingCall) {
18301841
let toMarkSkip = node!;
18311842
do {
18321843
getNodeLinks(toMarkSkip).skipDirectInference = undefined;
18331844
toMarkSkip = toMarkSkip.parent;
18341845
} while (toMarkSkip && toMarkSkip !== containingCall);
1835-
getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature;
18361846
}
18371847
return result;
18381848
}
18391849

1840-
function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode, editingArgument?: Node): Signature | undefined {
1850+
function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode): Signature | undefined {
18411851
const node = getParseTreeNode(nodeIn, isCallLikeExpression);
18421852
apparentArgumentCount = argumentCount;
1843-
const res =
1844-
!node ? undefined :
1845-
editingArgument ? runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignature(node, candidatesOutArray, checkMode)) :
1846-
getResolvedSignature(node, candidatesOutArray, checkMode);
1853+
const res = !node ? undefined : getResolvedSignature(node, candidatesOutArray, checkMode);
18471854
apparentArgumentCount = undefined;
18481855
return res;
18491856
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
///<reference path="fourslash.ts"/>
2+
// @strict: true
3+
////
4+
//// declare function f(x: string, y: number): any;
5+
////
6+
//// /*1*/f(/*2*/)/*3*/
7+
8+
goTo.marker("2");
9+
verify.signatureHelp({
10+
triggerReason: {
11+
kind: "invoked"
12+
}
13+
})
14+
edit.insert(`"`)
15+
edit.insert(`"`)
16+
verify.signatureHelp({
17+
triggerReason: {
18+
kind: "retrigger"
19+
}
20+
})
21+
verify.not.codeFixAvailable() // trigger typecheck
22+
verify.errorExistsBetweenMarkers("1", "3");
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
///<reference path="fourslash.ts"/>
2+
// @strict: true
3+
////
4+
//// interface Events {
5+
//// click: any;
6+
//// drag: any;
7+
//// }
8+
////
9+
//// declare function addListener<K extends keyof Events>(type: K, listener: (ev: Events[K]) => any): void;
10+
////
11+
//// /*1*/addListener("/*2*/")/*3*/
12+
13+
verify.completions({ marker: ["2"], exact: ["click", "drag"] });
14+
verify.errorExistsBetweenMarkers("1", "3");

0 commit comments

Comments
 (0)