@@ -1314,12 +1314,13 @@ module ts {
1314
1314
1315
1315
function isAnyFunction ( node : Node ) : boolean {
1316
1316
switch ( node . kind ) {
1317
+ case SyntaxKind . FunctionExpression :
1317
1318
case SyntaxKind . FunctionDeclaration :
1319
+ case SyntaxKind . ArrowFunction :
1318
1320
case SyntaxKind . Method :
1319
- case SyntaxKind . FunctionExpression :
1320
1321
case SyntaxKind . GetAccessor :
1321
1322
case SyntaxKind . SetAccessor :
1322
- case SyntaxKind . ArrowFunction :
1323
+ case SyntaxKind . Constructor :
1323
1324
return true ;
1324
1325
}
1325
1326
return false ;
@@ -1933,7 +1934,9 @@ module ts {
1933
1934
current = child ;
1934
1935
continue outer;
1935
1936
}
1936
- if ( child . end > position ) break ;
1937
+ if ( child . end > position ) {
1938
+ break ;
1939
+ }
1937
1940
}
1938
1941
return current ;
1939
1942
}
@@ -2160,13 +2163,143 @@ module ts {
2160
2163
return undefined ;
2161
2164
}
2162
2165
2163
- if ( node . kind !== SyntaxKind . Identifier &&
2164
- ! isLiteralNameOfPropertyDeclarationOrIndexAccess ( node ) &&
2165
- ! isNameOfExternalModuleImportOrDeclaration ( node ) ) {
2166
+ if ( node . kind === SyntaxKind . Identifier || isLiteralNameOfPropertyDeclarationOrIndexAccess ( node ) || isNameOfExternalModuleImportOrDeclaration ( node ) ) {
2167
+ return getReferencesForNode ( node , [ sourceFile ] ) ;
2168
+ }
2169
+
2170
+ switch ( node . kind ) {
2171
+ case SyntaxKind . TryKeyword :
2172
+ case SyntaxKind . CatchKeyword :
2173
+ case SyntaxKind . FinallyKeyword :
2174
+ if ( hasKind ( parent ( parent ( node ) ) , SyntaxKind . TryStatement ) ) {
2175
+ return getTryCatchFinallyOccurrences ( < TryStatement > node . parent . parent ) ;
2176
+ }
2177
+ break ;
2178
+ case SyntaxKind . SwitchKeyword :
2179
+ if ( hasKind ( node . parent , SyntaxKind . SwitchStatement ) ) {
2180
+ return getSwitchCaseDefaultOccurrences ( < SwitchStatement > node . parent ) ;
2181
+ }
2182
+ break ;
2183
+ case SyntaxKind . CaseKeyword :
2184
+ case SyntaxKind . DefaultKeyword :
2185
+ if ( hasKind ( parent ( parent ( node ) ) , SyntaxKind . SwitchStatement ) ) {
2186
+ return getSwitchCaseDefaultOccurrences ( < SwitchStatement > node . parent . parent ) ;
2187
+ }
2188
+ break ;
2189
+ case SyntaxKind . BreakKeyword :
2190
+ if ( hasKind ( node . parent , SyntaxKind . BreakStatement ) ) {
2191
+ return getBreakStatementOccurences ( < BreakOrContinueStatement > node . parent ) ;
2192
+ }
2193
+ break ;
2194
+ }
2195
+
2196
+ return undefined ;
2197
+
2198
+ function getTryCatchFinallyOccurrences ( tryStatement : TryStatement ) : ReferenceEntry [ ] {
2199
+ var keywords : Node [ ] = [ ] ;
2200
+
2201
+ pushKeywordIf ( keywords , tryStatement . getFirstToken ( ) , SyntaxKind . TryKeyword ) ;
2202
+
2203
+ if ( tryStatement . catchBlock ) {
2204
+ pushKeywordIf ( keywords , tryStatement . catchBlock . getFirstToken ( ) , SyntaxKind . CatchKeyword ) ;
2205
+ }
2206
+
2207
+ if ( tryStatement . finallyBlock ) {
2208
+ pushKeywordIf ( keywords , tryStatement . finallyBlock . getFirstToken ( ) , SyntaxKind . FinallyKeyword ) ;
2209
+ }
2210
+
2211
+ return keywordsToReferenceEntries ( keywords ) ;
2212
+ }
2213
+
2214
+ function getSwitchCaseDefaultOccurrences ( switchStatement : SwitchStatement ) {
2215
+ var keywords : Node [ ] = [ ] ;
2216
+
2217
+ pushKeywordIf ( keywords , switchStatement . getFirstToken ( ) , SyntaxKind . SwitchKeyword ) ;
2218
+
2219
+ // Go through each clause in the switch statement, collecting the clause keywords.
2220
+ forEach ( switchStatement . clauses , clause => {
2221
+ pushKeywordIf ( keywords , clause . getFirstToken ( ) , SyntaxKind . CaseKeyword , SyntaxKind . DefaultKeyword ) ;
2222
+
2223
+ // For each clause, also recursively traverse the statements where we can find analogous breaks.
2224
+ forEachChild ( clause , function aggregateBreakKeywords ( node : Node ) : void {
2225
+ switch ( node . kind ) {
2226
+ case SyntaxKind . BreakStatement :
2227
+ // If the break statement has a label, it cannot be part of a switch block.
2228
+ if ( ! ( < BreakOrContinueStatement > node ) . label ) {
2229
+ pushKeywordIf ( keywords , node . getFirstToken ( ) , SyntaxKind . BreakKeyword ) ;
2230
+ }
2231
+ // Fall through
2232
+ case SyntaxKind . ForStatement :
2233
+ case SyntaxKind . ForInStatement :
2234
+ case SyntaxKind . DoStatement :
2235
+ case SyntaxKind . WhileStatement :
2236
+ case SyntaxKind . SwitchStatement :
2237
+ return ;
2238
+ }
2239
+
2240
+ // Do not cross function boundaries.
2241
+ if ( ! isAnyFunction ( node ) ) {
2242
+ forEachChild ( node , aggregateBreakKeywords ) ;
2243
+ }
2244
+ } ) ;
2245
+ } ) ;
2246
+
2247
+ return keywordsToReferenceEntries ( keywords ) ;
2248
+ }
2249
+
2250
+ function getBreakStatementOccurences ( breakStatement : BreakOrContinueStatement ) : ReferenceEntry [ ] {
2251
+ // TODO (drosen): Deal with labeled statements.
2252
+ if ( breakStatement . label ) {
2253
+ return undefined ;
2254
+ }
2255
+
2256
+ for ( var owner = node . parent ; owner ; owner = owner . parent ) {
2257
+ switch ( owner . kind ) {
2258
+ case SyntaxKind . ForStatement :
2259
+ case SyntaxKind . ForInStatement :
2260
+ case SyntaxKind . DoStatement :
2261
+ case SyntaxKind . WhileStatement :
2262
+ // TODO (drosen): Handle loops!
2263
+ return undefined ;
2264
+
2265
+ case SyntaxKind . SwitchStatement :
2266
+ return getSwitchCaseDefaultOccurrences ( < SwitchStatement > owner ) ;
2267
+
2268
+ default :
2269
+ if ( isAnyFunction ( owner ) ) {
2270
+ return undefined ;
2271
+ }
2272
+ }
2273
+ }
2274
+
2166
2275
return undefined ;
2167
2276
}
2168
2277
2169
- return getReferencesForNode ( node , [ sourceFile ] ) ;
2278
+ // returns true if 'node' is defined and has a matching 'kind'.
2279
+ function hasKind ( node : Node , kind : SyntaxKind ) {
2280
+ return ! ! ( node && node . kind === kind ) ;
2281
+ }
2282
+
2283
+ // Null-propagating 'parent' function.
2284
+ function parent ( node : Node ) : Node {
2285
+ return node && node . parent ;
2286
+ }
2287
+
2288
+ function pushKeywordIf ( keywordList : Node [ ] , token : Node , ...expected : SyntaxKind [ ] ) : void {
2289
+ if ( ! token ) {
2290
+ return ;
2291
+ }
2292
+
2293
+ if ( contains ( < SyntaxKind [ ] > expected , token . kind ) ) {
2294
+ keywordList . push ( token ) ;
2295
+ }
2296
+ }
2297
+
2298
+ function keywordsToReferenceEntries ( keywords : Node [ ] ) : ReferenceEntry [ ] {
2299
+ return map ( keywords , keyword =>
2300
+ new ReferenceEntry ( filename , TypeScript . TextSpan . fromBounds ( keyword . getStart ( ) , keyword . end ) , /* isWriteAccess */ false )
2301
+ ) ;
2302
+ }
2170
2303
}
2171
2304
2172
2305
function getReferencesAtPosition ( filename : string , position : number ) : ReferenceEntry [ ] {
@@ -2284,13 +2417,13 @@ module ts {
2284
2417
var container = getContainerNode ( declarations [ i ] ) ;
2285
2418
2286
2419
if ( scope && scope !== container ) {
2287
- // Diffrent declarations have diffrent containers, bail out
2420
+ // Different declarations have different containers, bail out
2288
2421
return undefined ;
2289
2422
}
2290
2423
2291
2424
if ( container . kind === SyntaxKind . SourceFile && ! isExternalModule ( < SourceFile > container ) ) {
2292
2425
// This is a global variable and not an external module, any declaration defined
2293
- // withen this scope is visible outside the file
2426
+ // within this scope is visible outside the file
2294
2427
return undefined ;
2295
2428
}
2296
2429
@@ -2957,7 +3090,7 @@ module ts {
2957
3090
// ["// hack 1", "// ", "hack 1", undefined, "hack"]
2958
3091
//
2959
3092
// Here are the relevant capture groups:
2960
- // 0) The full match for hte entire regex.
3093
+ // 0) The full match for the entire regex.
2961
3094
// 1) The preamble to the message portion.
2962
3095
// 2) The message portion.
2963
3096
// 3...N) The descriptor that was matched - by index. 'undefined' for each
0 commit comments