Skip to content

Commit 63f43e8

Browse files
committed
Move findPrecedingToken to ServicesSyntaxUtilities
1 parent 49ae281 commit 63f43e8

File tree

4 files changed

+109
-175
lines changed

4 files changed

+109
-175
lines changed

src/services/formatting/smartIndenter.ts

Lines changed: 2 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
module ts.formatting {
44
export module SmartIndenter {
5-
65
export function getIndentation(position: number, sourceFile: SourceFile, options: TypeScript.FormattingOptions): number {
76
if (position > sourceFile.text.length) {
87
return 0; // past EOF
98
}
109

11-
var precedingToken = findPrecedingToken(position, sourceFile);
10+
var precedingToken = ServicesSyntaxUtilities.findPrecedingToken(position, sourceFile);
1211
if (!precedingToken) {
1312
return 0;
1413
}
@@ -137,7 +136,7 @@ module ts.formatting {
137136
}
138137

139138
function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken: Node, current: Node, lineAtPosition: number, sourceFile: SourceFile): boolean {
140-
var nextToken = findNextToken(precedingToken, current);
139+
var nextToken = ServicesSyntaxUtilities.findNextToken(precedingToken, current);
141140
if (!nextToken) {
142141
return false;
143142
}
@@ -288,112 +287,6 @@ module ts.formatting {
288287
return column;
289288
}
290289

291-
function findNextToken(previousToken: Node, parent: Node): Node {
292-
return find(parent);
293-
294-
function find(n: Node): Node {
295-
if (isToken(n) && n.pos === previousToken.end) {
296-
// this is token that starts at the end of previous token - return it
297-
return n;
298-
}
299-
300-
var children = n.getChildren();
301-
for (var i = 0, len = children.length; i < len; ++i) {
302-
var child = children[i];
303-
var shouldDiveInChildNode =
304-
// previous token is enclosed somewhere in the child
305-
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
306-
// previous token ends exactly at the beginning of child
307-
(child.pos === previousToken.end);
308-
309-
if (shouldDiveInChildNode && nodeHasTokens(child)) {
310-
return find(child);
311-
}
312-
}
313-
314-
return undefined;
315-
}
316-
}
317-
318-
function findPrecedingToken(position: number, sourceFile: SourceFile): Node {
319-
return find(sourceFile);
320-
321-
function findRightmostToken(n: Node): Node {
322-
if (isToken(n)) {
323-
return n;
324-
}
325-
326-
var children = n.getChildren();
327-
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
328-
return candidate && findRightmostToken(candidate);
329-
330-
}
331-
332-
function find(n: Node): Node {
333-
if (isToken(n)) {
334-
return n;
335-
}
336-
337-
var children = n.getChildren();
338-
for (var i = 0, len = children.length; i < len; ++i) {
339-
var child = children[i];
340-
if (nodeHasTokens(child)) {
341-
if (position < child.end) {
342-
if (child.getStart(sourceFile) >= position) {
343-
// actual start of the node is past the position - previous token should be at the end of previous child
344-
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
345-
return candidate && findRightmostToken(candidate)
346-
}
347-
else {
348-
// candidate should be in this node
349-
return find(child);
350-
}
351-
}
352-
}
353-
}
354-
355-
Debug.assert(n.kind === SyntaxKind.SourceFile);
356-
357-
// Here we know that none of child token nodes embrace the position,
358-
// the only known case is when position is at the end of the file.
359-
// Try to find the rightmost token in the file without filtering.
360-
// Namely we are skipping the check: 'position < node.end'
361-
if (children.length) {
362-
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
363-
return candidate && findRightmostToken(candidate);
364-
}
365-
}
366-
367-
/// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
368-
function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number): Node {
369-
for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
370-
if (nodeHasTokens(children[i])) {
371-
return children[i];
372-
}
373-
}
374-
}
375-
}
376-
377-
/*
378-
* Checks if node is something that can contain tokens (except EOF) - filters out EOF tokens, Missing\Omitted expressions, empty SyntaxLists and expression statements that wrap any of listed nodes.
379-
*/
380-
function nodeHasTokens(n: Node): boolean {
381-
if (n.kind === SyntaxKind.ExpressionStatement) {
382-
return nodeHasTokens((<ExpressionStatement>n).expression);
383-
}
384-
385-
if (n.kind === SyntaxKind.EndOfFileToken || n.kind === SyntaxKind.OmittedExpression || n.kind === SyntaxKind.Missing) {
386-
return false;
387-
}
388-
389-
// SyntaxList is already realized so getChildCount should be fast and non-expensive
390-
return n.kind !== SyntaxKind.SyntaxList || n.getChildCount() !== 0;
391-
}
392-
393-
function isToken(n: Node): boolean {
394-
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
395-
}
396-
397290
function nodeContentIsIndented(parent: Node, child: Node): boolean {
398291
switch (parent.kind) {
399292
case SyntaxKind.ClassDeclaration:

src/services/services.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
/// <reference path='breakpoints.ts' />
1212
/// <reference path='indentation.ts' />
1313
/// <reference path='signatureInfoHelpers.ts' />
14+
/// <reference path='servicesSyntaxUtilities.ts' />
1415
/// <reference path='formatting\formatting.ts' />
1516
/// <reference path='formatting\smartIndenter.ts' />
1617

@@ -3533,7 +3534,7 @@ module ts {
35333534
if (!isToken || position <= node.getStart() || position >= node.getEnd()) {
35343535
// This is a temporary hack until we figure out our token story.
35353536
// The correct solution is to get the previous token
3536-
node = SignatureInfoHelpers.findPrecedingToken(position, sourceFile);
3537+
node = ServicesSyntaxUtilities.findPrecedingToken(position, sourceFile);
35373538

35383539
if (!node) {
35393540
return undefined;
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// These utilities are common to multiple language service features.
2+
module ts.ServicesSyntaxUtilities {
3+
export function findNextToken(previousToken: Node, parent: Node): Node {
4+
return find(parent);
5+
6+
function find(n: Node): Node {
7+
if (isToken(n) && n.pos === previousToken.end) {
8+
// this is token that starts at the end of previous token - return it
9+
return n;
10+
}
11+
12+
var children = n.getChildren();
13+
for (var i = 0, len = children.length; i < len; ++i) {
14+
var child = children[i];
15+
var shouldDiveInChildNode =
16+
// previous token is enclosed somewhere in the child
17+
(child.pos <= previousToken.pos && child.end > previousToken.end) ||
18+
// previous token ends exactly at the beginning of child
19+
(child.pos === previousToken.end);
20+
21+
if (shouldDiveInChildNode && nodeHasTokens(child)) {
22+
return find(child);
23+
}
24+
}
25+
26+
return undefined;
27+
}
28+
}
29+
30+
export function findPrecedingToken(position: number, sourceFile: SourceFile): Node {
31+
return find(sourceFile);
32+
33+
function findRightmostToken(n: Node): Node {
34+
if (isToken(n)) {
35+
return n;
36+
}
37+
38+
var children = n.getChildren();
39+
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
40+
return candidate && findRightmostToken(candidate);
41+
42+
}
43+
44+
function find(n: Node): Node {
45+
if (isToken(n)) {
46+
return n;
47+
}
48+
49+
var children = n.getChildren();
50+
for (var i = 0, len = children.length; i < len; ++i) {
51+
var child = children[i];
52+
if (nodeHasTokens(child)) {
53+
if (position < child.end) {
54+
if (child.getStart(sourceFile) >= position) {
55+
// actual start of the node is past the position - previous token should be at the end of previous child
56+
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ i);
57+
return candidate && findRightmostToken(candidate)
58+
}
59+
else {
60+
// candidate should be in this node
61+
return find(child);
62+
}
63+
}
64+
}
65+
}
66+
67+
Debug.assert(n.kind === SyntaxKind.SourceFile);
68+
69+
// Here we know that none of child token nodes embrace the position,
70+
// the only known case is when position is at the end of the file.
71+
// Try to find the rightmost token in the file without filtering.
72+
// Namely we are skipping the check: 'position < node.end'
73+
if (children.length) {
74+
var candidate = findRightmostChildNodeWithTokens(children, /*exclusiveStartPosition*/ children.length);
75+
return candidate && findRightmostToken(candidate);
76+
}
77+
}
78+
79+
/// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
80+
function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number): Node {
81+
for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
82+
if (nodeHasTokens(children[i])) {
83+
return children[i];
84+
}
85+
}
86+
}
87+
}
88+
89+
function nodeHasTokens(n: Node): boolean {
90+
if (n.kind === SyntaxKind.ExpressionStatement) {
91+
return nodeHasTokens((<ExpressionStatement>n).expression);
92+
}
93+
94+
if (n.kind === SyntaxKind.EndOfFileToken || n.kind === SyntaxKind.OmittedExpression || n.kind === SyntaxKind.Missing) {
95+
return false;
96+
}
97+
98+
// SyntaxList is already realized so getChildCount should be fast and non-expensive
99+
return n.kind !== SyntaxKind.SyntaxList || n.getChildCount() !== 0;
100+
}
101+
102+
function isToken(n: Node): boolean {
103+
return n.kind >= SyntaxKind.FirstToken && n.kind <= SyntaxKind.LastToken;
104+
}
105+
}

src/services/signatureInfoHelpers.ts

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -345,70 +345,5 @@ module ts {
345345
// return null;
346346
//}
347347

348-
export function findPrecedingToken(position: number, sourceFile: SourceFile): Node {
349-
return find(sourceFile, /*diveIntoLastChild*/ false);
350-
351-
function find(n: Node, diveIntoLastChild: boolean): Node {
352-
if (isToken(n)) {
353-
return n;
354-
}
355-
356-
var children = n.getChildren();
357-
if (diveIntoLastChild) {
358-
var candidate = findLastChildNodeCandidate(children, /*exclusiveStartPosition*/ children.length);
359-
return candidate && find(candidate, /*diveIntoLastChild*/ true);
360-
}
361-
362-
for (var i = 0, len = children.length; i < len; ++i) {
363-
var child = children[i];
364-
if (nodeHasTokens(child)) {
365-
if (position < child.end) {
366-
if (child.getStart() >= position) {
367-
// actual start of the node is past the position - previous token should be at the end of previous child
368-
var candidate = findLastChildNodeCandidate(children, /*exclusiveStartPosition*/ i);
369-
return candidate && find(candidate, /*diveIntoLastChild*/ true)
370-
}
371-
else {
372-
// candidate should be in this node
373-
return find(child, diveIntoLastChild);
374-
}
375-
}
376-
}
377-
}
378-
379-
// here we know that none of child token nodes embrace the position
380-
// try to find the closest token on the left
381-
if (children.length) {
382-
var candidate = findLastChildNodeCandidate(children, /*exclusiveStartPosition*/ children.length);
383-
return candidate && find(candidate, /*diveIntoLastChild*/ true);
384-
}
385-
}
386-
387-
/// finds last node that is considered as candidate for search (isCandidate(node) === true) starting from 'exclusiveStartPosition'
388-
function findLastChildNodeCandidate(children: Node[], exclusiveStartPosition: number): Node {
389-
for (var i = exclusiveStartPosition - 1; i >= 0; --i) {
390-
if (nodeHasTokens(children[i])) {
391-
return children[i];
392-
}
393-
}
394-
}
395-
396-
function isToken(n: Node): boolean {
397-
return n.kind < SyntaxKind.Missing;
398-
}
399-
400-
function nodeHasTokens(n: Node): boolean {
401-
if (n.kind === SyntaxKind.ExpressionStatement) {
402-
return nodeHasTokens((<ExpressionStatement>n).expression);
403-
}
404-
405-
if (n.kind === SyntaxKind.EndOfFileToken || n.kind === SyntaxKind.OmittedExpression || n.kind === SyntaxKind.Missing) {
406-
return false;
407-
}
408-
409-
// SyntaxList is already realized so getChildCount should be fast and non-expensive
410-
return n.kind !== SyntaxKind.SyntaxList || n.getChildCount() !== 0;
411-
}
412-
}
413348
}
414349
}

0 commit comments

Comments
 (0)