From 67516a1f615d7bd3c66d4436e06bb03e4de02b8e Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Tue, 16 Sep 2014 14:36:52 -0700 Subject: [PATCH] Extract findListItem from smart indenter --- src/compiler/core.ts | 6 ++-- src/services/formatting/smartIndenter.ts | 27 +++----------- src/services/services.ts | 36 +++---------------- src/services/servicesSyntaxUtilities.ts | 21 +++++++++++ .../fourslash/signatureHelpNegativeTests2.ts | 4 +-- 5 files changed, 36 insertions(+), 58 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 6bfa537c9f2..79b0c9aca83 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -11,10 +11,12 @@ module ts { var result: U; if (array) { for (var i = 0, len = array.length; i < len; i++) { - if (result = callback(array[i])) break; + if (result = callback(array[i])) { + return result; + } } } - return result; + return undefined; } export function contains(array: T[], value: T): boolean { diff --git a/src/services/formatting/smartIndenter.ts b/src/services/formatting/smartIndenter.ts index 1e8c175937c..14abf1850c4 100644 --- a/src/services/formatting/smartIndenter.ts +++ b/src/services/formatting/smartIndenter.ts @@ -107,8 +107,10 @@ module ts.formatting { */ function getActualIndentationForListItemBeforeComma(commaToken: Node, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number { // previous token is comma that separates items in list - find the previous item and try to derive indentation from it - var itemInfo = findPrecedingListItem(commaToken); - return deriveActualIndentationFromList(itemInfo.list.getChildren(), itemInfo.listItemIndex, sourceFile, options); + var commaItemInfo = ServicesSyntaxUtilities.findListItemInfo(commaToken); + Debug.assert(commaItemInfo.listItemIndex > 0); + // The item we're interested in is right before the comma + return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options); } /* @@ -166,27 +168,6 @@ module ts.formatting { return sourceFile.getLineAndCharacterFromPosition(n.getStart(sourceFile)); } - function findPrecedingListItem(commaToken: Node): { listItemIndex: number; list: Node } { - // CommaToken node is synthetic and thus will be stored in SyntaxList, however parent of the CommaToken points to the container of the SyntaxList skipping the list. - // In order to find the preceding list item we first need to locate SyntaxList itself and then search for the position of CommaToken - var syntaxList = forEach(commaToken.parent.getChildren(), c => { - // find syntax list that covers the span of CommaToken - if (c.kind == SyntaxKind.SyntaxList && c.pos <= commaToken.end && c.end >= commaToken.end) { - return c; - } - }); - Debug.assert(syntaxList); - - var children = syntaxList.getChildren(); - var commaIndex = indexOf(children, commaToken); - Debug.assert(commaIndex !== -1 && commaIndex !== 0); - - return { - listItemIndex: commaIndex - 1, - list: syntaxList - }; - } - function positionBelongsToNode(candidate: Node, position: number, sourceFile: SourceFile): boolean { return candidate.end > position || !isCompletedNode(candidate, sourceFile); } diff --git a/src/services/services.ts b/src/services/services.ts index 537144f9a9d..2d3e60d0df9 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -3495,32 +3495,13 @@ module ts { return 0; } - var argumentListOrTypeArgumentList: NodeArray; - if (parent.typeArguments && node.pos >= parent.typeArguments.pos && node.end <= parent.typeArguments.end) { - argumentListOrTypeArgumentList = parent.typeArguments; - } - else if (parent.arguments && node.pos >= parent.arguments.pos && node.end <= parent.arguments.end) { - argumentListOrTypeArgumentList = parent.arguments; + if (node.kind === SyntaxKind.GreaterThanToken + || node.kind === SyntaxKind.CloseParenToken + || node === parent.func) { + return -1; } - return argumentListOrTypeArgumentList ? argumentListOrTypeArgumentList.indexOf(node) : -1; - - // if (parent.kind === SyntaxKind.SyntaxList) { - // var grandparent = parent.parent; - // if (grandparent.kind === SyntaxKind.CallExpression || grandparent.kind === SyntaxKind.NewExpression) { - // var index = (parent).getIndexOfChild(node); - // Debug.assert(index >= 0); - // return index; - // } - // } - - // if (node.kind === SyntaxKind.LessThanToken || node.kind === SyntaxKind.OpenParenToken) { - // return parent.kind === SyntaxKind.CallExpression || parent.kind === SyntaxKind.NewExpression - // ? 0 - // : -1; - // } - - // TODO: Handle close paren or close angle bracket on nonempty list + return ServicesSyntaxUtilities.findListItemInfo(node).listItemIndex; } function getSignatureHelpArgumentContext(node: Node): { @@ -3532,18 +3513,11 @@ module ts { // Otherwise we want the previous token var isToken = node.kind < SyntaxKind.Missing; if (!isToken || position <= node.getStart() || position >= node.getEnd()) { - // This is a temporary hack until we figure out our token story. - // The correct solution is to get the previous token node = ServicesSyntaxUtilities.findPrecedingToken(position, sourceFile); if (!node) { return undefined; } - if (node.parent.kind === SyntaxKind.CallExpression || node.parent.kind === SyntaxKind.NewExpression) { - if (node === (node.parent).func) { - node = node.parent.getChildAt(1); - } - } } var signatureHelpAvailable = false; diff --git a/src/services/servicesSyntaxUtilities.ts b/src/services/servicesSyntaxUtilities.ts index e6d74568261..63252c29f4b 100644 --- a/src/services/servicesSyntaxUtilities.ts +++ b/src/services/servicesSyntaxUtilities.ts @@ -1,5 +1,26 @@ // These utilities are common to multiple language service features. module ts.ServicesSyntaxUtilities { + export function findListItemInfo(node: Node): { listItemIndex: number; list: Node } { + // 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 + // for the position of the relevant node (or comma). + var syntaxList = forEach(node.parent.getChildren(), c => { + // find syntax list that covers the span of the node + if (c.kind == SyntaxKind.SyntaxList && c.pos <= node.pos && c.end >= node.end) { + return c; + } + }); + + var children = syntaxList.getChildren(); + var index = indexOf(children, node); + + return { + listItemIndex: index, + list: syntaxList + }; + } + export function findNextToken(previousToken: Node, parent: Node): Node { return find(parent); diff --git a/tests/cases/fourslash/signatureHelpNegativeTests2.ts b/tests/cases/fourslash/signatureHelpNegativeTests2.ts index 0302736ee97..28f25063ddf 100644 --- a/tests/cases/fourslash/signatureHelpNegativeTests2.ts +++ b/tests/cases/fourslash/signatureHelpNegativeTests2.ts @@ -1,10 +1,10 @@ /// ////class clsOverload { constructor(); constructor(test: string); constructor(test?: string) { } } -////var x = new clsOverload/*beforeOpenParen*/()/*afterOpenParen*/; +////var x = new clsOverload/*beforeOpenParen*/()/*afterCloseParen*/; goTo.marker('beforeOpenParen'); verify.not.signatureHelpPresent(); -goTo.marker('afterOpenParen'); +goTo.marker('afterCloseParen'); verify.not.signatureHelpPresent(); \ No newline at end of file