1
- // Copyright (c) Microsoft Corporation.
1
+ // Copyright (c) Microsoft Corporation.
2
2
// Licensed under the MIT License.
3
3
4
- using System ;
5
4
using System . Collections . Generic ;
6
- using System . Diagnostics ;
7
5
using System . IO ;
8
- using System . Linq ;
9
6
using System . Threading ;
10
7
using System . Threading . Tasks ;
11
8
using Microsoft . Extensions . Logging ;
12
- using Microsoft . PowerShell . EditorServices . Logging ;
13
9
using Microsoft . PowerShell . EditorServices . Services ;
14
10
using Microsoft . PowerShell . EditorServices . Services . Symbols ;
15
11
using Microsoft . PowerShell . EditorServices . Services . TextDocument ;
@@ -23,6 +19,7 @@ namespace Microsoft.PowerShell.EditorServices.Handlers
23
19
{
24
20
internal class PsesDocumentSymbolHandler : DocumentSymbolHandlerBase
25
21
{
22
+ private static readonly SymbolInformationOrDocumentSymbolContainer s_emptySymbolInformationOrDocumentSymbolContainer = new ( ) ;
26
23
private readonly ILogger _logger ;
27
24
private readonly WorkspaceService _workspaceService ;
28
25
private readonly IDocumentSymbolProvider [ ] _providers ;
@@ -48,23 +45,21 @@ public PsesDocumentSymbolHandler(ILoggerFactory factory, WorkspaceService worksp
48
45
// AKA the outline feature
49
46
public override async Task < SymbolInformationOrDocumentSymbolContainer > Handle ( DocumentSymbolParams request , CancellationToken cancellationToken )
50
47
{
51
- ScriptFile scriptFile = _workspaceService . GetFile ( request . TextDocument . Uri ) ;
52
-
53
- IEnumerable < SymbolReference > foundSymbols = ProvideDocumentSymbols ( scriptFile ) ;
54
- if ( foundSymbols is null )
55
- {
56
- return null ;
57
- }
48
+ _logger . LogDebug ( $ "Handling document symbols for { request . TextDocument . Uri } ") ;
58
49
50
+ ScriptFile scriptFile = _workspaceService . GetFile ( request . TextDocument . Uri ) ;
59
51
string containerName = Path . GetFileNameWithoutExtension ( scriptFile . FilePath ) ;
60
-
61
52
List < SymbolInformationOrDocumentSymbol > symbols = new ( ) ;
62
- foreach ( SymbolReference r in foundSymbols )
53
+
54
+ foreach ( SymbolReference r in ProvideDocumentSymbols ( scriptFile ) )
63
55
{
64
56
// This async method is pretty dense with synchronous code
65
57
// so it's helpful to add some yields.
66
58
await Task . Yield ( ) ;
67
- cancellationToken . ThrowIfCancellationRequested ( ) ;
59
+ if ( cancellationToken . IsCancellationRequested )
60
+ {
61
+ break ;
62
+ }
68
63
69
64
// Outline view should only include declarations.
70
65
//
@@ -93,58 +88,27 @@ public override async Task<SymbolInformationOrDocumentSymbolContainer> Handle(Do
93
88
Location = new Location
94
89
{
95
90
Uri = DocumentUri . From ( r . FilePath ) ,
96
- Range = new Range ( r . NameRegion . ToRange ( ) . Start , r . ScriptRegion . ToRange ( ) . End ) // Jump to name start, but keep whole range to support symbol tree in outline
91
+ // Jump to name start, but keep whole range to support symbol tree in outline
92
+ Range = new Range ( r . NameRegion . ToRange ( ) . Start , r . ScriptRegion . ToRange ( ) . End )
97
93
} ,
98
94
Name = r . Name
99
95
} ) ) ;
100
96
}
101
97
102
- return new SymbolInformationOrDocumentSymbolContainer ( symbols ) ;
98
+ return symbols . Count == 0
99
+ ? s_emptySymbolInformationOrDocumentSymbolContainer
100
+ : new SymbolInformationOrDocumentSymbolContainer ( symbols ) ;
103
101
}
104
102
105
103
private IEnumerable < SymbolReference > ProvideDocumentSymbols ( ScriptFile scriptFile )
106
104
{
107
- return InvokeProviders ( p => p . ProvideDocumentSymbols ( scriptFile ) )
108
- . SelectMany ( r => r ) ;
109
- }
110
-
111
- /// <summary>
112
- /// Invokes the given function synchronously against all
113
- /// registered providers.
114
- /// </summary>
115
- /// <param name="invokeFunc">The function to be invoked.</param>
116
- /// <returns>
117
- /// An IEnumerable containing the results of all providers
118
- /// that were invoked successfully.
119
- /// </returns>
120
- protected IEnumerable < TResult > InvokeProviders < TResult > (
121
- Func < IDocumentSymbolProvider , TResult > invokeFunc )
122
- {
123
- Stopwatch invokeTimer = new ( ) ;
124
- List < TResult > providerResults = new ( ) ;
125
-
126
105
foreach ( IDocumentSymbolProvider provider in _providers )
127
106
{
128
- try
107
+ foreach ( SymbolReference symbol in provider . ProvideDocumentSymbols ( scriptFile ) )
129
108
{
130
- invokeTimer . Restart ( ) ;
131
-
132
- providerResults . Add ( invokeFunc ( provider ) ) ;
133
-
134
- invokeTimer . Stop ( ) ;
135
-
136
- _logger . LogTrace (
137
- $ "Invocation of provider '{ provider . GetType ( ) . Name } ' completed in { invokeTimer . ElapsedMilliseconds } ms.") ;
138
- }
139
- catch ( Exception e )
140
- {
141
- _logger . LogException (
142
- $ "Exception caught while invoking provider { provider . GetType ( ) . Name } :",
143
- e ) ;
109
+ yield return symbol ;
144
110
}
145
111
}
146
-
147
- return providerResults ;
148
112
}
149
113
}
150
114
}
0 commit comments