From 5ca7983ebe894278c68954a0d35386598a4a5b3c Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Fri, 14 May 2021 02:12:17 -0400 Subject: [PATCH] Fix the code that checks for variadic signatures This code looks strange, like there's a typo in it (eg, using `lists` in the `parameterList` loop, etc) -- so I also refactored it a bit to look more intentional. The new format makes it clearer that `lists` is checked once *outside* the loop, as well as the role of `hasEffectiveRestParameter`. The actual bug fix is checking `pList.length` in the new `isVariadic()`. Fixes 41059. --- src/services/signatureHelp.ts | 19 ++++++++++--------- tests/cases/fourslash/jsSignature-41059.ts | 10 ++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 tests/cases/fourslash/jsSignature-41059.ts diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 8faf17f1956..ea72661a868 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -624,7 +624,6 @@ namespace ts.SignatureHelp { } function itemInfoForParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] { - const isVariadic = checker.hasEffectiveRestParameter(candidateSignature); const printer = createPrinter({ removeComments: true }); const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { @@ -633,14 +632,16 @@ namespace ts.SignatureHelp { } }); const lists = checker.getExpandedParameters(candidateSignature); - return lists.map(parameterList => { - return { - isVariadic: isVariadic && (lists.length === 1 || !!((parameterList[parameterList.length - 1] as TransientSymbol).checkFlags & CheckFlags.RestParameter)), - parameters: parameterList.map(p => createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer)), - prefix: [...typeParameterParts, punctuationPart(SyntaxKind.OpenParenToken)], - suffix: [punctuationPart(SyntaxKind.CloseParenToken)] - }; - }); + const isVariadic: (parameterList: readonly Symbol[]) => boolean = + !checker.hasEffectiveRestParameter(candidateSignature) ? _ => false + : lists.length === 1 ? _ => true + : pList => !!(pList.length && (pList[pList.length - 1] as TransientSymbol).checkFlags & CheckFlags.RestParameter); + return lists.map(parameterList => ({ + isVariadic: isVariadic(parameterList), + parameters: parameterList.map(p => createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer)), + prefix: [...typeParameterParts, punctuationPart(SyntaxKind.OpenParenToken)], + suffix: [punctuationPart(SyntaxKind.CloseParenToken)] + })); } function createSignatureHelpParameterForParameter(parameter: Symbol, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile, printer: Printer): SignatureHelpParameter { diff --git a/tests/cases/fourslash/jsSignature-41059.ts b/tests/cases/fourslash/jsSignature-41059.ts new file mode 100644 index 00000000000..35e550aaa89 --- /dev/null +++ b/tests/cases/fourslash/jsSignature-41059.ts @@ -0,0 +1,10 @@ +/// + +// @lib: esnext +// @allowNonTsExtensions: true + +// @Filename: Foo.js +//// a.next(/**/); + +goTo.marker(); +verify.signatureHelp({ overloadsCount: 2, text: "Generator.next(): IteratorResult" });