44//
55
66using Microsoft . PowerShell . EditorServices ;
7- using Microsoft . PowerShell . EditorServices . Console ;
8- using Microsoft . PowerShell . EditorServices . Session ;
97using Microsoft . PowerShell . EditorServices . Transport . Stdio . Event ;
108using Microsoft . PowerShell . EditorServices . Transport . Stdio . Message ;
9+ using Microsoft . PowerShell . EditorServices . Transport . Stdio . Model ;
1110using Microsoft . PowerShell . EditorServices . Transport . Stdio . Response ;
1211using Nito . AsyncEx ;
1312using System ;
13+ using System . IO ;
14+ using System . Management . Automation ;
1415using System . Reflection ;
1516using System . Text ;
1617using System . Threading ;
1718using System . Threading . Tasks ;
1819
19- namespace Microsoft . PowerShell . EditorServices . Transport . Stdio
20+ namespace Microsoft . PowerShell . EditorServices . Host
2021{
21- public class StdioHost : IHost
22+ public class MessageLoop : IHost
2223 {
2324 #region Private Fields
2425
26+ private Stream inputStream ;
27+ private Stream outputStream ;
2528 private IConsoleHost consoleHost ;
2629 private EditorSession editorSession ;
27- private SynchronizationContext syncContext ;
30+ private MessageReader messageReader ;
31+ private MessageWriter messageWriter ;
32+ private SynchronizationContext applicationSyncContext ;
33+ private SynchronizationContext messageLoopSyncContext ;
2834 private AsyncContextThread messageLoopThread ;
2935
3036 #endregion
@@ -41,12 +47,8 @@ Version IHost.Version
4147 get { throw new NotImplementedException ( ) ; }
4248 }
4349
44- void IHost . Start ( )
50+ public void Start ( )
4551 {
46- // Start a new EditorSession
47- // TODO: Allow multiple sessions?
48- this . editorSession = new EditorSession ( ) ;
49-
5052 // Start the main message loop
5153 AsyncContext . Run ( ( Func < Task > ) this . StartMessageLoop ) ;
5254 }
@@ -58,110 +60,54 @@ void IHost.Start()
5860 private async Task StartMessageLoop ( )
5961 {
6062 // Hold on to the current synchronization context
61- this . syncContext = SynchronizationContext . Current ;
63+ this . applicationSyncContext = SynchronizationContext . Current ;
6264
6365 // Start the message listener on another thread
6466 this . messageLoopThread = new AsyncContextThread ( true ) ;
6567 await this . messageLoopThread . Factory . Run ( ( ) => this . ListenForMessages ( ) ) ;
6668 }
6769
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- //}
13170 async Task ListenForMessages ( )
13271 {
72+ this . messageLoopSyncContext = SynchronizationContext . Current ;
73+
13374 // Ensure that the console is using UTF-8 encoding
13475 System . Console . InputEncoding = Encoding . UTF8 ;
13576 System . Console . OutputEncoding = Encoding . UTF8 ;
13677
13778 // Find all message types in this assembly
13879 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 ( ) ;
14085
14186 // Set up the reader and writer
142- MessageReader messageReader =
87+ this . messageReader =
14388 new MessageReader (
144- System . Console . In ,
145- MessageFormat . WithContentLength ,
89+ this . inputStream ,
14690 messageTypeResolver ) ;
14791
148- MessageWriter messageWriter =
92+ this . messageWriter =
14993 new MessageWriter (
150- System . Console . Out ,
151- MessageFormat . WithContentLength ,
94+ this . outputStream ,
15295 messageTypeResolver ) ;
15396
15497 // Set up the console host which will send events
15598 // through the MessageWriter
15699 this . consoleHost = new StdioConsoleHost ( messageWriter ) ;
157100
158101 // 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 ;
162108
163109 // Send a "started" event
164- messageWriter . WriteMessage (
110+ await this . messageWriter . WriteMessage (
165111 new StartedEvent ( ) ) ;
166112
167113 // Run the message loop
@@ -173,13 +119,13 @@ async Task ListenForMessages()
173119 try
174120 {
175121 // Read a message from stdin
176- newMessage = await messageReader . ReadMessage ( ) ;
122+ newMessage = await this . messageReader . ReadMessage ( ) ;
177123 }
178124 catch ( MessageParseException e )
179125 {
180126 // Write an error response
181- messageWriter . WriteMessage (
182- MessageErrorResponse . CreateParseErrorResponse ( e ) ) ;
127+ this . messageWriter . WriteMessage (
128+ MessageErrorResponse . CreateParseErrorResponse ( e ) ) . Wait ( ) ;
183129
184130 // Continue the loop
185131 continue ;
@@ -191,16 +137,16 @@ async Task ListenForMessages()
191137 {
192138 // Process the message. The processor will take care
193139 // of writing responses throguh the messageWriter.
194- messageProcessor . ProcessMessage (
195- editorSession ,
196- messageWriter ) ;
140+ await messageProcessor . ProcessMessage (
141+ this . editorSession ,
142+ this . messageWriter ) ;
197143 }
198144 else
199145 {
200146 if ( newMessage != null )
201147 {
202148 // Return an error response to keep the client moving
203- messageWriter . WriteMessage (
149+ await this . messageWriter . WriteMessage (
204150 MessageErrorResponse . CreateUnhandledMessageResponse (
205151 newMessage ) ) ;
206152 }
@@ -213,6 +159,48 @@ async Task ListenForMessages()
213159 }
214160 }
215161
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+
216204 #endregion
217205 }
218206}
0 commit comments