@@ -70,6 +70,7 @@ module ts {
70
70
getSourceUnit ( ) : TypeScript . SourceUnitSyntax ;
71
71
getSyntaxTree ( ) : TypeScript . SyntaxTree ;
72
72
getScriptSnapshot ( ) : TypeScript . IScriptSnapshot ;
73
+ getNamedDeclarations ( ) : Declaration [ ] ;
73
74
update ( scriptSnapshot : TypeScript . IScriptSnapshot , version : string , isOpen : boolean , textChangeRange : TypeScript . TextChangeRange ) : SourceFile ;
74
75
}
75
76
@@ -326,6 +327,7 @@ module ts {
326
327
327
328
private syntaxTree : TypeScript . SyntaxTree ;
328
329
private scriptSnapshot : TypeScript . IScriptSnapshot ;
330
+ private namedDeclarations : Declaration [ ] ;
329
331
330
332
public getSourceUnit ( ) : TypeScript . SourceUnitSyntax {
331
333
// If we don't have a script, create one from our parse tree.
@@ -340,6 +342,59 @@ module ts {
340
342
return this . getSyntaxTree ( ) . lineMap ( ) ;
341
343
}
342
344
345
+ public getNamedDeclarations ( ) {
346
+ if ( ! this . namedDeclarations ) {
347
+ var sourceFile = this ;
348
+ var namedDeclarations : Declaration [ ] = [ ] ;
349
+ var isExternalModule = ts . isExternalModule ( sourceFile ) ;
350
+
351
+ forEachChild ( sourceFile , function visit ( node : Node ) : boolean {
352
+ switch ( node . kind ) {
353
+ case SyntaxKind . ClassDeclaration :
354
+ case SyntaxKind . InterfaceDeclaration :
355
+ case SyntaxKind . EnumDeclaration :
356
+ case SyntaxKind . ModuleDeclaration :
357
+ case SyntaxKind . ImportDeclaration :
358
+ case SyntaxKind . Method :
359
+ case SyntaxKind . FunctionDeclaration :
360
+ case SyntaxKind . Constructor :
361
+ case SyntaxKind . GetAccessor :
362
+ case SyntaxKind . SetAccessor :
363
+ case SyntaxKind . TypeLiteral :
364
+ if ( ( < Declaration > node ) . name ) {
365
+ namedDeclarations . push ( < Declaration > node ) ;
366
+ }
367
+ forEachChild ( node , visit ) ;
368
+ break ;
369
+
370
+ case SyntaxKind . VariableStatement :
371
+ case SyntaxKind . ModuleBlock :
372
+ case SyntaxKind . FunctionBlock :
373
+ forEachChild ( node , visit ) ;
374
+ break ;
375
+
376
+ case SyntaxKind . Parameter :
377
+ if ( ! ( node . flags & NodeFlags . AccessibilityModifier ) ) {
378
+ // Only consider properties defined as constructor parameters
379
+ break ;
380
+ }
381
+ case SyntaxKind . VariableDeclaration :
382
+ case SyntaxKind . EnumMember :
383
+ case SyntaxKind . Property :
384
+ namedDeclarations . push ( < Declaration > node ) ;
385
+ break ;
386
+ }
387
+
388
+ // do not go any deeper
389
+ return undefined ;
390
+ } ) ;
391
+
392
+ this . namedDeclarations = namedDeclarations ;
393
+ }
394
+
395
+ return this . namedDeclarations ;
396
+ }
397
+
343
398
public getSyntaxTree ( ) : TypeScript . SyntaxTree {
344
399
if ( ! this . syntaxTree ) {
345
400
var start = new Date ( ) . getTime ( ) ;
@@ -820,11 +875,11 @@ module ts {
820
875
static staticModifier = "static" ;
821
876
}
822
877
823
- export class MatchKind {
824
- static none : string = null ;
825
- static exact = "exact" ;
826
- static subString = "substring" ;
827
- static prefix = "prefix" ;
878
+ enum MatchKind {
879
+ none = 0 ,
880
+ exact = 1 ,
881
+ substring = 2 ,
882
+ prefix = 3
828
883
}
829
884
830
885
interface IncrementalParse {
@@ -1983,6 +2038,29 @@ module ts {
1983
2038
return ScriptElementKind . unknown ;
1984
2039
}
1985
2040
2041
+ function getNodeKind ( node : Node ) : string {
2042
+ switch ( node . kind ) {
2043
+ case SyntaxKind . ModuleDeclaration : return ScriptElementKind . moduleElement ;
2044
+ case SyntaxKind . ClassDeclaration : return ScriptElementKind . classElement ;
2045
+ case SyntaxKind . InterfaceDeclaration : return ScriptElementKind . interfaceElement ;
2046
+ case SyntaxKind . EnumDeclaration : return ScriptElementKind . enumElement ;
2047
+ case SyntaxKind . VariableDeclaration : return ScriptElementKind . variableElement ;
2048
+ case SyntaxKind . FunctionDeclaration : return ScriptElementKind . functionElement ;
2049
+ case SyntaxKind . GetAccessor : return ScriptElementKind . memberGetAccessorElement ;
2050
+ case SyntaxKind . SetAccessor : return ScriptElementKind . memberSetAccessorElement ;
2051
+ case SyntaxKind . Method : return ScriptElementKind . memberFunctionElement ;
2052
+ case SyntaxKind . Property : return ScriptElementKind . memberVariableElement ;
2053
+ case SyntaxKind . IndexSignature : return ScriptElementKind . indexSignatureElement ;
2054
+ case SyntaxKind . ConstructSignature : return ScriptElementKind . constructSignatureElement ;
2055
+ case SyntaxKind . CallSignature : return ScriptElementKind . callSignatureElement ;
2056
+ case SyntaxKind . Constructor : return ScriptElementKind . constructorImplementationElement ;
2057
+ case SyntaxKind . TypeParameter : return ScriptElementKind . typeParameterElement ;
2058
+ case SyntaxKind . EnumMember : return ScriptElementKind . variableElement ;
2059
+ case SyntaxKind . Parameter : return ( node . flags & NodeFlags . AccessibilityModifier ) ? ScriptElementKind . memberVariableElement : ScriptElementKind . parameterElement ;
2060
+ return ScriptElementKind . unknown ;
2061
+ }
2062
+ }
2063
+
1986
2064
function getNodeModifiers ( node : Node ) : string {
1987
2065
var flags = node . flags ;
1988
2066
var result : string [ ] = [ ] ;
@@ -2134,6 +2212,7 @@ module ts {
2134
2212
return result ;
2135
2213
}
2136
2214
2215
+ /// References and Occurances
2137
2216
function getOccurrencesAtPosition ( filename : string , position : number ) : ReferenceEntry [ ] {
2138
2217
synchronizeHostData ( ) ;
2139
2218
@@ -2612,9 +2691,10 @@ module ts {
2612
2691
return false ;
2613
2692
}
2614
2693
2615
- /// Search within node "container" for references for a search value, where the search value is defined as a
2616
- /// tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
2617
- /// searchLocation: a node where the search value
2694
+ /** Search within node "container" for references for a search value, where the search value is defined as a
2695
+ * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
2696
+ * searchLocation: a node where the search value
2697
+ */
2618
2698
function getReferencesInNode ( container : Node , searchSymbol : Symbol , searchText : string , searchLocation : Node , searchMeaning : SearchMeaning , result : ReferenceEntry [ ] ) : void {
2619
2699
var sourceFile = container . getSourceFile ( ) ;
2620
2700
@@ -2980,12 +3060,13 @@ module ts {
2980
3060
}
2981
3061
}
2982
3062
2983
- /// Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
2984
- /// of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
2985
- /// then we need to widen the search to include type positions as well.
2986
- /// On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
2987
- /// module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
2988
- /// do not intersect in any of the three spaces.
3063
+ /** Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
3064
+ * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
3065
+ * then we need to widen the search to include type positions as well.
3066
+ * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
3067
+ * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
3068
+ * do not intersect in any of the three spaces.
3069
+ */
2989
3070
function getIntersectingMeaningFromDeclarations ( meaning : SearchMeaning , declarations : Declaration [ ] ) : SearchMeaning {
2990
3071
if ( declarations ) {
2991
3072
do {
@@ -3022,7 +3103,7 @@ module ts {
3022
3103
return new ReferenceEntry ( node . getSourceFile ( ) . filename , TypeScript . TextSpan . fromBounds ( start , end ) , isWriteAccess ( node ) ) ;
3023
3104
}
3024
3105
3025
- /// A node is considedered a writeAccess iff it is a name of a declaration or a target of an assignment
3106
+ /** A node is considedered a writeAccess iff it is a name of a declaration or a target of an assignment */
3026
3107
function isWriteAccess ( node : Node ) : boolean {
3027
3108
if ( node . kind === SyntaxKind . Identifier && isDeclarationOrFunctionExpressionOrCatchVariableName ( node ) ) {
3028
3109
return true ;
@@ -3042,6 +3123,88 @@ module ts {
3042
3123
return false ;
3043
3124
}
3044
3125
3126
+ /// NavigateTo
3127
+ function getNavigateToItems ( searchValue : string ) : NavigateToItem [ ] {
3128
+ synchronizeHostData ( ) ;
3129
+
3130
+ // Split search value in terms array
3131
+ var terms = searchValue . split ( " " ) ;
3132
+
3133
+ // default NavigateTo approach: if search term contains only lower-case chars - use case-insensitive search, otherwise switch to case-sensitive version
3134
+ var searchTerms = map ( terms , t => ( { caseSensitive : hasAnyUpperCaseCharacter ( t ) , term : t } ) ) ;
3135
+
3136
+ var items : NavigateToItem [ ] = [ ] ;
3137
+
3138
+ // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
3139
+ forEach ( program . getSourceFiles ( ) , sourceFile => {
3140
+ cancellationToken . throwIfCancellationRequested ( ) ;
3141
+
3142
+ var filename = sourceFile . filename ;
3143
+ var declarations = sourceFile . getNamedDeclarations ( ) ;
3144
+ for ( var i = 0 , n = declarations . length ; i < n ; i ++ ) {
3145
+ var declaration = declarations [ i ] ;
3146
+ var name = declaration . name . text ;
3147
+ var matchKind = getMatchKind ( searchTerms , name ) ;
3148
+ if ( matchKind !== MatchKind . none ) {
3149
+ var container = < Declaration > getContainerNode ( declaration ) ;
3150
+ items . push ( {
3151
+ name : name ,
3152
+ kind : getNodeKind ( declaration ) ,
3153
+ kindModifiers : getNodeModifiers ( declaration ) ,
3154
+ matchKind : MatchKind [ matchKind ] ,
3155
+ fileName : filename ,
3156
+ textSpan : TypeScript . TextSpan . fromBounds ( declaration . getStart ( ) , declaration . getEnd ( ) ) ,
3157
+ containerName : container . name ? container . name . text : "" ,
3158
+ containerKind : container . name ? getNodeKind ( container ) : ""
3159
+ } ) ;
3160
+ }
3161
+ }
3162
+ } ) ;
3163
+
3164
+ return items ;
3165
+
3166
+ function hasAnyUpperCaseCharacter ( s : string ) : boolean {
3167
+ for ( var i = 0 ; i < s . length ; ++ i ) {
3168
+ if ( s . charAt ( i ) . toLocaleLowerCase ( ) !== s . charAt ( i ) ) {
3169
+ return true ;
3170
+ }
3171
+ }
3172
+
3173
+ return false ;
3174
+ }
3175
+
3176
+ function getMatchKind ( searchTerms : { caseSensitive : boolean ; term : string } [ ] , name : string ) : MatchKind {
3177
+ var matchKind = MatchKind . none ;
3178
+
3179
+ if ( name ) {
3180
+ for ( var j = 0 , n = searchTerms . length ; j < n ; j ++ ) {
3181
+ var searchTerm = searchTerms [ j ] ;
3182
+ var nameToSearch = searchTerm . caseSensitive ? name : name . toLocaleLowerCase ( ) ;
3183
+ // in case of case-insensitive search searchTerm.term will already be lower-cased
3184
+ var index = nameToSearch . indexOf ( searchTerm . term ) ;
3185
+ if ( index < 0 ) {
3186
+ // Didn't match.
3187
+ return MatchKind . none ;
3188
+ }
3189
+
3190
+ var termKind = MatchKind . substring ;
3191
+ if ( index === 0 ) {
3192
+ // here we know that match occur at the beginning of the string.
3193
+ // 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
3194
+ termKind = name . length === searchTerm . term . length ? MatchKind . exact : MatchKind . prefix ;
3195
+ }
3196
+
3197
+ // Update our match kind if we don't have one, or if this match is better.
3198
+ if ( matchKind === MatchKind . none || termKind < matchKind ) {
3199
+ matchKind = termKind ;
3200
+ }
3201
+ }
3202
+ }
3203
+
3204
+ return matchKind ;
3205
+ }
3206
+ }
3207
+
3045
3208
/// Syntactic features
3046
3209
function getSyntaxTree ( filename : string ) : TypeScript . SyntaxTree {
3047
3210
filename = TypeScript . switchToForwardSlashes ( filename ) ;
@@ -3382,7 +3545,7 @@ module ts {
3382
3545
getImplementorsAtPosition : ( filename , position ) => [ ] ,
3383
3546
getNameOrDottedNameSpan : getNameOrDottedNameSpan ,
3384
3547
getBreakpointStatementAtPosition : getBreakpointStatementAtPosition ,
3385
- getNavigateToItems : ( searchValue ) => [ ] ,
3548
+ getNavigateToItems : getNavigateToItems ,
3386
3549
getRenameInfo : ( fileName , position ) : RenameInfo => RenameInfo . CreateError ( getLocaleSpecificMessage ( Diagnostics . You_cannot_rename_this_element . key ) ) ,
3387
3550
getNavigationBarItems : getNavigationBarItems ,
3388
3551
getOutliningSpans : getOutliningSpans ,
0 commit comments