@@ -138,7 +138,13 @@ namespace ts.NavigationBar {
138138 }
139139
140140 function sortNodes ( nodes : Node [ ] ) : Node [ ] {
141- return nodes . slice ( 0 ) . sort ( ( n1 : Declaration , n2 : Declaration ) => {
141+ const sortedCopy = nodes . slice ( 0 ) ;
142+ doSortNodes ( sortedCopy ) ;
143+ return sortedCopy ;
144+ }
145+
146+ function doSortNodes ( nodes : Node [ ] ) : void {
147+ nodes . sort ( ( n1 : Declaration , n2 : Declaration ) => {
142148 if ( n1 . name && n2 . name ) {
143149 return getPropertyNameForPropertyNameNode ( n1 . name ) . localeCompare ( getPropertyNameForPropertyNameNode ( n2 . name ) ) ;
144150 }
@@ -154,52 +160,63 @@ namespace ts.NavigationBar {
154160 } ) ;
155161 }
156162
157- function addTopLevelNodes ( nodes : Node [ ] , topLevelNodes : Node [ ] ) : void {
158- nodes = sortNodes ( nodes ) ;
159-
163+ // Add nodes in a single "level" of top-level nodes (as in, methods in a class.)
164+ // Nodes in a single "level" are sorted together.
165+ function addTopLevelNodes ( nodes : Node [ ] , higherLevel : Node [ ] ) : void {
166+ const thisLevel : Node [ ] = [ ] ;
160167 for ( const node of nodes ) {
161- switch ( node . kind ) {
162- case SyntaxKind . ClassExpression :
163- case SyntaxKind . ClassDeclaration :
164- topLevelNodes . push ( node ) ;
165- for ( const member of ( < ClassDeclaration > node ) . members ) {
166- if ( member . kind === SyntaxKind . MethodDeclaration || member . kind === SyntaxKind . Constructor ) {
167- type FunctionLikeMember = MethodDeclaration | ConstructorDeclaration ;
168- if ( ( < FunctionLikeMember > member ) . body ) {
169- // We do not include methods that does not have child functions in it, because of duplications.
170- if ( hasNamedFunctionDeclarations ( ( < Block > ( < FunctionLikeMember > member ) . body ) . statements ) ) {
171- topLevelNodes . push ( member ) ;
172- }
173- addTopLevelNodes ( ( < Block > ( < MethodDeclaration > member ) . body ) . statements , topLevelNodes ) ;
168+ addTopLevelNode ( node , thisLevel ) ;
169+ }
170+ doSortNodes ( thisLevel ) ;
171+
172+ for ( const node of thisLevel ) {
173+ higherLevel . push ( node ) ;
174+ }
175+ }
176+
177+ function addTopLevelNode ( node : Node , thisLevel : Node [ ] ) : void {
178+ switch ( node . kind ) {
179+ case SyntaxKind . ClassExpression :
180+ case SyntaxKind . ClassDeclaration :
181+ thisLevel . push ( node ) ;
182+ for ( const member of ( < ClassDeclaration > node ) . members ) {
183+ if ( member . kind === SyntaxKind . MethodDeclaration || member . kind === SyntaxKind . Constructor ) {
184+ type FunctionLikeMember = MethodDeclaration | ConstructorDeclaration ;
185+ if ( ( < FunctionLikeMember > member ) . body ) {
186+ // We do not include methods that does not have child functions in it, because of duplications.
187+ if ( hasNamedFunctionDeclarations ( ( < Block > ( < FunctionLikeMember > member ) . body ) . statements ) ) {
188+ thisLevel . push ( member ) ;
174189 }
190+ addTopLevelNodes ( ( < Block > ( < MethodDeclaration > member ) . body ) . statements , thisLevel ) ;
175191 }
176192 }
177- break ;
178- case SyntaxKind . EnumDeclaration :
179- case SyntaxKind . InterfaceDeclaration :
180- case SyntaxKind . TypeAliasDeclaration :
181- topLevelNodes . push ( node ) ;
182- break ;
193+ }
194+ break ;
183195
184- case SyntaxKind . ModuleDeclaration :
185- let moduleDeclaration = < ModuleDeclaration > node ;
186- topLevelNodes . push ( node ) ;
187- addTopLevelNodes ( ( < Block > getInnermostModule ( moduleDeclaration ) . body ) . statements , topLevelNodes ) ;
188- break ;
196+ case SyntaxKind . EnumDeclaration :
197+ case SyntaxKind . InterfaceDeclaration :
198+ case SyntaxKind . TypeAliasDeclaration :
199+ thisLevel . push ( node ) ;
200+ break ;
189201
190- case SyntaxKind . FunctionDeclaration :
191- let functionDeclaration = < FunctionLikeDeclaration > node ;
192- if ( isTopLevelFunctionDeclaration ( functionDeclaration ) ) {
193- topLevelNodes . push ( node ) ;
194- addTopLevelNodes ( ( < Block > functionDeclaration . body ) . statements , topLevelNodes ) ;
195- }
196- break ;
202+ case SyntaxKind . ModuleDeclaration :
203+ let moduleDeclaration = < ModuleDeclaration > node ;
204+ thisLevel . push ( node ) ;
205+ addTopLevelNodes ( ( < Block > getInnermostModule ( moduleDeclaration ) . body ) . statements , thisLevel ) ;
206+ break ;
197207
198- default :
199- const childrens : Node [ ] = [ ] ;
200- forEachChild ( node , child => { childrens . push ( child ) } ) ;
201- addTopLevelNodes ( childrens , topLevelNodes ) ;
202- }
208+ case SyntaxKind . FunctionDeclaration :
209+ let functionDeclaration = < FunctionLikeDeclaration > node ;
210+ if ( isTopLevelFunctionDeclaration ( functionDeclaration ) ) {
211+ thisLevel . push ( node ) ;
212+ addTopLevelNodes ( ( < Block > functionDeclaration . body ) . statements , thisLevel ) ;
213+ }
214+ break ;
215+
216+ default :
217+ // Nodes within nested expressions are still sorted as if they were top-level,
218+ // so in this case we recurse with `addTopLevelNode` rather than calling `addTopLevelNodes`.
219+ forEachChild ( node , child => addTopLevelNode ( child , thisLevel ) ) ;
203220 }
204221 }
205222
0 commit comments