From 992310268a92ad11e133e6913ca90f4fcc8c9476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 8 Feb 2023 18:09:56 +0100 Subject: [PATCH 1/3] Fixed lack of errors on call expressions after LSP requests that read their signatures --- src/compiler/checker.ts | 22 ++++++++++++++----- .../fourslash/arityErrorAfterSignatureHelp.ts | 22 +++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 tests/cases/fourslash/arityErrorAfterSignatureHelp.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fe687cc3be0fd..d1a6273705778 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1636,9 +1636,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getResolvedSignature: (node, candidatesOutArray, argumentCount) => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal), getResolvedSignatureForStringLiteralCompletions: (call, editingArgument, candidatesOutArray) => - getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions, editingArgument), + runWithoutResolvedSignatureCaching(call, () => getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions, editingArgument)), getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) => - getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp), + runWithoutResolvedSignatureCaching(node, () => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp)), getExpandedParameters, hasEffectiveRestParameter, containsArgumentsReference, @@ -1813,25 +1813,35 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isTypeParameterPossiblyReferenced, }; - function runWithInferenceBlockedFromSourceNode(node: Node | undefined, fn: () => T): T { + function runWithoutResolvedSignatureCaching(node: Node | undefined, fn: () => T): T { const containingCall = findAncestor(node, isCallLikeExpression); const containingCallResolvedSignature = containingCall && getNodeLinks(containingCall).resolvedSignature; + if (containingCall) { + getNodeLinks(containingCall).resolvedSignature = undefined; + } + const result = fn(); + if (containingCall) { + getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature; + } + return result; + } + + function runWithInferenceBlockedFromSourceNode(node: Node | undefined, fn: () => T): T { + const containingCall = findAncestor(node, isCallLikeExpression); if (containingCall) { let toMarkSkip = node!; do { getNodeLinks(toMarkSkip).skipDirectInference = true; toMarkSkip = toMarkSkip.parent; } while (toMarkSkip && toMarkSkip !== containingCall); - getNodeLinks(containingCall).resolvedSignature = undefined; } - const result = fn(); + const result = runWithoutResolvedSignatureCaching(node, fn); if (containingCall) { let toMarkSkip = node!; do { getNodeLinks(toMarkSkip).skipDirectInference = undefined; toMarkSkip = toMarkSkip.parent; } while (toMarkSkip && toMarkSkip !== containingCall); - getNodeLinks(containingCall).resolvedSignature = containingCallResolvedSignature; } return result; } diff --git a/tests/cases/fourslash/arityErrorAfterSignatureHelp.ts b/tests/cases/fourslash/arityErrorAfterSignatureHelp.ts new file mode 100644 index 0000000000000..d6578ec1288f4 --- /dev/null +++ b/tests/cases/fourslash/arityErrorAfterSignatureHelp.ts @@ -0,0 +1,22 @@ +/// +// @strict: true +//// +//// declare function f(x: string, y: number): any; +//// +//// /*1*/f(/*2*/)/*3*/ + +goTo.marker("2"); +verify.signatureHelp({ + triggerReason: { + kind: "invoked" + } +}) +edit.insert(`"`) +edit.insert(`"`) +verify.signatureHelp({ + triggerReason: { + kind: "retrigger" + } +}) +verify.not.codeFixAvailable() // trigger typecheck +verify.errorExistsBetweenMarkers("1", "3"); From 5313604707376f1c7fbe518acf00676ae2bac5d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Feb 2023 00:49:34 +0100 Subject: [PATCH 2/3] Cleanup blocking calls --- src/compiler/checker.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d1a6273705778..403928ccdcb2a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1636,7 +1636,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getResolvedSignature: (node, candidatesOutArray, argumentCount) => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.Normal), getResolvedSignatureForStringLiteralCompletions: (call, editingArgument, candidatesOutArray) => - runWithoutResolvedSignatureCaching(call, () => getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions, editingArgument)), + runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignatureWorker(call, candidatesOutArray, /*argumentCount*/ undefined, CheckMode.IsForStringLiteralArgumentCompletions)), getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, argumentCount) => runWithoutResolvedSignatureCaching(node, () => getResolvedSignatureWorker(node, candidatesOutArray, argumentCount, CheckMode.IsForSignatureHelp)), getExpandedParameters, @@ -1846,13 +1846,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode, editingArgument?: Node): Signature | undefined { + function getResolvedSignatureWorker(nodeIn: CallLikeExpression, candidatesOutArray: Signature[] | undefined, argumentCount: number | undefined, checkMode: CheckMode): Signature | undefined { const node = getParseTreeNode(nodeIn, isCallLikeExpression); apparentArgumentCount = argumentCount; - const res = - !node ? undefined : - editingArgument ? runWithInferenceBlockedFromSourceNode(editingArgument, () => getResolvedSignature(node, candidatesOutArray, checkMode)) : - getResolvedSignature(node, candidatesOutArray, checkMode); + const res = !node ? undefined : getResolvedSignature(node, candidatesOutArray, checkMode); apparentArgumentCount = undefined; return res; } From 7b79e1a5a7b820f1a5eabf9a6699cf4aff27e685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 11 Feb 2023 00:53:40 +0100 Subject: [PATCH 3/3] add an extra regression test case for string completions --- .../fourslash/arityErrorAfterStringCompletions.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/cases/fourslash/arityErrorAfterStringCompletions.ts diff --git a/tests/cases/fourslash/arityErrorAfterStringCompletions.ts b/tests/cases/fourslash/arityErrorAfterStringCompletions.ts new file mode 100644 index 0000000000000..7784e3ef70c06 --- /dev/null +++ b/tests/cases/fourslash/arityErrorAfterStringCompletions.ts @@ -0,0 +1,14 @@ +/// +// @strict: true +//// +//// interface Events { +//// click: any; +//// drag: any; +//// } +//// +//// declare function addListener(type: K, listener: (ev: Events[K]) => any): void; +//// +//// /*1*/addListener("/*2*/")/*3*/ + +verify.completions({ marker: ["2"], exact: ["click", "drag"] }); +verify.errorExistsBetweenMarkers("1", "3");