@@ -21,185 +21,183 @@ namespace ts.NavigateTo {
2121 }
2222
2323 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 ) ;
5425 } ) ;
5526 }
5627
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-
7028 rawItems . sort ( compareNavigateToItems ) ;
7129 if ( maxResultCount !== undefined ) {
7230 rawItems = rawItems . slice ( 0 , maxResultCount ) ;
7331 }
32+ return rawItems . map ( createNavigateToItem ) ;
33+ }
7434
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 ) ;
7839
79- function allMatchesAreCaseSensitive ( matches : PatternMatch [ ] ) : boolean {
80- Debug . assert ( matches . length > 0 ) ;
40+ if ( ! matches ) {
41+ return ; // continue to next named declarations
42+ }
8143
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 ;
8747 }
8848
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 ;
10756 }
10857 }
10958
110- return true ;
59+ const matchKind = bestMatchKind ( containerMatches ) ;
60+ const isCaseSensitive = allMatchesAreCaseSensitive ( containerMatches ) ;
61+ rawItems . push ( { name, fileName, matchKind, isCaseSensitive, declaration } ) ;
11162 }
63+ }
11264
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 :
12274 return true ;
123- }
75+ }
76+ }
12477
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 ) ;
13080
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 ;
13285 }
133-
134- return false ;
13586 }
13687
137- function getContainers ( declaration : Declaration ) {
138- const containers : string [ ] = [ ] ;
88+ return true ;
89+ }
13990
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 ) {
14293 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 ;
146105 }
147106 }
107+ }
148108
149- // Now, walk up our containers, adding all their names to the container array.
150- declaration = getContainerNode ( declaration ) ;
109+ return true ;
110+ }
151111
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+ }
156123
157- declaration = getContainerNode ( declaration ) ;
124+ if ( expression . kind === SyntaxKind . PropertyAccessExpression ) {
125+ const propertyAccess = < PropertyAccessExpression > expression ;
126+ if ( includeLastPortion ) {
127+ containers . unshift ( propertyAccess . name . text ) ;
158128 }
159129
160- return containers ;
130+ return tryAddComputedPropertyName ( propertyAccess . expression , containers , /*includeLastPortion*/ true ) ;
161131 }
162132
163- function bestMatchKind ( matches : PatternMatch [ ] ) {
164- Debug . assert ( matches . length > 0 ) ;
165- let bestMatchKind = PatternMatchKind . camelCase ;
133+ return false ;
134+ }
166135
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 [ ] = [ ] ;
173138
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+ }
175146 }
176147
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 ) ;
185157 }
186158
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+ }
203171 }
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+ } ;
204202 }
205203}
0 commit comments