@@ -42,6 +42,10 @@ module ts.BreakpointResolver {
42
42
}
43
43
}
44
44
45
+ function spanInPreviousNode ( node : Node ) : TypeScript . TextSpan {
46
+ return spanInNode ( findPrecedingToken ( node . pos , sourceFile ) ) ;
47
+ }
48
+
45
49
function spanInNode ( node : Node ) : TypeScript . TextSpan {
46
50
if ( node ) {
47
51
switch ( node . kind ) {
@@ -51,10 +55,41 @@ module ts.BreakpointResolver {
51
55
case SyntaxKind . VariableDeclaration :
52
56
return spanInVariableDeclaration ( < VariableDeclaration > node ) ;
53
57
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:
54
74
case SyntaxKind . SemicolonToken :
55
75
case SyntaxKind . EndOfFileToken :
56
76
return spanInNodeIfStartsOnSameLine ( findPrecedingToken ( node . pos , sourceFile ) ) ;
57
77
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
+
58
93
default :
59
94
// Default go to parent to set the breakpoint
60
95
return spanInNode ( node . parent ) ;
@@ -88,6 +123,123 @@ module ts.BreakpointResolver {
88
123
function spanInVariableStatement ( variableStatement : VariableStatement ) : TypeScript . TextSpan {
89
124
return spanInVariableDeclaration ( variableStatement . declarations [ 0 ] ) ;
90
125
}
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
+ }
91
243
}
92
244
}
93
245
}
0 commit comments