1414// See the Apache Version 2.0 License for specific language governing
1515// permissions and limitations under the License.
1616
17+ using System ;
1718using System . Collections . Generic ;
1819using System . Linq ;
1920using System . Threading ;
2627
2728namespace Microsoft . Python . LanguageServer . Implementation {
2829 public sealed partial class Server {
29- private static int _symbolHierarchyDepthLimit = 1 ;
30+ private static int _symbolHierarchyMaxSymbols = 1000 ;
3031
3132 public override async Task < SymbolInformation [ ] > WorkspaceSymbols ( WorkspaceSymbolParams @params , CancellationToken cancellationToken ) {
3233 await WaitForCompleteAnalysisAsync ( cancellationToken ) ;
@@ -82,16 +83,16 @@ private static IEnumerable<IMemberResult> GetModuleVariables(ProjectEntry entry,
8283 }
8384 return false ;
8485 } )
85- . Concat ( GetChildScopesVariables ( analysis , analysis . Scope , opts , 0 ) ) ;
86+ . Take ( _symbolHierarchyMaxSymbols )
87+ . Concat ( GetChildScopesVariables ( analysis , analysis . Scope , opts ) )
88+ . Take ( _symbolHierarchyMaxSymbols ) ;
8689 }
8790
88- private static IEnumerable < IMemberResult > GetChildScopesVariables ( IModuleAnalysis analysis , IScope scope , GetMemberOptions opts , int currentDepth )
89- => currentDepth < _symbolHierarchyDepthLimit
90- ? scope . Children . SelectMany ( c => GetScopeVariables ( analysis , c , opts , currentDepth ) )
91- : Enumerable . Empty < IMemberResult > ( ) ;
91+ private static IEnumerable < IMemberResult > GetChildScopesVariables ( IModuleAnalysis analysis , IScope scope , GetMemberOptions opts )
92+ => scope . TraverseBreadthFirst ( s => s . Children ) . SelectMany ( c => GetScopeVariables ( analysis , c , opts ) ) ;
9293
93- private static IEnumerable < IMemberResult > GetScopeVariables ( IModuleAnalysis analysis , IScope scope , GetMemberOptions opts , int currentDepth )
94- => analysis . GetAllAvailableMembersFromScope ( scope , opts ) . Concat ( GetChildScopesVariables ( analysis , scope , opts , currentDepth + 1 ) ) ;
94+ private static IEnumerable < IMemberResult > GetScopeVariables ( IModuleAnalysis analysis , IScope scope , GetMemberOptions opts )
95+ => analysis . GetAllAvailableMembersFromScope ( scope , opts ) . Concat ( GetChildScopesVariables ( analysis , scope , opts ) ) ;
9596
9697 private SymbolInformation ToSymbolInformation ( IMemberResult m ) {
9798 var res = new SymbolInformation {
@@ -115,8 +116,9 @@ private SymbolInformation ToSymbolInformation(IMemberResult m) {
115116 }
116117
117118 private DocumentSymbol [ ] ToDocumentSymbols ( List < IMemberResult > members ) {
118- var childMap = new Dictionary < IMemberResult , List < IMemberResult > > ( ) ;
119119 var topLevel = new List < IMemberResult > ( ) ;
120+ var childMap = new Dictionary < IMemberResult , List < IMemberResult > > ( ) ;
121+ var totalCount = 0 ;
120122
121123 foreach ( var m in members ) {
122124 var parent = members . FirstOrDefault ( x => x . Scope ? . Node == m . Scope ? . OuterScope ? . Node && x . Name == m . Scope ? . Name ) ;
@@ -128,18 +130,23 @@ private DocumentSymbol[] ToDocumentSymbols(List<IMemberResult> members) {
128130 } else {
129131 topLevel . Add ( m ) ;
130132 }
133+ if ( ++ totalCount >= _symbolHierarchyMaxSymbols ) {
134+ break ;
135+ }
131136 }
132137
133- var symbols = topLevel
134- . GroupBy ( mr => mr . Name )
135- . Select ( g => g . First ( ) )
136- . Select ( m => ToDocumentSymbol ( m , childMap , 0 ) )
137- . ToArray ( ) ;
138+ var symbols = topLevel . SelectMany ( t => t
139+ . TraverseBreadthFirst ( c => childMap . ContainsKey ( c ) ? childMap [ c ] : Enumerable . Empty < IMemberResult > ( ) )
140+ . Take ( _symbolHierarchyMaxSymbols )
141+ . GroupBy ( mr => mr . Name )
142+ . Select ( g => g . First ( ) )
143+ . Select ( m => ToDocumentSymbol ( m , childMap ) ) )
144+ . ToArray ( ) ;
138145
139146 return symbols ;
140147 }
141148
142- private DocumentSymbol ToDocumentSymbol ( IMemberResult m , Dictionary < IMemberResult , List < IMemberResult > > childMap , int currentDepth ) {
149+ private DocumentSymbol ToDocumentSymbol ( IMemberResult m , Dictionary < IMemberResult , List < IMemberResult > > childMap ) {
143150 var res = new DocumentSymbol {
144151 name = m . Name ,
145152 detail = m . Name ,
@@ -148,10 +155,12 @@ private DocumentSymbol ToDocumentSymbol(IMemberResult m, Dictionary<IMemberResul
148155 _functionKind = GetFunctionKind ( m )
149156 } ;
150157
151- if ( childMap . TryGetValue ( m , out var children ) && currentDepth < _symbolHierarchyDepthLimit ) {
152- res . children = children . Select ( x => ToDocumentSymbol ( x , childMap , currentDepth + 1 ) ) . ToArray ( ) ;
158+ if ( childMap . TryGetValue ( m , out var children ) ) {
159+ res . children = children
160+ . Select ( x => ToDocumentSymbol ( x , childMap ) )
161+ . ToArray ( ) ;
153162 } else {
154- res . children = new DocumentSymbol [ 0 ] ;
163+ res . children = Array . Empty < DocumentSymbol > ( ) ;
155164 }
156165
157166 var loc = m . Locations . FirstOrDefault ( l => ! string . IsNullOrEmpty ( l . FilePath ) ) ;
0 commit comments