@@ -21,15 +21,22 @@ namespace Microsoft.PowerShell.EditorServices.Hosting
21
21
{
22
22
/// <summary>
23
23
/// Factory class for hiding dependencies of Editor Services.
24
- /// In particular, dependency injection and logging are wrapped by factory methods on this class
25
- /// so that the host assembly can construct the LSP and debug servers
26
- /// without taking logging or dependency injection dependencies directly.
24
+ ///
25
+ /// NOTE: dependency injection and logging are wrapped by factory methods on this class so that
26
+ /// the host assembly can construct the LSP and debug servers without directly depending on <see
27
+ /// cref="Microsoft.Extensions.Logging"/>
28
+ /// and <see cref="Microsoft.Extensions.DependencyInjection"/>.
27
29
/// </summary>
28
30
internal class EditorServicesServerFactory : IDisposable
29
31
{
30
32
/// <summary>
31
- /// Create a new Editor Services factory.
32
- /// This method will instantiate logging.
33
+ /// Create a new Editor Services factory. This method will instantiate logging.
34
+ ///
35
+ /// NOTE: This can only be called once because it sets global state (the logger) and that
36
+ /// call is in <see cref="EditorServicesRunner"/>.
37
+ ///
38
+ /// TODO: Why is this a static function wrapping a constructor instead of just a
39
+ /// constructor? In the end it returns an instance (albeit a "singleton").
33
40
/// </summary>
34
41
/// <param name="logPath">The path of the log file to use.</param>
35
42
/// <param name="minimumLogLevel">The minimum log level to use.</param>
@@ -69,10 +76,15 @@ private EditorServicesServerFactory(ILoggerFactory loggerFactory, LogLevel minim
69
76
70
77
/// <summary>
71
78
/// Create the LSP server.
79
+ ///
80
+ /// NOTE: This is only called once and that's in <see cref="EditorServicesRunner"/>.
81
+ ///
82
+ /// TODO: Why is this a method on this class? It only uses <see cref="_loggerFactory"/>.
72
83
/// </summary>
73
84
/// <param name="inputStream">The protocol transport input stream.</param>
74
85
/// <param name="outputStream">The protocol transport output stream.</param>
75
- /// <param name="hostStartupInfo">The host details configuration for Editor Services instantation.</param>
86
+ /// <param name="hostStartupInfo">The host details configuration for Editor Services
87
+ /// instantation.</param>
76
88
/// <returns>A new, unstarted language server instance.</returns>
77
89
public PsesLanguageServer CreateLanguageServer (
78
90
Stream inputStream ,
@@ -84,42 +96,73 @@ public PsesLanguageServer CreateLanguageServer(
84
96
85
97
/// <summary>
86
98
/// Create the debug server given a language server instance.
99
+ ///
100
+ /// NOTE: This is only called once and that's in <see cref="EditorServicesRunner"/>.
101
+ ///
102
+ /// TODO: Why is this a method on this class? It only uses <see cref="_loggerFactory"/>.
87
103
/// </summary>
88
104
/// <param name="inputStream">The protocol transport input stream.</param>
89
105
/// <param name="outputStream">The protocol transport output stream.</param>
90
106
/// <param name="languageServer"></param>
91
107
/// <returns>A new, unstarted debug server instance.</returns>
92
- public PsesDebugServer CreateDebugServerWithLanguageServer ( Stream inputStream , Stream outputStream , PsesLanguageServer languageServer , bool usePSReadLine )
108
+ public PsesDebugServer CreateDebugServerWithLanguageServer (
109
+ Stream inputStream ,
110
+ Stream outputStream ,
111
+ PsesLanguageServer languageServer ,
112
+ bool usePSReadLine )
93
113
{
94
- return new PsesDebugServer ( _loggerFactory , inputStream , outputStream , languageServer . LanguageServer . Services , useTempSession : false , usePSReadLine ) ;
114
+ return new PsesDebugServer (
115
+ _loggerFactory ,
116
+ inputStream ,
117
+ outputStream ,
118
+ languageServer . LanguageServer . Services ,
119
+ useTempSession : false ,
120
+ usePSReadLine ) ;
95
121
}
96
122
97
123
/// <summary>
98
124
/// Create a new debug server based on an old one in an ended session.
125
+ ///
126
+ /// NOTE: This is only called once and that's in <see cref="EditorServicesRunner"/>.
127
+ ///
128
+ /// TODO: Why is this a method on this class? It only uses <see cref="_loggerFactory"/>.
99
129
/// </summary>
100
130
/// <param name="inputStream">The protocol transport input stream.</param>
101
131
/// <param name="outputStream">The protocol transport output stream.</param>
102
132
/// <param name="debugServer">The old debug server to recreate.</param>
103
133
/// <returns></returns>
104
- public PsesDebugServer RecreateDebugServer ( Stream inputStream , Stream outputStream , PsesDebugServer debugServer , bool usePSReadLine )
134
+ public PsesDebugServer RecreateDebugServer (
135
+ Stream inputStream ,
136
+ Stream outputStream ,
137
+ PsesDebugServer debugServer ,
138
+ bool usePSReadLine )
105
139
{
106
- return new PsesDebugServer ( _loggerFactory , inputStream , outputStream , debugServer . ServiceProvider , useTempSession : false , usePSReadLine ) ;
140
+ return new PsesDebugServer (
141
+ _loggerFactory ,
142
+ inputStream ,
143
+ outputStream ,
144
+ debugServer . ServiceProvider ,
145
+ useTempSession : false ,
146
+ usePSReadLine ) ;
107
147
}
108
148
109
149
/// <summary>
110
150
/// Create a standalone debug server for temp sessions.
151
+ ///
152
+ /// TODO: What is a "temp session" and how is this different?
111
153
/// </summary>
112
154
/// <param name="inputStream">The protocol transport input stream.</param>
113
155
/// <param name="outputStream">The protocol transport output stream.</param>
114
156
/// <param name="hostStartupInfo">The host startup configuration to create the server session with.</param>
115
157
/// <returns></returns>
116
- public PsesDebugServer CreateDebugServerForTempSession ( Stream inputStream , Stream outputStream , HostStartupInfo hostStartupInfo )
158
+ public PsesDebugServer CreateDebugServerForTempSession (
159
+ Stream inputStream , Stream outputStream , HostStartupInfo hostStartupInfo )
117
160
{
118
161
var serviceProvider = new ServiceCollection ( )
119
162
. AddLogging ( builder => builder
120
163
. ClearProviders ( )
121
164
. AddSerilog ( )
122
- . SetMinimumLevel ( LogLevel . Trace ) )
165
+ . SetMinimumLevel ( LogLevel . Trace ) ) // TODO: Why randomly set to trace?
123
166
. AddSingleton < ILanguageServerFacade > ( provider => null )
124
167
. AddPsesLanguageServices ( hostStartupInfo )
125
168
// For a Temp session, there is no LanguageServer so just set it to null
@@ -143,6 +186,14 @@ public PsesDebugServer CreateDebugServerForTempSession(Stream inputStream, Strea
143
186
usePSReadLine : hostStartupInfo . ConsoleReplEnabled && ! hostStartupInfo . UsesLegacyReadLine ) ;
144
187
}
145
188
189
+ /// <summary>
190
+ /// TODO: This class probably should not be <see cref="IDisposable"/> as the primary
191
+ /// intention of that interface is to provide cleanup of unmanaged resources, which the
192
+ /// logger certainly is not. Nor is this class used with a <see langword="using"/>. Instead,
193
+ /// this class should call <see cref="Serilog.Log.CloseAndFlush()"/> in a finalizer. This
194
+ /// could potentially even be done with <see
195
+ /// cref="SerilogLoggerFactoryExtensions.AddSerilog"</> by passing <c>dispose=true</c>.
196
+ /// </summary>
146
197
public void Dispose ( )
147
198
{
148
199
Log . CloseAndFlush ( ) ;
0 commit comments