@@ -21,16 +21,25 @@ 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.
27
24
/// </summary>
25
+ /// <remarks>
26
+ /// Dependency injection and logging are wrapped by factory methods on this class so that the
27
+ /// host assembly can construct the LSP and debug servers without directly depending on <see
28
+ /// cref="Microsoft.Extensions.Logging"/> and <see
29
+ /// cref="Microsoft.Extensions.DependencyInjection"/>.
30
+ /// </remarks>
28
31
internal class EditorServicesServerFactory : IDisposable
29
32
{
30
33
/// <summary>
31
- /// Create a new Editor Services factory.
32
- /// This method will instantiate logging.
34
+ /// Create a new Editor Services factory. This method will instantiate logging.
33
35
/// </summary>
36
+ /// <remarks>
37
+ /// This can only be called once because it sets global state (the logger) and that call is
38
+ /// in <see cref="EditorServicesRunner"/>.
39
+ ///
40
+ /// TODO: Why is this a static function wrapping a constructor instead of just a
41
+ /// constructor? In the end it returns an instance (albeit a "singleton").
42
+ /// </remarks>
34
43
/// <param name="logPath">The path of the log file to use.</param>
35
44
/// <param name="minimumLogLevel">The minimum log level to use.</param>
36
45
/// <returns></returns>
@@ -54,6 +63,9 @@ public static EditorServicesServerFactory Create(string logPath, int minimumLogL
54
63
return new EditorServicesServerFactory ( loggerFactory , ( LogLevel ) minimumLogLevel ) ;
55
64
}
56
65
66
+ // TODO: Can we somehow refactor this member so the language and debug servers can be
67
+ // instantiated using their constructors instead of tying them to this factory with `Create`
68
+ // methods?
57
69
private readonly ILoggerFactory _loggerFactory ;
58
70
59
71
private readonly Microsoft . Extensions . Logging . ILogger _logger ;
@@ -70,9 +82,13 @@ private EditorServicesServerFactory(ILoggerFactory loggerFactory, LogLevel minim
70
82
/// <summary>
71
83
/// Create the LSP server.
72
84
/// </summary>
85
+ /// <remarks>
86
+ /// This is only called once and that's in <see cref="EditorServicesRunner"/>.
87
+ /// </remarks>
73
88
/// <param name="inputStream">The protocol transport input stream.</param>
74
89
/// <param name="outputStream">The protocol transport output stream.</param>
75
- /// <param name="hostStartupInfo">The host details configuration for Editor Services instantation.</param>
90
+ /// <param name="hostStartupInfo">The host details configuration for Editor Services
91
+ /// instantation.</param>
76
92
/// <returns>A new, unstarted language server instance.</returns>
77
93
public PsesLanguageServer CreateLanguageServer (
78
94
Stream inputStream ,
@@ -85,25 +101,51 @@ public PsesLanguageServer CreateLanguageServer(
85
101
/// <summary>
86
102
/// Create the debug server given a language server instance.
87
103
/// </summary>
104
+ /// <remarks>
105
+ /// This is only called once and that's in <see cref="EditorServicesRunner"/>.
106
+ /// </remarks>
88
107
/// <param name="inputStream">The protocol transport input stream.</param>
89
108
/// <param name="outputStream">The protocol transport output stream.</param>
90
109
/// <param name="languageServer"></param>
91
110
/// <returns>A new, unstarted debug server instance.</returns>
92
- public PsesDebugServer CreateDebugServerWithLanguageServer ( Stream inputStream , Stream outputStream , PsesLanguageServer languageServer , bool usePSReadLine )
111
+ public PsesDebugServer CreateDebugServerWithLanguageServer (
112
+ Stream inputStream ,
113
+ Stream outputStream ,
114
+ PsesLanguageServer languageServer ,
115
+ bool usePSReadLine )
93
116
{
94
- return new PsesDebugServer ( _loggerFactory , inputStream , outputStream , languageServer . LanguageServer . Services , useTempSession : false , usePSReadLine ) ;
117
+ return new PsesDebugServer (
118
+ _loggerFactory ,
119
+ inputStream ,
120
+ outputStream ,
121
+ languageServer . LanguageServer . Services ,
122
+ useTempSession : false ,
123
+ usePSReadLine ) ;
95
124
}
96
125
97
126
/// <summary>
98
127
/// Create a new debug server based on an old one in an ended session.
99
128
/// </summary>
129
+ /// <remarks>
130
+ /// This is only called once and that's in <see cref="EditorServicesRunner"/>.
131
+ /// </remarks>
100
132
/// <param name="inputStream">The protocol transport input stream.</param>
101
133
/// <param name="outputStream">The protocol transport output stream.</param>
102
134
/// <param name="debugServer">The old debug server to recreate.</param>
103
135
/// <returns></returns>
104
- public PsesDebugServer RecreateDebugServer ( Stream inputStream , Stream outputStream , PsesDebugServer debugServer , bool usePSReadLine )
136
+ public PsesDebugServer RecreateDebugServer (
137
+ Stream inputStream ,
138
+ Stream outputStream ,
139
+ PsesDebugServer debugServer ,
140
+ bool usePSReadLine )
105
141
{
106
- return new PsesDebugServer ( _loggerFactory , inputStream , outputStream , debugServer . ServiceProvider , useTempSession : false , usePSReadLine ) ;
142
+ return new PsesDebugServer (
143
+ _loggerFactory ,
144
+ inputStream ,
145
+ outputStream ,
146
+ debugServer . ServiceProvider ,
147
+ useTempSession : false ,
148
+ usePSReadLine ) ;
107
149
}
108
150
109
151
/// <summary>
@@ -113,13 +155,16 @@ public PsesDebugServer RecreateDebugServer(Stream inputStream, Stream outputStre
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 ,
160
+ Stream outputStream ,
161
+ HostStartupInfo hostStartupInfo )
117
162
{
118
163
var serviceProvider = new ServiceCollection ( )
119
164
. AddLogging ( builder => builder
120
165
. ClearProviders ( )
121
166
. AddSerilog ( )
122
- . SetMinimumLevel ( LogLevel . Trace ) )
167
+ . SetMinimumLevel ( LogLevel . Trace ) ) // TODO: Why randomly set to trace?
123
168
. AddSingleton < ILanguageServerFacade > ( provider => null )
124
169
. AddPsesLanguageServices ( hostStartupInfo )
125
170
// For a Temp session, there is no LanguageServer so just set it to null
@@ -143,6 +188,14 @@ public PsesDebugServer CreateDebugServerForTempSession(Stream inputStream, Strea
143
188
usePSReadLine : hostStartupInfo . ConsoleReplEnabled && ! hostStartupInfo . UsesLegacyReadLine ) ;
144
189
}
145
190
191
+ /// <remarks>
192
+ /// TODO: This class probably should not be <see cref="IDisposable"/> as the primary
193
+ /// intention of that interface is to provide cleanup of unmanaged resources, which the
194
+ /// logger certainly is not. Nor is this class used with a <see langword="using"/>. Instead,
195
+ /// this class should call <see cref="Serilog.Log.CloseAndFlush()"/> in a finalizer. This
196
+ /// could potentially even be done with <see
197
+ /// cref="SerilogLoggerFactoryExtensions.AddSerilog"</> by passing <c>dispose=true</c>.
198
+ /// </remarks>
146
199
public void Dispose ( )
147
200
{
148
201
Log . CloseAndFlush ( ) ;
0 commit comments