From 5e1bd0c5bfed2f3f54cd45b1aec09b999fe0b97f Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 17 Sep 2014 15:32:33 -0700 Subject: [PATCH] Add applicableSpan to SignatureHelpItems --- src/services/services.ts | 57 +++++++++++++++---------- src/services/servicesSyntaxUtilities.ts | 7 ++- tests/cases/fourslash/fourslash.ts | 2 +- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index 986b4de88a3..0117af0ab70 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3483,32 +3483,43 @@ module ts { function getSignatureHelpItems(fileName: string, position: number): SignatureHelpItems { // If node is an argument, returns its index in the argument list // If not, returns -1 - function getArgumentIndex(node: Node): number { + function getArgumentIndexInfo(node: Node): ServicesSyntaxUtilities.ListItemInfo { if (node.parent.kind !== SyntaxKind.CallExpression && node.parent.kind !== SyntaxKind.NewExpression) { - return -1; + return undefined; } var parent = node.parent; // Find out if 'node' is an argument, a type argument, or neither - // Treat the open paren / angle bracket of a call as the introduction of parameter slot 0 if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) { - return 0; + // Find the list that starts right *after* the < or ( token + var seenRelevantOpenerToken = false; + var list = forEach(parent.getChildren(), c => { + if (seenRelevantOpenerToken) { + Debug.assert(c.kind === SyntaxKind.SyntaxList); + return c; + } + if (c.kind === node.kind /*node is the relevant opener token we are looking for*/) { + seenRelevantOpenerToken = true; + } + }); + Debug.assert(list); + // Treat the open paren / angle bracket of a call as the introduction of parameter slot 0 + return { + listItemIndex: 0, + list: list + }; } if (node.kind === SyntaxKind.GreaterThanToken || node.kind === SyntaxKind.CloseParenToken || node === parent.func) { - return -1; + return undefined; } - return ServicesSyntaxUtilities.findListItemInfo(node).listItemIndex; + return ServicesSyntaxUtilities.findListItemInfo(node); } - function getSignatureHelpArgumentContext(node: Node): { - argumentNode: Node; - argumentIndex: number; - isTypeArgument: boolean; - } { + function getSignatureHelpArgumentContext(node: Node): ServicesSyntaxUtilities.ListItemInfo { // We only want this node if it is a token and it strictly contains the current position. // Otherwise we want the previous token var isToken = node.kind < SyntaxKind.Missing; @@ -3526,13 +3537,9 @@ module ts { return undefined; } - var index = getArgumentIndex(n); - if (index >= 0) { - return { - argumentNode: n, - argumentIndex: index, - isTypeArgument: false - } + var argumentInfo = getArgumentIndexInfo(n); + if (argumentInfo) { + return argumentInfo; } @@ -3542,13 +3549,17 @@ module ts { return undefined; } - function getSignatureHelpItemsFromCandidateInfo(candidates: Signature[], bestSignature: Signature): SignatureHelpItems { + function getSignatureHelpItemsFromCandidateInfo(candidates: Signature[], bestSignature: Signature, argumentListOrTypeArgumentList: Node): SignatureHelpItems { var items = map(candidates, candidateSignature => { return new SignatureHelpItem(false, "", "", "", new Array(candidateSignature.parameters.length), ""); }); var selectedItemIndex = candidates.indexOf(bestSignature); - Debug.assert(selectedItemIndex >= 0); - return new SignatureHelpItems(items, undefined, selectedItemIndex); + if (selectedItemIndex < 0) { + selectedItemIndex = 0; + } + + var applicableSpan = new TypeScript.TextSpan(argumentListOrTypeArgumentList.getFullStart(), argumentListOrTypeArgumentList.end); + return new SignatureHelpItems(items, applicableSpan, selectedItemIndex); } synchronizeHostData(); @@ -3561,11 +3572,11 @@ module ts { // Semantic filtering of signature help var signatureHelpContext = getSignatureHelpArgumentContext(node); if (signatureHelpContext) { - var call = signatureHelpContext.argumentNode.parent; + var call = signatureHelpContext.list.parent; var candidates = []; var resolvedSignature = typeInfoResolver.getResolvedSignature(call, candidates); return candidates.length - ? getSignatureHelpItemsFromCandidateInfo(candidates, resolvedSignature) + ? getSignatureHelpItemsFromCandidateInfo(candidates, resolvedSignature, signatureHelpContext.list) : undefined; } diff --git a/src/services/servicesSyntaxUtilities.ts b/src/services/servicesSyntaxUtilities.ts index 63252c29f4b..5c72428bd04 100644 --- a/src/services/servicesSyntaxUtilities.ts +++ b/src/services/servicesSyntaxUtilities.ts @@ -1,6 +1,11 @@ // These utilities are common to multiple language service features. module ts.ServicesSyntaxUtilities { - export function findListItemInfo(node: Node): { listItemIndex: number; list: Node } { + export interface ListItemInfo { + listItemIndex: number; + list: Node; + } + + export function findListItemInfo(node: Node): ListItemInfo { // The node might be a list element (nonsynthetic) or a comma (synthetic). Either way, it will // be parented by the container of the SyntaxList, not the SyntaxList itself. // In order to find the list item index, we first need to locate SyntaxList itself and then search diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 99b73231c7e..e824165283a 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -275,7 +275,7 @@ module FourSlashInterface { } public currentParameterHelpArgumentNameIs(name: string) { - // FourSlash.currentTestState.verifyCurrentParameterHelpName(name); + FourSlash.currentTestState.verifyCurrentParameterHelpName(name); } public currentParameterSpanIs(parameter: string) {