@@ -21,185 +21,183 @@ namespace ts.NavigateTo {
21
21
}
22
22
23
23
forEachEntry ( sourceFile . getNamedDeclarations ( ) , ( declarations , name ) => {
24
- if ( declarations ) {
25
- // First do a quick check to see if the name of the declaration matches the
26
- // last portion of the (possibly) dotted name they're searching for.
27
- let matches = patternMatcher . getMatchesForLastSegmentOfPattern ( name ) ;
28
-
29
- if ( ! matches ) {
30
- return ; // continue to next named declarations
31
- }
32
-
33
- for ( const declaration of declarations ) {
34
- // It was a match! If the pattern has dots in it, then also see if the
35
- // declaration container matches as well.
36
- if ( patternMatcher . patternContainsDots ) {
37
- const containers = getContainers ( declaration ) ;
38
- if ( ! containers ) {
39
- return true ; // Break out of named declarations and go to the next source file.
40
- }
41
-
42
- matches = patternMatcher . getMatches ( containers , name ) ;
43
-
44
- if ( ! matches ) {
45
- return ; // continue to next named declarations
46
- }
47
- }
48
-
49
- const fileName = sourceFile . fileName ;
50
- const matchKind = bestMatchKind ( matches ) ;
51
- rawItems . push ( { name, fileName, matchKind, isCaseSensitive : allMatchesAreCaseSensitive ( matches ) , declaration } ) ;
52
- }
53
- }
24
+ getItemsFromNamedDeclaration ( patternMatcher , name , declarations , checker , sourceFile . fileName , rawItems ) ;
54
25
} ) ;
55
26
}
56
27
57
- // Remove imports when the imported declaration is already in the list and has the same name.
58
- rawItems = filter ( rawItems , item => {
59
- const decl = item . declaration ;
60
- if ( decl . kind === SyntaxKind . ImportClause || decl . kind === SyntaxKind . ImportSpecifier || decl . kind === SyntaxKind . ImportEqualsDeclaration ) {
61
- const importer = checker . getSymbolAtLocation ( ( decl as NamedDeclaration ) . name ) ;
62
- const imported = checker . getAliasedSymbol ( importer ) ;
63
- return importer . escapedName !== imported . escapedName ;
64
- }
65
- else {
66
- return true ;
67
- }
68
- } ) ;
69
-
70
28
rawItems . sort ( compareNavigateToItems ) ;
71
29
if ( maxResultCount !== undefined ) {
72
30
rawItems = rawItems . slice ( 0 , maxResultCount ) ;
73
31
}
32
+ return rawItems . map ( createNavigateToItem ) ;
33
+ }
74
34
75
- const items = map ( rawItems , createNavigateToItem ) ;
76
-
77
- return items ;
35
+ function getItemsFromNamedDeclaration ( patternMatcher : PatternMatcher , name : string , declarations : ReadonlyArray < Declaration > , checker : TypeChecker , fileName : string , rawItems : Push < RawNavigateToItem > ) : void {
36
+ // First do a quick check to see if the name of the declaration matches the
37
+ // last portion of the (possibly) dotted name they're searching for.
38
+ const matches = patternMatcher . getMatchesForLastSegmentOfPattern ( name ) ;
78
39
79
- function allMatchesAreCaseSensitive ( matches : PatternMatch [ ] ) : boolean {
80
- Debug . assert ( matches . length > 0 ) ;
40
+ if ( ! matches ) {
41
+ return ; // continue to next named declarations
42
+ }
81
43
82
- // This is a case sensitive match, only if all the submatches were case sensitive.
83
- for ( const match of matches ) {
84
- if ( ! match . isCaseSensitive ) {
85
- return false ;
86
- }
44
+ for ( const declaration of declarations ) {
45
+ if ( ! shouldKeepItem ( declaration , checker ) ) {
46
+ continue ;
87
47
}
88
48
89
- return true ;
90
- }
91
-
92
- function tryAddSingleDeclarationName ( declaration : Declaration , containers : string [ ] ) {
93
- if ( declaration ) {
94
- const name = getNameOfDeclaration ( declaration ) ;
95
- if ( name ) {
96
- const text = getTextOfIdentifierOrLiteral ( name as ( Identifier | LiteralExpression ) ) ;
97
- if ( text !== undefined ) {
98
- containers . unshift ( text ) ;
99
- }
100
- else if ( name . kind === SyntaxKind . ComputedPropertyName ) {
101
- return tryAddComputedPropertyName ( ( < ComputedPropertyName > name ) . expression , containers , /*includeLastPortion*/ true ) ;
102
- }
103
- else {
104
- // Don't know how to add this.
105
- return false ;
106
- }
49
+ // It was a match! If the pattern has dots in it, then also see if the
50
+ // declaration container matches as well.
51
+ let containerMatches = matches ;
52
+ if ( patternMatcher . patternContainsDots ) {
53
+ containerMatches = patternMatcher . getMatches ( getContainers ( declaration ) , name ) ;
54
+ if ( ! containerMatches ) {
55
+ continue ;
107
56
}
108
57
}
109
58
110
- return true ;
59
+ const matchKind = bestMatchKind ( containerMatches ) ;
60
+ const isCaseSensitive = allMatchesAreCaseSensitive ( containerMatches ) ;
61
+ rawItems . push ( { name, fileName, matchKind, isCaseSensitive, declaration } ) ;
111
62
}
63
+ }
112
64
113
- // Only added the names of computed properties if they're simple dotted expressions, like:
114
- //
115
- // [X.Y.Z]() { }
116
- function tryAddComputedPropertyName ( expression : Expression , containers : string [ ] , includeLastPortion : boolean ) : boolean {
117
- const text = getTextOfIdentifierOrLiteral ( expression as LiteralExpression ) ;
118
- if ( text !== undefined ) {
119
- if ( includeLastPortion ) {
120
- containers . unshift ( text ) ;
121
- }
65
+ function shouldKeepItem ( declaration : Declaration , checker : ts . TypeChecker ) : boolean {
66
+ switch ( declaration . kind ) {
67
+ case SyntaxKind . ImportClause :
68
+ case SyntaxKind . ImportSpecifier :
69
+ case SyntaxKind . ImportEqualsDeclaration :
70
+ const importer = checker . getSymbolAtLocation ( ( declaration as ImportClause | ImportSpecifier | ImportEqualsDeclaration ) . name ) ;
71
+ const imported = checker . getAliasedSymbol ( importer ) ;
72
+ return importer . escapedName !== imported . escapedName ;
73
+ default :
122
74
return true ;
123
- }
75
+ }
76
+ }
124
77
125
- if ( expression . kind === SyntaxKind . PropertyAccessExpression ) {
126
- const propertyAccess = < PropertyAccessExpression > expression ;
127
- if ( includeLastPortion ) {
128
- containers . unshift ( propertyAccess . name . text ) ;
129
- }
78
+ function allMatchesAreCaseSensitive ( matches : ReadonlyArray < PatternMatch > ) : boolean {
79
+ Debug . assert ( matches . length > 0 ) ;
130
80
131
- return tryAddComputedPropertyName ( propertyAccess . expression , containers , /*includeLastPortion*/ true ) ;
81
+ // This is a case sensitive match, only if all the submatches were case sensitive.
82
+ for ( const match of matches ) {
83
+ if ( ! match . isCaseSensitive ) {
84
+ return false ;
132
85
}
133
-
134
- return false ;
135
86
}
136
87
137
- function getContainers ( declaration : Declaration ) {
138
- const containers : string [ ] = [ ] ;
88
+ return true ;
89
+ }
139
90
140
- // First, if we started with a computed property name, then add all but the last
141
- // portion into the container array.
91
+ function tryAddSingleDeclarationName ( declaration : Declaration , containers : string [ ] ) : boolean {
92
+ if ( declaration ) {
142
93
const name = getNameOfDeclaration ( declaration ) ;
143
- if ( name . kind === SyntaxKind . ComputedPropertyName ) {
144
- if ( ! tryAddComputedPropertyName ( ( < ComputedPropertyName > name ) . expression , containers , /*includeLastPortion*/ false ) ) {
145
- return undefined ;
94
+ if ( name ) {
95
+ const text = getTextOfIdentifierOrLiteral ( name as ( Identifier | LiteralExpression ) ) ;
96
+ if ( text !== undefined ) {
97
+ containers . unshift ( text ) ;
98
+ }
99
+ else if ( name . kind === SyntaxKind . ComputedPropertyName ) {
100
+ return tryAddComputedPropertyName ( ( < ComputedPropertyName > name ) . expression , containers , /*includeLastPortion*/ true ) ;
101
+ }
102
+ else {
103
+ // Don't know how to add this.
104
+ return false ;
146
105
}
147
106
}
107
+ }
148
108
149
- // Now, walk up our containers, adding all their names to the container array.
150
- declaration = getContainerNode ( declaration ) ;
109
+ return true ;
110
+ }
151
111
152
- while ( declaration ) {
153
- if ( ! tryAddSingleDeclarationName ( declaration , containers ) ) {
154
- return undefined ;
155
- }
112
+ // Only added the names of computed properties if they're simple dotted expressions, like:
113
+ //
114
+ // [X.Y.Z]() { }
115
+ function tryAddComputedPropertyName ( expression : Expression , containers : string [ ] , includeLastPortion : boolean ) : boolean {
116
+ const text = getTextOfIdentifierOrLiteral ( expression as LiteralExpression ) ;
117
+ if ( text !== undefined ) {
118
+ if ( includeLastPortion ) {
119
+ containers . unshift ( text ) ;
120
+ }
121
+ return true ;
122
+ }
156
123
157
- declaration = getContainerNode ( declaration ) ;
124
+ if ( expression . kind === SyntaxKind . PropertyAccessExpression ) {
125
+ const propertyAccess = < PropertyAccessExpression > expression ;
126
+ if ( includeLastPortion ) {
127
+ containers . unshift ( propertyAccess . name . text ) ;
158
128
}
159
129
160
- return containers ;
130
+ return tryAddComputedPropertyName ( propertyAccess . expression , containers , /*includeLastPortion*/ true ) ;
161
131
}
162
132
163
- function bestMatchKind ( matches : PatternMatch [ ] ) {
164
- Debug . assert ( matches . length > 0 ) ;
165
- let bestMatchKind = PatternMatchKind . camelCase ;
133
+ return false ;
134
+ }
166
135
167
- for ( const match of matches ) {
168
- const kind = match . kind ;
169
- if ( kind < bestMatchKind ) {
170
- bestMatchKind = kind ;
171
- }
172
- }
136
+ function getContainers ( declaration : Declaration ) : string [ ] {
137
+ const containers : string [ ] = [ ] ;
173
138
174
- return bestMatchKind ;
139
+ // First, if we started with a computed property name, then add all but the last
140
+ // portion into the container array.
141
+ const name = getNameOfDeclaration ( declaration ) ;
142
+ if ( name . kind === SyntaxKind . ComputedPropertyName ) {
143
+ if ( ! tryAddComputedPropertyName ( ( < ComputedPropertyName > name ) . expression , containers , /*includeLastPortion*/ false ) ) {
144
+ return undefined ;
145
+ }
175
146
}
176
147
177
- function compareNavigateToItems ( i1 : RawNavigateToItem , i2 : RawNavigateToItem ) {
178
- // TODO(cyrusn): get the gamut of comparisons that VS already uses here.
179
- // Right now we just sort by kind first, and then by name of the item.
180
- // We first sort case insensitively. So "Aaa" will come before "bar".
181
- // Then we sort case sensitively, so "aaa" will come before "Aaa".
182
- return i1 . matchKind - i2 . matchKind ||
183
- ts . compareStringsCaseInsensitive ( i1 . name , i2 . name ) ||
184
- ts . compareStrings ( i1 . name , i2 . name ) ;
148
+ // Now, walk up our containers, adding all their names to the container array.
149
+ declaration = getContainerNode ( declaration ) ;
150
+
151
+ while ( declaration ) {
152
+ if ( ! tryAddSingleDeclarationName ( declaration , containers ) ) {
153
+ return undefined ;
154
+ }
155
+
156
+ declaration = getContainerNode ( declaration ) ;
185
157
}
186
158
187
- function createNavigateToItem ( rawItem : RawNavigateToItem ) : NavigateToItem {
188
- const declaration = rawItem . declaration ;
189
- const container = < Declaration > getContainerNode ( declaration ) ;
190
- const containerName = container && getNameOfDeclaration ( container ) ;
191
- return {
192
- name : rawItem . name ,
193
- kind : getNodeKind ( declaration ) ,
194
- kindModifiers : getNodeModifiers ( declaration ) ,
195
- matchKind : PatternMatchKind [ rawItem . matchKind ] ,
196
- isCaseSensitive : rawItem . isCaseSensitive ,
197
- fileName : rawItem . fileName ,
198
- textSpan : createTextSpanFromNode ( declaration ) ,
199
- // TODO(jfreeman): What should be the containerName when the container has a computed name?
200
- containerName : containerName ? ( < Identifier > containerName ) . text : "" ,
201
- containerKind : containerName ? getNodeKind ( container ) : ScriptElementKind . unknown
202
- } ;
159
+ return containers ;
160
+ }
161
+
162
+ function bestMatchKind ( matches : ReadonlyArray < PatternMatch > ) : PatternMatchKind {
163
+ Debug . assert ( matches . length > 0 ) ;
164
+ let bestMatchKind = PatternMatchKind . camelCase ;
165
+
166
+ for ( const match of matches ) {
167
+ const kind = match . kind ;
168
+ if ( kind < bestMatchKind ) {
169
+ bestMatchKind = kind ;
170
+ }
203
171
}
172
+
173
+ return bestMatchKind ;
174
+ }
175
+
176
+ function compareNavigateToItems ( i1 : RawNavigateToItem , i2 : RawNavigateToItem ) : number {
177
+ // TODO(cyrusn): get the gamut of comparisons that VS already uses here.
178
+ // Right now we just sort by kind first, and then by name of the item.
179
+ // We first sort case insensitively. So "Aaa" will come before "bar".
180
+ // Then we sort case sensitively, so "aaa" will come before "Aaa".
181
+ return i1 . matchKind - i2 . matchKind ||
182
+ ts . compareStringsCaseInsensitive ( i1 . name , i2 . name ) ||
183
+ ts . compareStrings ( i1 . name , i2 . name ) ;
184
+ }
185
+
186
+ function createNavigateToItem ( rawItem : RawNavigateToItem ) : NavigateToItem {
187
+ const declaration = rawItem . declaration ;
188
+ const container = < Declaration > getContainerNode ( declaration ) ;
189
+ const containerName = container && getNameOfDeclaration ( container ) ;
190
+ return {
191
+ name : rawItem . name ,
192
+ kind : getNodeKind ( declaration ) ,
193
+ kindModifiers : getNodeModifiers ( declaration ) ,
194
+ matchKind : PatternMatchKind [ rawItem . matchKind ] ,
195
+ isCaseSensitive : rawItem . isCaseSensitive ,
196
+ fileName : rawItem . fileName ,
197
+ textSpan : createTextSpanFromNode ( declaration ) ,
198
+ // TODO(jfreeman): What should be the containerName when the container has a computed name?
199
+ containerName : containerName ? ( < Identifier > containerName ) . text : "" ,
200
+ containerKind : containerName ? getNodeKind ( container ) : ScriptElementKind . unknown
201
+ } ;
204
202
}
205
203
}
0 commit comments