From 8d66d55de1bd3b2c3aa4a8d80e515df6f265d174 Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Mon, 25 Feb 2019 18:18:00 +0200 Subject: [PATCH 1/2] Improved argument description for parameters originating from tuples that were extracted from functions. (ie mapped functions) --- src/compiler/checker.ts | 1 + src/compiler/types.ts | 1 + src/services/signatureHelp.ts | 13 ++++- .../signatureHelpCallExpressionTuples.ts | 56 +++++++++++++++++++ 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 tests/cases/fourslash/signatureHelpCallExpressionTuples.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 958ceae0395a2..43ca06fa21dc9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -112,6 +112,7 @@ namespace ts { getMergedSymbol, getDiagnostics, getGlobalDiagnostics, + getExpandedParameters, getTypeOfSymbolAtLocation: (symbol, location) => { location = getParseTreeNode(location); return location ? getTypeOfSymbolAtLocation(symbol, location) : errorType; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index cce869df44ea1..21389cb2e765a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3032,6 +3032,7 @@ namespace ts { /* @internal */ getPromisedTypeOfPromise(promise: Type, errorNode?: Node): Type | undefined; getReturnTypeOfSignature(signature: Signature): Type; + /* @internal */ getExpandedParameters(sig: Signature): ReadonlyArray; /** * Gets the type of a parameter at a given position in a signature. * Returns `any` if the index is not valid. diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 27ed0b6dc24a9..41bc068c77615 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -566,7 +566,7 @@ namespace ts.SignatureHelp { } function itemInfoForParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo { - const isVariadic = candidateSignature.hasRestParameter; + let isVariadic = candidateSignature.hasRestParameter; const printer = createPrinter({ removeComments: true }); const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { @@ -574,7 +574,16 @@ namespace ts.SignatureHelp { printer.writeList(ListFormat.TypeParameters, args, sourceFile, writer); } }); - const parameters = candidateSignature.parameters.map(p => createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer)); + + const expandedParameters = checker.getExpandedParameters(candidateSignature); + const parameters = expandedParameters.map(p => createSignatureHelpParameterForParameter(p, checker, enclosingDeclaration, sourceFile, printer)); + + // If parameters are not the same as the expanded parameters, we need to reevaluate whether this a variadic signature based on the last parameter + if (expandedParameters !== candidateSignature.parameters) { + const restCandidate = lastOrUndefined(expandedParameters); + isVariadic = !!restCandidate && !!(getCheckFlags(restCandidate) & CheckFlags.RestParameter); + } + return { isVariadic, parameters, prefix: [...typeParameterParts, punctuationPart(SyntaxKind.OpenParenToken)], suffix: [punctuationPart(SyntaxKind.CloseParenToken)] }; } diff --git a/tests/cases/fourslash/signatureHelpCallExpressionTuples.ts b/tests/cases/fourslash/signatureHelpCallExpressionTuples.ts new file mode 100644 index 0000000000000..bcad3ccde4894 --- /dev/null +++ b/tests/cases/fourslash/signatureHelpCallExpressionTuples.ts @@ -0,0 +1,56 @@ +/// + + +//// function fnTest(str: string, num: number) { } +//// declare function wrap(fn: (...a: A) => R) : (...a: A) => R; +//// var fnWrapped = wrap(fnTest); +//// fnWrapped/*3*/(/*1*/'', /*2*/5); +//// function fnTestVariadic (str: string, ...num: number[]) { } +//// var fnVariadicWrapped = wrap(fnTestVariadic); +//// fnVariadicWrapped/*4*/(/*5*/'', /*6*/5); +//// function fnNoParams () { } +//// var fnNoParamsWrapped = wrap(fnNoParams); +//// fnNoParamsWrapped/*7*/(/*8*/); + +verify.quickInfoAt("3", "var fnWrapped: (str: string, num: number) => void"); +verify.signatureHelp( + { + marker: "1", + text: "fnWrapped(str: string, num: number): void", + parameterCount: 2, + parameterName: "str", + parameterSpan: "str: string", + }, + { + marker: "2", + parameterName: "num", + parameterSpan: "num: number", + }, +); + +verify.quickInfoAt("4", "var fnVariadicWrapped: (str: string, ...num: number[]) => void"); +verify.signatureHelp( + { + marker: "5", + text: "fnVariadicWrapped(str: string, ...num: number[]): void", + parameterCount: 2, + parameterName: "str", + parameterSpan: "str: string", + isVariadic: true, + }, + { + marker: "6", + parameterName: "num", + parameterSpan: "...num: number[]", + isVariadic: true, + }, +); + +verify.quickInfoAt("7", "var fnNoParamsWrapped: () => void"); +verify.signatureHelp( + { + marker: "8", + text: "fnNoParamsWrapped(): void", + parameterCount: 0, + } +); From d433042386d93a512586fdde0d274e67d78b5088 Mon Sep 17 00:00:00 2001 From: Titian Cernicova-Dragomir Date: Mon, 11 Mar 2019 02:55:10 +0200 Subject: [PATCH 2/2] Fixed isVariadic handling when signature parameters are expanded for itemInfoForParameters --- src/compiler/checker.ts | 1 + src/compiler/types.ts | 2 +- src/services/signatureHelp.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1b0904723dfd0..3791124a2a26e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -232,6 +232,7 @@ namespace ts { getResolvedSignatureForSignatureHelp: (node, candidatesOutArray, agumentCount) => getResolvedSignatureWorker(node, candidatesOutArray, agumentCount, CheckMode.IsForSignatureHelp), getExpandedParameters, + hasEffectiveRestParameter, getConstantValue: nodeIn => { const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 2d5f084434cde..83bcf01742d5f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3093,7 +3093,6 @@ namespace ts { /* @internal */ getPromisedTypeOfPromise(promise: Type, errorNode?: Node): Type | undefined; getReturnTypeOfSignature(signature: Signature): Type; - /* @internal */ getExpandedParameters(sig: Signature): ReadonlyArray; /** * Gets the type of a parameter at a given position in a signature. * Returns `any` if the index is not valid. @@ -3172,6 +3171,7 @@ namespace ts { getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; /* @internal */ getResolvedSignatureForSignatureHelp(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; /* @internal */ getExpandedParameters(sig: Signature): ReadonlyArray; + /* @internal */ hasEffectiveRestParameter(sig: Signature): boolean; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 5e7b160e326c5..0c9f76acacb7f 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -566,7 +566,7 @@ namespace ts.SignatureHelp { } function itemInfoForParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo { - let isVariadic = candidateSignature.hasRestParameter; + const isVariadic = checker.hasEffectiveRestParameter(candidateSignature); const printer = createPrinter({ removeComments: true }); const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {