Skip to content

Commit 35cdea1

Browse files
committed
Breakpointspan implementation for function declaration, expression statements and return statements
1 parent cec8146 commit 35cdea1

File tree

3 files changed

+254
-0
lines changed

3 files changed

+254
-0
lines changed

src/services/breakpoints.ts

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ module ts.BreakpointResolver {
4242
}
4343
}
4444

45+
function spanInPreviousNode(node: Node): TypeScript.TextSpan {
46+
return spanInNode(findPrecedingToken(node.pos, sourceFile));
47+
}
48+
4549
function spanInNode(node: Node): TypeScript.TextSpan {
4650
if (node) {
4751
switch (node.kind) {
@@ -51,10 +55,41 @@ module ts.BreakpointResolver {
5155
case SyntaxKind.VariableDeclaration:
5256
return spanInVariableDeclaration(<VariableDeclaration>node);
5357

58+
case SyntaxKind.Parameter:
59+
return spanInParameterDeclaration(<ParameterDeclaration>node);
60+
61+
case SyntaxKind.FunctionDeclaration:
62+
return spanInFunctionDeclaration(<FunctionDeclaration>node);
63+
64+
case SyntaxKind.FunctionBlock:
65+
return spanInBlock(<Block>node);
66+
67+
case SyntaxKind.ExpressionStatement:
68+
return spanInExpressionStatement(<ExpressionStatement>node);
69+
70+
case SyntaxKind.ReturnStatement:
71+
return spanInReturnStatement(<ReturnStatement>node);
72+
73+
// Tokens:
5474
case SyntaxKind.SemicolonToken:
5575
case SyntaxKind.EndOfFileToken:
5676
return spanInNodeIfStartsOnSameLine(findPrecedingToken(node.pos, sourceFile));
5777

78+
case SyntaxKind.CommaToken:
79+
return spanInCommaToken(node);
80+
81+
case SyntaxKind.OpenBraceToken:
82+
return spanInOpenBraceToken(node);
83+
84+
case SyntaxKind.CloseBraceToken:
85+
return spanInCloseBraceToken(node);
86+
87+
case SyntaxKind.CloseParenToken:
88+
return spanInCloseParenToken(node);
89+
90+
case SyntaxKind.ColonToken:
91+
return spanInColonToken(node);
92+
5893
default:
5994
// Default go to parent to set the breakpoint
6095
return spanInNode(node.parent);
@@ -88,6 +123,123 @@ module ts.BreakpointResolver {
88123
function spanInVariableStatement(variableStatement: VariableStatement): TypeScript.TextSpan {
89124
return spanInVariableDeclaration(variableStatement.declarations[0]);
90125
}
126+
127+
function canHaveSpanInParameterDeclaration(parameter: ParameterDeclaration): boolean {
128+
// Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier
129+
return !!parameter.initializer || !!(parameter.flags & NodeFlags.Rest) ||
130+
!!(parameter.flags & NodeFlags.Public) || !!(parameter.flags & NodeFlags.Private);
131+
}
132+
133+
function spanInParameterDeclaration(parameter: ParameterDeclaration): TypeScript.TextSpan {
134+
if (canHaveSpanInParameterDeclaration(parameter)) {
135+
return textSpan(parameter);
136+
}
137+
else {
138+
var functionDeclaration = <FunctionDeclaration>parameter.parent;
139+
var indexOfParameter = indexOf(functionDeclaration.parameters, parameter);
140+
if (indexOfParameter) {
141+
// Not a first parameter, go to previous parameter
142+
return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]);
143+
}
144+
else {
145+
// Set breakpoint in the function declaration body
146+
return spanInNode(functionDeclaration.body);
147+
}
148+
}
149+
}
150+
151+
function spanInFunctionDeclaration(functionDeclaration: FunctionDeclaration): TypeScript.TextSpan {
152+
// No breakpoints in the function signature
153+
if (!functionDeclaration.body) {
154+
return;
155+
}
156+
157+
// Is this coming because the touchingToken was in typeAnnotation of return type
158+
if (functionDeclaration.type) {
159+
for (var node = tokenAtLocation; node; node = node.parent) {
160+
if (node.parent === functionDeclaration && functionDeclaration.type === node) {
161+
if (functionDeclaration.parameters && functionDeclaration.parameters.length) {
162+
// Set breakpoint in last parameter
163+
return spanInParameterDeclaration(functionDeclaration.parameters[functionDeclaration.parameters.length - 1]);
164+
}
165+
166+
// Set breakpoint in function body
167+
break;
168+
}
169+
}
170+
}
171+
172+
// Set span in function body
173+
return spanInNode(functionDeclaration.body);
174+
}
175+
176+
function spanInBlock(block: Block): TypeScript.TextSpan {
177+
// Set breakpoint in first statement
178+
return spanInNode(block.statements[0]);
179+
}
180+
181+
function spanInExpressionStatement(expressionStatement: ExpressionStatement): TypeScript.TextSpan {
182+
return textSpan(expressionStatement.expression);
183+
}
184+
185+
function spanInReturnStatement(returnStatement: ReturnStatement): TypeScript.TextSpan {
186+
return textSpan(returnStatement.getChildAt(0, sourceFile), returnStatement.expression);
187+
}
188+
189+
// Tokens:
190+
function spanInCommaToken(node: Node): TypeScript.TextSpan {
191+
switch (node.parent.kind) {
192+
case SyntaxKind.FunctionDeclaration:
193+
case SyntaxKind.VariableStatement:
194+
return spanInPreviousNode(node);
195+
196+
// Default to parent node
197+
default:
198+
return spanInNode(node.parent);
199+
}
200+
}
201+
202+
function spanInOpenBraceToken(node: Node): TypeScript.TextSpan {
203+
switch (node.parent.kind) {
204+
case SyntaxKind.FunctionBlock:
205+
return spanInBlock(<Block>node.parent);
206+
207+
// Default to parent node
208+
default:
209+
return spanInNode(node.parent);
210+
}
211+
}
212+
213+
function spanInCloseBraceToken(node: Node): TypeScript.TextSpan {
214+
switch (node.parent.kind) {
215+
case SyntaxKind.FunctionBlock:
216+
// Span on close brace token
217+
return textSpan(node);
218+
219+
// Default to parent node
220+
default:
221+
return spanInNode(node.parent);
222+
}
223+
}
224+
225+
function spanInCloseParenToken(node: Node): TypeScript.TextSpan {
226+
// Is this close paren token of parameter list, set span in previous token
227+
if (isAnyFunction(node.parent)) {
228+
return spanInPreviousNode(node);
229+
}
230+
231+
// Default to parent node
232+
return spanInNode(node.parent);
233+
}
234+
235+
function spanInColonToken(node: Node): TypeScript.TextSpan {
236+
// Is this : specifying return annotation of the function declaration
237+
if (isAnyFunction(node.parent)) {
238+
return spanInPreviousNode(node);
239+
}
240+
241+
return spanInNode(node.parent);
242+
}
91243
}
92244
}
93245
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
2+
1 >var greetings = 0;
3+
4+
~~~~~~~~~~~~~~~~~~~ => Pos: (0 to 18) SpanInfo: {"start":0,"length":17}
5+
>var greetings = 0
6+
>:=> (line 1, col 0) to (line 1, col 17)
7+
--------------------------------
8+
2 >function greet(greeting: string): number {
9+
10+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (19 to 61) SpanInfo: {"start":66,"length":11}
11+
>greetings++
12+
>:=> (line 3, col 4) to (line 3, col 15)
13+
--------------------------------
14+
3 > greetings++;
15+
16+
~~~~~~~~~~~~~~~~~ => Pos: (62 to 78) SpanInfo: {"start":66,"length":11}
17+
>greetings++
18+
>:=> (line 3, col 4) to (line 3, col 15)
19+
--------------------------------
20+
4 > return greetings;
21+
22+
~~~~~~~~~~~~~~~~~~~~~~ => Pos: (79 to 100) SpanInfo: {"start":83,"length":16}
23+
>return greetings
24+
>:=> (line 4, col 4) to (line 4, col 20)
25+
--------------------------------
26+
5 >}
27+
28+
~~ => Pos: (101 to 102) SpanInfo: {"start":101,"length":1}
29+
>}
30+
>:=> (line 5, col 0) to (line 5, col 1)
31+
--------------------------------
32+
6 >function greet2(greeting: string, n = 10, x?: string, ...restParams: string[]): number {
33+
34+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (103 to 135) SpanInfo: {"start":196,"length":11}
35+
>greetings++
36+
>:=> (line 7, col 4) to (line 7, col 15)
37+
6 >function greet2(greeting: string, n = 10, x?: string, ...restParams: string[]): number {
38+
39+
~~~~~~~~~~~~~~~~~~~~=> Pos: (136 to 155) SpanInfo: {"start":137,"length":6}
40+
>n = 10
41+
>:=> (line 6, col 34) to (line 6, col 40)
42+
6 >function greet2(greeting: string, n = 10, x?: string, ...restParams: string[]): number {
43+
44+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~=> Pos: (156 to 188) SpanInfo: {"start":157,"length":23}
45+
>...restParams: string[]
46+
>:=> (line 6, col 54) to (line 6, col 77)
47+
6 >function greet2(greeting: string, n = 10, x?: string, ...restParams: string[]): number {
48+
49+
~~~=> Pos: (189 to 191) SpanInfo: {"start":196,"length":11}
50+
>greetings++
51+
>:=> (line 7, col 4) to (line 7, col 15)
52+
--------------------------------
53+
7 > greetings++;
54+
55+
~~~~~~~~~~~~~~~~~ => Pos: (192 to 208) SpanInfo: {"start":196,"length":11}
56+
>greetings++
57+
>:=> (line 7, col 4) to (line 7, col 15)
58+
--------------------------------
59+
8 > return greetings;
60+
61+
~~~~~~~~~~~~~~~~~~~~~~ => Pos: (209 to 230) SpanInfo: {"start":213,"length":16}
62+
>return greetings
63+
>:=> (line 8, col 4) to (line 8, col 20)
64+
--------------------------------
65+
9 >}
66+
67+
~~ => Pos: (231 to 232) SpanInfo: {"start":231,"length":1}
68+
>}
69+
>:=> (line 9, col 0) to (line 9, col 1)
70+
--------------------------------
71+
10 >function foo(greeting: string, n = 10, x?: string, ...restParams: string[])
72+
73+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ => Pos: (233 to 262) SpanInfo: {"start":315,"length":6}
74+
>return
75+
>:=> (line 12, col 4) to (line 12, col 10)
76+
10 >function foo(greeting: string, n = 10, x?: string, ...restParams: string[])
77+
78+
~~~~~~~~~~~~~~~~~~~~=> Pos: (263 to 282) SpanInfo: {"start":264,"length":6}
79+
>n = 10
80+
>:=> (line 10, col 31) to (line 10, col 37)
81+
10 >function foo(greeting: string, n = 10, x?: string, ...restParams: string[])
82+
83+
~~~~~~~~~~~~~~~~~~~~~~~~~~=> Pos: (283 to 308) SpanInfo: {"start":284,"length":23}
84+
>...restParams: string[]
85+
>:=> (line 10, col 51) to (line 10, col 74)
86+
--------------------------------
87+
11 >{
88+
89+
~~ => Pos: (309 to 310) SpanInfo: {"start":315,"length":6}
90+
>return
91+
>:=> (line 12, col 4) to (line 12, col 10)
92+
--------------------------------
93+
12 > return;
94+
95+
~~~~~~~~~~~~ => Pos: (311 to 322) SpanInfo: {"start":315,"length":6}
96+
>return
97+
>:=> (line 12, col 4) to (line 12, col 10)
98+
--------------------------------
99+
13 >}
100+
~ => Pos: (323 to 323) SpanInfo: {"start":323,"length":1}
101+
>}
102+
>:=> (line 13, col 0) to (line 13, col 1)

0 commit comments

Comments
 (0)