mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-17 21:06:50 -05:00
Signature help: support non-trailing rest parameters
In signature help, the first rest parameter will always be the *last*
'current' parameter (disregarding types). Previously, the signature help
current-parameter highlight was only correct for trailing rest
parameters. However, with tuple types, you can now create non-trailing
rest parameters. This PR now correctly highlights non-trailing rest
parameters as the last 'current' parameter.
For example, `names` should be the current parameter in all the calls
below:
```ts
declare function loading(...args: [...names: string[], allCaps: boolean, extra: boolean]): void;
leading(/**/
leading('one', /**/
leading('one', 'two', /**/
```
And, because signature help doesn't do real overload resolution, `names`
is also the current parameter for other calls:
```ts
leading(1, 2, 3, 'ill-typed', /**/
leading('fine', true, /**/
```
This commit is contained in:
@@ -517,7 +517,6 @@ namespace ts.SignatureHelp {
|
||||
if (argumentIndex !== 0) {
|
||||
Debug.assertLessThan(argumentIndex, argumentCount);
|
||||
}
|
||||
|
||||
let selectedItemIndex = 0;
|
||||
let itemsSeen = 0;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
@@ -541,8 +540,15 @@ namespace ts.SignatureHelp {
|
||||
}
|
||||
|
||||
Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function.
|
||||
|
||||
return { items: flatMapToMutable(items, identity), applicableSpan, selectedItemIndex, argumentIndex, argumentCount };
|
||||
const help = { items: flatMapToMutable(items, identity), applicableSpan, selectedItemIndex, argumentIndex, argumentCount };
|
||||
const selected = help.items[selectedItemIndex];
|
||||
if (selected.isVariadic) {
|
||||
const firstVariadic = findIndex(selected.parameters, p => !!p.isVariadic);
|
||||
if (firstVariadic > -1 && help.argumentIndex > firstVariadic) {
|
||||
help.argumentIndex = firstVariadic;
|
||||
}
|
||||
}
|
||||
return help;
|
||||
}
|
||||
|
||||
function createTypeHelpItems(
|
||||
@@ -638,8 +644,9 @@ namespace ts.SignatureHelp {
|
||||
const param = checker.symbolToParameterDeclaration(parameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!;
|
||||
printer.writeNode(EmitHint.Unspecified, param, sourceFile, writer);
|
||||
});
|
||||
const isOptional = checker.isOptionalParameter(<ParameterDeclaration>parameter.valueDeclaration);
|
||||
return { name: parameter.name, documentation: parameter.getDocumentationComment(checker), displayParts, isOptional };
|
||||
const isOptional = checker.isOptionalParameter(parameter.valueDeclaration as ParameterDeclaration);
|
||||
const isVariadic = !!((parameter as TransientSymbol).checkFlags & CheckFlags.RestParameter);
|
||||
return { name: parameter.name, documentation: parameter.getDocumentationComment(checker), displayParts, isOptional, isVariadic };
|
||||
}
|
||||
|
||||
function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile, printer: Printer): SignatureHelpParameter {
|
||||
@@ -647,6 +654,6 @@ namespace ts.SignatureHelp {
|
||||
const param = checker.typeParameterToDeclaration(typeParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!;
|
||||
printer.writeNode(EmitHint.Unspecified, param, sourceFile, writer);
|
||||
});
|
||||
return { name: typeParameter.symbol.name, documentation: typeParameter.symbol.getDocumentationComment(checker), displayParts, isOptional: false };
|
||||
return { name: typeParameter.symbol.name, documentation: typeParameter.symbol.getDocumentationComment(checker), displayParts, isOptional: false, isVariadic: false };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1078,6 +1078,7 @@ namespace ts {
|
||||
documentation: SymbolDisplayPart[];
|
||||
displayParts: SymbolDisplayPart[];
|
||||
isOptional: boolean;
|
||||
isVariadic?: boolean;
|
||||
}
|
||||
|
||||
export interface SelectionRange {
|
||||
|
||||
38
tests/cases/fourslash/signatureHelpLeadingRestTuple.ts
Normal file
38
tests/cases/fourslash/signatureHelpLeadingRestTuple.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////export function leading(...args: [...names: string[], allCaps: boolean]): void {
|
||||
////}
|
||||
////
|
||||
////leading(/*1*/);
|
||||
////leading("ok", /*2*/);
|
||||
////leading("ok", "ok", /*3*/);
|
||||
|
||||
verify.signatureHelp(
|
||||
{
|
||||
marker: "1",
|
||||
text: "leading(...names: string[], allCaps: boolean): void",
|
||||
overloadsCount: 1,
|
||||
parameterCount: 2,
|
||||
parameterName: "names",
|
||||
parameterSpan: "...names: string[]",
|
||||
isVariadic: true,
|
||||
},
|
||||
{
|
||||
marker: "2",
|
||||
text: "leading(...names: string[], allCaps: boolean): void",
|
||||
overloadsCount: 1,
|
||||
parameterCount: 2,
|
||||
parameterName: "names",
|
||||
parameterSpan: "...names: string[]",
|
||||
isVariadic: true,
|
||||
},
|
||||
{
|
||||
marker: "3",
|
||||
text: "leading(...names: string[], allCaps: boolean): void",
|
||||
overloadsCount: 1,
|
||||
parameterCount: 2,
|
||||
parameterName: "names",
|
||||
parameterSpan: "...names: string[]",
|
||||
isVariadic: true,
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user