4
4
//
5
5
6
6
using Microsoft . PowerShell . EditorServices ;
7
- using Microsoft . PowerShell . EditorServices . Console ;
8
- using Microsoft . PowerShell . EditorServices . Session ;
9
7
using Microsoft . PowerShell . EditorServices . Transport . Stdio . Event ;
10
8
using Microsoft . PowerShell . EditorServices . Transport . Stdio . Message ;
9
+ using Microsoft . PowerShell . EditorServices . Transport . Stdio . Model ;
11
10
using Microsoft . PowerShell . EditorServices . Transport . Stdio . Response ;
12
11
using Nito . AsyncEx ;
13
12
using System ;
13
+ using System . IO ;
14
+ using System . Management . Automation ;
14
15
using System . Reflection ;
15
16
using System . Text ;
16
17
using System . Threading ;
17
18
using System . Threading . Tasks ;
18
19
19
- namespace Microsoft . PowerShell . EditorServices . Transport . Stdio
20
+ namespace Microsoft . PowerShell . EditorServices . Host
20
21
{
21
- public class StdioHost : IHost
22
+ public class MessageLoop : IHost
22
23
{
23
24
#region Private Fields
24
25
26
+ private Stream inputStream ;
27
+ private Stream outputStream ;
25
28
private IConsoleHost consoleHost ;
26
29
private EditorSession editorSession ;
27
- private SynchronizationContext syncContext ;
30
+ private MessageReader messageReader ;
31
+ private MessageWriter messageWriter ;
32
+ private SynchronizationContext applicationSyncContext ;
33
+ private SynchronizationContext messageLoopSyncContext ;
28
34
private AsyncContextThread messageLoopThread ;
29
35
30
36
#endregion
@@ -41,12 +47,8 @@ Version IHost.Version
41
47
get { throw new NotImplementedException ( ) ; }
42
48
}
43
49
44
- void IHost . Start ( )
50
+ public void Start ( )
45
51
{
46
- // Start a new EditorSession
47
- // TODO: Allow multiple sessions?
48
- this . editorSession = new EditorSession ( ) ;
49
-
50
52
// Start the main message loop
51
53
AsyncContext . Run ( ( Func < Task > ) this . StartMessageLoop ) ;
52
54
}
@@ -58,110 +60,54 @@ void IHost.Start()
58
60
private async Task StartMessageLoop ( )
59
61
{
60
62
// Hold on to the current synchronization context
61
- this . syncContext = SynchronizationContext . Current ;
63
+ this . applicationSyncContext = SynchronizationContext . Current ;
62
64
63
65
// Start the message listener on another thread
64
66
this . messageLoopThread = new AsyncContextThread ( true ) ;
65
67
await this . messageLoopThread . Factory . Run ( ( ) => this . ListenForMessages ( ) ) ;
66
68
}
67
69
68
- //private async Task ListenForMessages()
69
- //{
70
- // // Ensure that the console is using UTF-8 encoding
71
- // System.Console.InputEncoding = Encoding.UTF8;
72
- // System.Console.OutputEncoding = Encoding.UTF8;
73
-
74
- // // Set up the reader and writer
75
- // MessageReader messageReader =
76
- // new MessageReader(
77
- // System.Console.In,
78
- // MessageFormat.WithoutContentLength);
79
-
80
- // MessageWriter messageWriter =
81
- // new MessageWriter(
82
- // System.Console.Out,
83
- // MessageFormat.WithContentLength);
84
-
85
- // this.ConsoleHost = new StdioConsoleHost(messageWriter);
86
-
87
- // // Set up the PowerShell session
88
- // // TODO: Do this elsewhere
89
- // EditorSession editorSession = new EditorSession();
90
- // editorSession.StartSession(this.ConsoleHost);
91
-
92
- // // Send a "started" event
93
- // messageWriter.WriteMessage(
94
- // new Event<object>
95
- // {
96
- // EventType = "started"
97
- // });
98
-
99
- // // Run the message loop
100
- // bool isRunning = true;
101
- // while(isRunning)
102
- // {
103
- // // Read a message
104
- // Message newMessage = await messageReader.ReadMessage();
105
-
106
- // // Is the message a request?
107
- // IMessageProcessor messageProcessor = newMessage as IMessageProcessor;
108
- // if (messageProcessor != null)
109
- // {
110
- // // Process the request on the host thread
111
- // messageProcessor.ProcessMessage(
112
- // editorSession,
113
- // messageWriter);
114
- // }
115
- // else
116
- // {
117
- // if (newMessage != null)
118
- // {
119
- // // Return an error response to keep the client moving
120
- // messageWriter.WriteMessage(
121
- // new Response<object>
122
- // {
123
- // Command = request != null ? request.Command : string.Empty,
124
- // RequestSeq = newMessage.Seq,
125
- // Success = false,
126
- // });
127
- // }
128
- // }
129
- // }
130
- //}
131
70
async Task ListenForMessages ( )
132
71
{
72
+ this . messageLoopSyncContext = SynchronizationContext . Current ;
73
+
133
74
// Ensure that the console is using UTF-8 encoding
134
75
System . Console . InputEncoding = Encoding . UTF8 ;
135
76
System . Console . OutputEncoding = Encoding . UTF8 ;
136
77
137
78
// Find all message types in this assembly
138
79
MessageTypeResolver messageTypeResolver = new MessageTypeResolver ( ) ;
139
- messageTypeResolver . ScanForMessageTypes ( Assembly . GetExecutingAssembly ( ) ) ;
80
+ messageTypeResolver . ScanForMessageTypes ( typeof ( StartedEvent ) . Assembly ) ;
81
+
82
+ // Open the standard input/output streams
83
+ this . inputStream = System . Console . OpenStandardInput ( ) ;
84
+ this . outputStream = System . Console . OpenStandardOutput ( ) ;
140
85
141
86
// Set up the reader and writer
142
- MessageReader messageReader =
87
+ this . messageReader =
143
88
new MessageReader (
144
- System . Console . In ,
145
- MessageFormat . WithContentLength ,
89
+ this . inputStream ,
146
90
messageTypeResolver ) ;
147
91
148
- MessageWriter messageWriter =
92
+ this . messageWriter =
149
93
new MessageWriter (
150
- System . Console . Out ,
151
- MessageFormat . WithContentLength ,
94
+ this . outputStream ,
152
95
messageTypeResolver ) ;
153
96
154
97
// Set up the console host which will send events
155
98
// through the MessageWriter
156
99
this . consoleHost = new StdioConsoleHost ( messageWriter ) ;
157
100
158
101
// Set up the PowerShell session
159
- // TODO: Do this elsewhere
160
- EditorSession editorSession = new EditorSession ( ) ;
161
- editorSession . StartSession ( this . consoleHost ) ;
102
+ this . editorSession = new EditorSession ( ) ;
103
+ this . editorSession . StartSession ( this . consoleHost ) ;
104
+
105
+ // Attach to events from the PowerShell session
106
+ this . editorSession . PowerShellSession . OutputWritten += PowerShellSession_OutputWritten ;
107
+ this . editorSession . DebugService . DebuggerStopped += DebugService_DebuggerStopped ;
162
108
163
109
// Send a "started" event
164
- messageWriter . WriteMessage (
110
+ await this . messageWriter . WriteMessage (
165
111
new StartedEvent ( ) ) ;
166
112
167
113
// Run the message loop
@@ -173,13 +119,13 @@ async Task ListenForMessages()
173
119
try
174
120
{
175
121
// Read a message from stdin
176
- newMessage = await messageReader . ReadMessage ( ) ;
122
+ newMessage = await this . messageReader . ReadMessage ( ) ;
177
123
}
178
124
catch ( MessageParseException e )
179
125
{
180
126
// Write an error response
181
- messageWriter . WriteMessage (
182
- MessageErrorResponse . CreateParseErrorResponse ( e ) ) ;
127
+ this . messageWriter . WriteMessage (
128
+ MessageErrorResponse . CreateParseErrorResponse ( e ) ) . Wait ( ) ;
183
129
184
130
// Continue the loop
185
131
continue ;
@@ -191,16 +137,16 @@ async Task ListenForMessages()
191
137
{
192
138
// Process the message. The processor will take care
193
139
// of writing responses throguh the messageWriter.
194
- messageProcessor . ProcessMessage (
195
- editorSession ,
196
- messageWriter ) ;
140
+ await messageProcessor . ProcessMessage (
141
+ this . editorSession ,
142
+ this . messageWriter ) ;
197
143
}
198
144
else
199
145
{
200
146
if ( newMessage != null )
201
147
{
202
148
// Return an error response to keep the client moving
203
- messageWriter . WriteMessage (
149
+ await this . messageWriter . WriteMessage (
204
150
MessageErrorResponse . CreateUnhandledMessageResponse (
205
151
newMessage ) ) ;
206
152
}
@@ -213,6 +159,48 @@ async Task ListenForMessages()
213
159
}
214
160
}
215
161
162
+ async void DebugService_DebuggerStopped ( object sender , DebuggerStopEventArgs e )
163
+ {
164
+ // Push the write operation to the correct thread
165
+ this . messageLoopSyncContext . Post (
166
+ async ( obj ) =>
167
+ {
168
+ await this . messageWriter . WriteMessage (
169
+ new StoppedEvent
170
+ {
171
+ Body = new StoppedEventBody
172
+ {
173
+ Source = new Source
174
+ {
175
+ Path = e . InvocationInfo . ScriptName ,
176
+ } ,
177
+ Line = e . InvocationInfo . ScriptLineNumber ,
178
+ Column = e . InvocationInfo . OffsetInLine ,
179
+ ThreadId = 1 , // TODO: Change this based on context
180
+ Reason = "breakpoint" // TODO: Change this based on context
181
+ }
182
+ } ) ;
183
+ } , null ) ;
184
+ }
185
+
186
+ void PowerShellSession_OutputWritten ( object sender , OutputWrittenEventArgs e )
187
+ {
188
+ // TODO: change this to use the OutputEvent!
189
+
190
+ //await this.messageWriter.WriteMessage(
191
+ // new ReplWriteOutputEvent
192
+ // {
193
+ // Body = new ReplWriteOutputEventBody
194
+ // {
195
+ // LineContents = e.OutputText,
196
+ // LineType = e.OutputType,
197
+ // IncludeNewLine = e.IncludeNewLine,
198
+ // ForegroundColor = e.ForegroundColor,
199
+ // BackgroundColor = e.BackgroundColor
200
+ // }
201
+ // });
202
+ }
203
+
216
204
#endregion
217
205
}
218
206
}
0 commit comments