@@ -71,6 +71,7 @@ module ts {
71
71
getSourceUnit ( ) : TypeScript . SourceUnitSyntax ;
72
72
getSyntaxTree ( ) : TypeScript . SyntaxTree ;
73
73
getScriptSnapshot ( ) : TypeScript . IScriptSnapshot ;
74
+ getNamedDeclarations ( ) : Declaration [ ] ;
74
75
update ( scriptSnapshot : TypeScript . IScriptSnapshot , version : string , isOpen : boolean , textChangeRange : TypeScript . TextChangeRange ) : SourceFile ;
75
76
}
76
77
@@ -327,6 +328,7 @@ module ts {
327
328
328
329
private syntaxTree : TypeScript . SyntaxTree ;
329
330
private scriptSnapshot : TypeScript . IScriptSnapshot ;
331
+ private namedDeclarations : Declaration [ ] ;
330
332
331
333
public getSourceUnit ( ) : TypeScript . SourceUnitSyntax {
332
334
// If we don't have a script, create one from our parse tree.
@@ -341,6 +343,59 @@ module ts {
341
343
return this . getSyntaxTree ( ) . lineMap ( ) ;
342
344
}
343
345
346
+ public getNamedDeclarations ( ) {
347
+ if ( ! this . namedDeclarations ) {
348
+ var sourceFile = this ;
349
+ var namedDeclarations : Declaration [ ] = [ ] ;
350
+ var isExternalModule = ts . isExternalModule ( sourceFile ) ;
351
+
352
+ forEachChild ( sourceFile , function visit ( node : Node ) : boolean {
353
+ switch ( node . kind ) {
354
+ case SyntaxKind . ClassDeclaration :
355
+ case SyntaxKind . InterfaceDeclaration :
356
+ case SyntaxKind . EnumDeclaration :
357
+ case SyntaxKind . ModuleDeclaration :
358
+ case SyntaxKind . ImportDeclaration :
359
+ case SyntaxKind . Method :
360
+ case SyntaxKind . FunctionDeclaration :
361
+ case SyntaxKind . Constructor :
362
+ case SyntaxKind . GetAccessor :
363
+ case SyntaxKind . SetAccessor :
364
+ case SyntaxKind . TypeLiteral :
365
+ if ( ( < Declaration > node ) . name ) {
366
+ namedDeclarations . push ( < Declaration > node ) ;
367
+ }
368
+ forEachChild ( node , visit ) ;
369
+ break ;
370
+
371
+ case SyntaxKind . VariableStatement :
372
+ case SyntaxKind . ModuleBlock :
373
+ case SyntaxKind . FunctionBlock :
374
+ forEachChild ( node , visit ) ;
375
+ break ;
376
+
377
+ case SyntaxKind . Parameter :
378
+ if ( ! ( node . flags & NodeFlags . AccessibilityModifier ) ) {
379
+ // Only consider properties defined as constructor parameters
380
+ break ;
381
+ }
382
+ case SyntaxKind . VariableDeclaration :
383
+ case SyntaxKind . EnumMember :
384
+ case SyntaxKind . Property :
385
+ namedDeclarations . push ( < Declaration > node ) ;
386
+ break ;
387
+ }
388
+
389
+ // do not go any deeper
390
+ return undefined ;
391
+ } ) ;
392
+
393
+ this . namedDeclarations = namedDeclarations ;
394
+ }
395
+
396
+ return this . namedDeclarations ;
397
+ }
398
+
344
399
public getSyntaxTree ( ) : TypeScript . SyntaxTree {
345
400
if ( ! this . syntaxTree ) {
346
401
var start = new Date ( ) . getTime ( ) ;
@@ -850,11 +905,11 @@ module ts {
850
905
static staticModifier = "static" ;
851
906
}
852
907
853
- export class MatchKind {
854
- static none : string = null ;
855
- static exact = "exact" ;
856
- static subString = "substring" ;
857
- static prefix = "prefix" ;
908
+ enum MatchKind {
909
+ none = 0 ,
910
+ exact = 1 ,
911
+ substring = 2 ,
912
+ prefix = 3
858
913
}
859
914
860
915
interface IncrementalParse {
@@ -2035,6 +2090,29 @@ module ts {
2035
2090
return ScriptElementKind . unknown ;
2036
2091
}
2037
2092
2093
+ function getNodeKind ( node : Node ) : string {
2094
+ switch ( node . kind ) {
2095
+ case SyntaxKind . ModuleDeclaration : return ScriptElementKind . moduleElement ;
2096
+ case SyntaxKind . ClassDeclaration : return ScriptElementKind . classElement ;
2097
+ case SyntaxKind . InterfaceDeclaration : return ScriptElementKind . interfaceElement ;
2098
+ case SyntaxKind . EnumDeclaration : return ScriptElementKind . enumElement ;
2099
+ case SyntaxKind . VariableDeclaration : return ScriptElementKind . variableElement ;
2100
+ case SyntaxKind . FunctionDeclaration : return ScriptElementKind . functionElement ;
2101
+ case SyntaxKind . GetAccessor : return ScriptElementKind . memberGetAccessorElement ;
2102
+ case SyntaxKind . SetAccessor : return ScriptElementKind . memberSetAccessorElement ;
2103
+ case SyntaxKind . Method : return ScriptElementKind . memberFunctionElement ;
2104
+ case SyntaxKind . Property : return ScriptElementKind . memberVariableElement ;
2105
+ case SyntaxKind . IndexSignature : return ScriptElementKind . indexSignatureElement ;
2106
+ case SyntaxKind . ConstructSignature : return ScriptElementKind . constructSignatureElement ;
2107
+ case SyntaxKind . CallSignature : return ScriptElementKind . callSignatureElement ;
2108
+ case SyntaxKind . Constructor : return ScriptElementKind . constructorImplementationElement ;
2109
+ case SyntaxKind . TypeParameter : return ScriptElementKind . typeParameterElement ;
2110
+ case SyntaxKind . EnumMember : return ScriptElementKind . variableElement ;
2111
+ case SyntaxKind . Parameter : return ( node . flags & NodeFlags . AccessibilityModifier ) ? ScriptElementKind . memberVariableElement : ScriptElementKind . parameterElement ;
2112
+ return ScriptElementKind . unknown ;
2113
+ }
2114
+ }
2115
+
2038
2116
function getNodeModifiers ( node : Node ) : string {
2039
2117
var flags = node . flags ;
2040
2118
var result : string [ ] = [ ] ;
@@ -2186,6 +2264,7 @@ module ts {
2186
2264
return result ;
2187
2265
}
2188
2266
2267
+ /// References and Occurances
2189
2268
function getOccurrencesAtPosition ( filename : string , position : number ) : ReferenceEntry [ ] {
2190
2269
synchronizeHostData ( ) ;
2191
2270
@@ -2732,9 +2811,10 @@ module ts {
2732
2811
return false ;
2733
2812
}
2734
2813
2735
- /// Search within node "container" for references for a search value, where the search value is defined as a
2736
- /// tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
2737
- /// searchLocation: a node where the search value
2814
+ /** Search within node "container" for references for a search value, where the search value is defined as a
2815
+ * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
2816
+ * searchLocation: a node where the search value
2817
+ */
2738
2818
function getReferencesInNode ( container : Node , searchSymbol : Symbol , searchText : string , searchLocation : Node , searchMeaning : SearchMeaning , result : ReferenceEntry [ ] ) : void {
2739
2819
var sourceFile = container . getSourceFile ( ) ;
2740
2820
@@ -3100,12 +3180,13 @@ module ts {
3100
3180
}
3101
3181
}
3102
3182
3103
- /// Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
3104
- /// of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
3105
- /// then we need to widen the search to include type positions as well.
3106
- /// On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
3107
- /// module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
3108
- /// do not intersect in any of the three spaces.
3183
+ /** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
3184
+ * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
3185
+ * then we need to widen the search to include type positions as well.
3186
+ * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
3187
+ * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
3188
+ * do not intersect in any of the three spaces.
3189
+ */
3109
3190
function getIntersectingMeaningFromDeclarations ( meaning : SearchMeaning , declarations : Declaration [ ] ) : SearchMeaning {
3110
3191
if ( declarations ) {
3111
3192
do {
@@ -3142,7 +3223,7 @@ module ts {
3142
3223
return new ReferenceEntry ( node . getSourceFile ( ) . filename , TypeScript . TextSpan . fromBounds ( start , end ) , isWriteAccess ( node ) ) ;
3143
3224
}
3144
3225
3145
- /// A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment
3226
+ /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
3146
3227
function isWriteAccess ( node : Node ) : boolean {
3147
3228
if ( node . kind === SyntaxKind . Identifier && isDeclarationOrFunctionExpressionOrCatchVariableName ( node ) ) {
3148
3229
return true ;
@@ -3162,6 +3243,90 @@ module ts {
3162
3243
return false ;
3163
3244
}
3164
3245
3246
+ /// NavigateTo
3247
+ function getNavigateToItems ( searchValue : string ) : NavigateToItem [ ] {
3248
+ synchronizeHostData ( ) ;
3249
+
3250
+ // Split search value in terms array
3251
+ var terms = searchValue . split ( " " ) ;
3252
+
3253
+ // default NavigateTo approach: if search term contains only lower-case chars - use case-insensitive search, otherwise switch to case-sensitive version
3254
+ var searchTerms = map ( terms , t => ( { caseSensitive : hasAnyUpperCaseCharacter ( t ) , term : t } ) ) ;
3255
+
3256
+ var items : NavigateToItem [ ] = [ ] ;
3257
+
3258
+ // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
3259
+ forEach ( program . getSourceFiles ( ) , sourceFile => {
3260
+ cancellationToken . throwIfCancellationRequested ( ) ;
3261
+
3262
+ var filename = sourceFile . filename ;
3263
+ var declarations = sourceFile . getNamedDeclarations ( ) ;
3264
+ for ( var i = 0 , n = declarations . length ; i < n ; i ++ ) {
3265
+ var declaration = declarations [ i ] ;
3266
+ var name = declaration . name . text ;
3267
+ var matchKind = getMatchKind ( searchTerms , name ) ;
3268
+ if ( matchKind !== MatchKind . none ) {
3269
+ var container = < Declaration > getContainerNode ( declaration ) ;
3270
+ items . push ( {
3271
+ name : name ,
3272
+ kind : getNodeKind ( declaration ) ,
3273
+ kindModifiers : getNodeModifiers ( declaration ) ,
3274
+ matchKind : MatchKind [ matchKind ] ,
3275
+ fileName : filename ,
3276
+ textSpan : TypeScript . TextSpan . fromBounds ( declaration . getStart ( ) , declaration . getEnd ( ) ) ,
3277
+ containerName : container . name ? container . name . text : "" ,
3278
+ containerKind : container . name ? getNodeKind ( container ) : ""
3279
+ } ) ;
3280
+ }
3281
+ }
3282
+ } ) ;
3283
+
3284
+ return items ;
3285
+
3286
+ function hasAnyUpperCaseCharacter ( s : string ) : boolean {
3287
+ for ( var i = 0 , n = s . length ; i < n ; i ++ ) {
3288
+ var c = s . charCodeAt ( i ) ;
3289
+ if ( ( CharacterCodes . A <= c && c <= CharacterCodes . Z ) ||
3290
+ ( c >= CharacterCodes . maxAsciiCharacter && s . charAt ( i ) . toLocaleLowerCase ( ) !== s . charAt ( i ) ) ) {
3291
+ return true ;
3292
+ }
3293
+ }
3294
+
3295
+ return false ;
3296
+ }
3297
+
3298
+ function getMatchKind ( searchTerms : { caseSensitive : boolean ; term : string } [ ] , name : string ) : MatchKind {
3299
+ var matchKind = MatchKind . none ;
3300
+
3301
+ if ( name ) {
3302
+ for ( var j = 0 , n = searchTerms . length ; j < n ; j ++ ) {
3303
+ var searchTerm = searchTerms [ j ] ;
3304
+ var nameToSearch = searchTerm . caseSensitive ? name : name . toLocaleLowerCase ( ) ;
3305
+ // in case of case-insensitive search searchTerm.term will already be lower-cased
3306
+ var index = nameToSearch . indexOf ( searchTerm . term ) ;
3307
+ if ( index < 0 ) {
3308
+ // Didn't match.
3309
+ return MatchKind . none ;
3310
+ }
3311
+
3312
+ var termKind = MatchKind . substring ;
3313
+ if ( index === 0 ) {
3314
+ // here we know that match occur at the beginning of the string.
3315
+ // if search term and declName has the same length - we have an exact match, otherwise declName have longer length and this will be prefix match
3316
+ termKind = name . length === searchTerm . term . length ? MatchKind . exact : MatchKind . prefix ;
3317
+ }
3318
+
3319
+ // Update our match kind if we don't have one, or if this match is better.
3320
+ if ( matchKind === MatchKind . none || termKind < matchKind ) {
3321
+ matchKind = termKind ;
3322
+ }
3323
+ }
3324
+ }
3325
+
3326
+ return matchKind ;
3327
+ }
3328
+ }
3329
+
3165
3330
/// Syntactic features
3166
3331
function getSyntaxTree ( filename : string ) : TypeScript . SyntaxTree {
3167
3332
filename = TypeScript . switchToForwardSlashes ( filename ) ;
@@ -3692,7 +3857,7 @@ module ts {
3692
3857
getImplementorsAtPosition : ( filename , position ) => [ ] ,
3693
3858
getNameOrDottedNameSpan : getNameOrDottedNameSpan ,
3694
3859
getBreakpointStatementAtPosition : getBreakpointStatementAtPosition ,
3695
- getNavigateToItems : ( searchValue ) => [ ] ,
3860
+ getNavigateToItems : getNavigateToItems ,
3696
3861
getRenameInfo : ( fileName , position ) : RenameInfo => RenameInfo . CreateError ( getLocaleSpecificMessage ( Diagnostics . You_cannot_rename_this_element . key ) ) ,
3697
3862
getNavigationBarItems : getNavigationBarItems ,
3698
3863
getOutliningSpans : getOutliningSpans ,
0 commit comments