Skip to content

Commit 7bdb8e2

Browse files
all handlers
1 parent be3426d commit 7bdb8e2

17 files changed

+1015
-100
lines changed

src/PowerShellEditorServices.Engine/PowerShellEditorServices.Engine.csproj

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,4 @@
3131
<PackageReference Include="UnixConsoleEcho" Version="0.1.0" />
3232
<PackageReference Include="OmniSharp.Extensions.DebugAdapter.Server" Version="1.0.0" />
3333
</ItemGroup>
34-
35-
<ItemGroup>
36-
<Folder Include="Services\DebugAdapter\Handlers\" />
37-
<Folder Include="Services\DebugAdapter\Debugging\" />
38-
</ItemGroup>
3934
</Project>

src/PowerShellEditorServices.Engine/Server/PsesDebugServer.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider)
4444
ILogger logger = options.LoggerFactory.CreateLogger("DebugOptionsStartup");
4545
options.Services = new ServiceCollection()
4646
.AddSingleton(languageServerServiceProvider.GetService<PowerShellContextService>())
47+
.AddSingleton(languageServerServiceProvider.GetService<WorkspaceService>())
4748
.AddSingleton<PsesDebugServer>(this)
4849
.AddSingleton<DebugService>()
4950
.AddSingleton<DebugStateService>()
@@ -59,7 +60,23 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider)
5960
.WithHandler<InitializeHandler>()
6061
.WithHandler<LaunchHandler>()
6162
.WithHandler<AttachHandler>()
62-
.WithHandler<DisconnectHandler>();
63+
.WithHandler<DisconnectHandler>()
64+
.WithHandler<SetFunctionBreakpointsHandler>()
65+
.WithHandler<SetExceptionBreakpointsHandler>()
66+
.WithHandler<ConfigurationDoneHandler>()
67+
.WithHandler<ThreadsHandler>()
68+
.WithHandler<SetBreakpointsHandler>()
69+
.WithHandler<StackTraceHandler>()
70+
.WithHandler<ScopesHandler>()
71+
.WithHandler<VariablesHandler>()
72+
.WithHandler<ContinueHandler>()
73+
.WithHandler<NextHandler>()
74+
.WithHandler<PauseHandler>()
75+
.WithHandler<StepInHandler>()
76+
.WithHandler<StepOutHandler>()
77+
.WithHandler<SourceHandler>()
78+
.WithHandler<SetVariableHandler>()
79+
.WithHandler<DebugEvaluateHandler>();
6380

6481
logger.LogInformation("Handlers added");
6582
});

src/PowerShellEditorServices.Engine/Services/DebugAdapter/DebugEventHandlerService.cs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,32 @@ public DebugEventHandlerService(
3737

3838
internal void RegisterEventHandlers()
3939
{
40-
_powerShellContextService.RunspaceChanged += PowerShellContext_RunspaceChangedAsync;
41-
_debugService.BreakpointUpdated += DebugService_BreakpointUpdatedAsync;
42-
_debugService.DebuggerStopped += DebugService_DebuggerStoppedAsync;
43-
_powerShellContextService.DebuggerResumed += PowerShellContext_DebuggerResumedAsync;
40+
_powerShellContextService.RunspaceChanged += PowerShellContext_RunspaceChanged;
41+
_debugService.BreakpointUpdated += DebugService_BreakpointUpdated;
42+
_debugService.DebuggerStopped += DebugService_DebuggerStopped;
43+
_powerShellContextService.DebuggerResumed += PowerShellContext_DebuggerResumed;
4444
}
4545

4646
internal void UnregisterEventHandlers()
4747
{
48-
_powerShellContextService.RunspaceChanged -= PowerShellContext_RunspaceChangedAsync;
49-
_debugService.BreakpointUpdated -= DebugService_BreakpointUpdatedAsync;
50-
_debugService.DebuggerStopped -= DebugService_DebuggerStoppedAsync;
51-
_powerShellContextService.DebuggerResumed -= PowerShellContext_DebuggerResumedAsync;
48+
_powerShellContextService.RunspaceChanged -= PowerShellContext_RunspaceChanged;
49+
_debugService.BreakpointUpdated -= DebugService_BreakpointUpdated;
50+
_debugService.DebuggerStopped -= DebugService_DebuggerStopped;
51+
_powerShellContextService.DebuggerResumed -= PowerShellContext_DebuggerResumed;
5252
}
5353

54+
#region Public methods
55+
56+
internal void TriggerDebuggerStopped(DebuggerStoppedEventArgs e)
57+
{
58+
DebugService_DebuggerStopped(null, e);
59+
}
60+
61+
#endregion
62+
5463
#region Event Handlers
5564

56-
private void DebugService_DebuggerStoppedAsync(object sender, DebuggerStoppedEventArgs e)
65+
private void DebugService_DebuggerStopped(object sender, DebuggerStoppedEventArgs e)
5766
{
5867
// Provide the reason for why the debugger has stopped script execution.
5968
// See https://github.com/Microsoft/vscode/issues/3648
@@ -78,7 +87,7 @@ e.OriginalEvent.Breakpoints[0] is CommandBreakpoint
7887
});
7988
}
8089

81-
private void PowerShellContext_RunspaceChangedAsync(object sender, RunspaceChangedEventArgs e)
90+
private void PowerShellContext_RunspaceChanged(object sender, RunspaceChangedEventArgs e)
8291
{
8392
if (_debugStateService.WaitingForAttach &&
8493
e.ChangeAction == RunspaceChangeAction.Enter &&
@@ -105,7 +114,7 @@ private void PowerShellContext_RunspaceChangedAsync(object sender, RunspaceChang
105114
}
106115
}
107116

108-
private void PowerShellContext_DebuggerResumedAsync(object sender, DebuggerResumeAction e)
117+
private void PowerShellContext_DebuggerResumed(object sender, DebuggerResumeAction e)
109118
{
110119
_jsonRpcServer.SendNotification(EventNames.Continued,
111120
new ContinuedEvent
@@ -115,7 +124,7 @@ private void PowerShellContext_DebuggerResumedAsync(object sender, DebuggerResum
115124
});
116125
}
117126

118-
private void DebugService_BreakpointUpdatedAsync(object sender, BreakpointUpdatedEventArgs e)
127+
private void DebugService_BreakpointUpdated(object sender, BreakpointUpdatedEventArgs e)
119128
{
120129
string reason = "changed";
121130

@@ -140,7 +149,7 @@ private void DebugService_BreakpointUpdatedAsync(object sender, BreakpointUpdate
140149
OmniSharp.Extensions.DebugAdapter.Protocol.Models.Breakpoint breakpoint;
141150
if (e.Breakpoint is LineBreakpoint)
142151
{
143-
breakpoint = LspBreakpointUtils.CreateBreakpoint(BreakpointDetails.Create(e.Breakpoint));
152+
breakpoint = LspDebugUtils.CreateBreakpoint(BreakpointDetails.Create(e.Breakpoint));
144153
}
145154
else if (e.Breakpoint is CommandBreakpoint)
146155
{
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
//
2+
// Copyright (c) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4+
//
5+
6+
using System;
7+
using System.IO;
8+
using System.Linq;
9+
using System.Threading;
10+
using System.Threading.Tasks;
11+
using Microsoft.Extensions.Logging;
12+
using Microsoft.PowerShell.EditorServices.Engine.Logging;
13+
using Microsoft.PowerShell.EditorServices.Engine.Services;
14+
using Microsoft.PowerShell.EditorServices.Engine.Services.DebugAdapter;
15+
using Microsoft.PowerShell.EditorServices.Engine.Services.TextDocument;
16+
using Microsoft.PowerShell.EditorServices.Utility;
17+
using OmniSharp.Extensions.DebugAdapter.Protocol.Models;
18+
using OmniSharp.Extensions.DebugAdapter.Protocol.Requests;
19+
20+
namespace Microsoft.PowerShell.EditorServices.Engine.Handlers
21+
{
22+
public class SetFunctionBreakpointsHandler : ISetFunctionBreakpointsHandler
23+
{
24+
private readonly ILogger _logger;
25+
private readonly DebugService _debugService;
26+
private readonly DebugStateService _debugStateService;
27+
28+
public SetFunctionBreakpointsHandler(
29+
ILoggerFactory loggerFactory,
30+
DebugService debugService,
31+
DebugStateService debugStateService)
32+
{
33+
_logger = loggerFactory.CreateLogger<SetFunctionBreakpointsHandler>();
34+
_debugService = debugService;
35+
_debugStateService = debugStateService;
36+
}
37+
38+
public async Task<SetFunctionBreakpointsResponse> Handle(SetFunctionBreakpointsArguments request, CancellationToken cancellationToken)
39+
{
40+
CommandBreakpointDetails[] breakpointDetails = request.Breakpoints
41+
.Select((funcBreakpoint) => CommandBreakpointDetails.Create(
42+
funcBreakpoint.Name,
43+
funcBreakpoint.Condition,
44+
funcBreakpoint.HitCondition))
45+
.ToArray();
46+
47+
// If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
48+
CommandBreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
49+
if (!_debugStateService.NoDebug)
50+
{
51+
_debugStateService.SetBreakpointInProgress = true;
52+
53+
try
54+
{
55+
updatedBreakpointDetails =
56+
await _debugService.SetCommandBreakpointsAsync(
57+
breakpointDetails);
58+
}
59+
catch (Exception e)
60+
{
61+
// Log whatever the error is
62+
_logger.LogException($"Caught error while setting command breakpoints", e);
63+
}
64+
finally
65+
{
66+
_debugStateService.SetBreakpointInProgress = false;
67+
}
68+
}
69+
70+
return new SetFunctionBreakpointsResponse
71+
{
72+
Breakpoints = updatedBreakpointDetails
73+
.Select(LspDebugUtils.CreateBreakpoint)
74+
.ToArray()
75+
};
76+
}
77+
}
78+
79+
public class SetExceptionBreakpointsHandler : ISetExceptionBreakpointsHandler
80+
{
81+
private readonly ILogger _logger;
82+
private readonly DebugService _debugService;
83+
private readonly DebugStateService _debugStateService;
84+
85+
public SetExceptionBreakpointsHandler(
86+
ILoggerFactory loggerFactory,
87+
DebugService debugService,
88+
DebugStateService debugStateService)
89+
{
90+
_logger = loggerFactory.CreateLogger<SetFunctionBreakpointsHandler>();
91+
_debugService = debugService;
92+
_debugStateService = debugStateService;
93+
}
94+
95+
public Task<SetExceptionBreakpointsResponse> Handle(SetExceptionBreakpointsArguments request, CancellationToken cancellationToken)
96+
{
97+
// TODO: When support for exception breakpoints (unhandled and/or first chance)
98+
// are added to the PowerShell engine, wire up the VSCode exception
99+
// breakpoints here using the pattern below to prevent bug regressions.
100+
//if (!noDebug)
101+
//{
102+
// setBreakpointInProgress = true;
103+
104+
// try
105+
// {
106+
// // Set exception breakpoints in DebugService
107+
// }
108+
// catch (Exception e)
109+
// {
110+
// // Log whatever the error is
111+
// Logger.WriteException($"Caught error while setting exception breakpoints", e);
112+
// }
113+
// finally
114+
// {
115+
// setBreakpointInProgress = false;
116+
// }
117+
//}
118+
119+
return Task.FromResult(new SetExceptionBreakpointsResponse());
120+
}
121+
}
122+
123+
public class SetBreakpointsHandler : ISetBreakpointsHandler
124+
{
125+
private readonly ILogger _logger;
126+
private readonly DebugService _debugService;
127+
private readonly DebugStateService _debugStateService;
128+
private readonly WorkspaceService _workspaceService;
129+
130+
public SetBreakpointsHandler(
131+
ILoggerFactory loggerFactory,
132+
DebugService debugService,
133+
DebugStateService debugStateService,
134+
WorkspaceService workspaceService)
135+
{
136+
_logger = loggerFactory.CreateLogger<SetFunctionBreakpointsHandler>();
137+
_debugService = debugService;
138+
_debugStateService = debugStateService;
139+
_workspaceService = workspaceService;
140+
}
141+
142+
public async Task<SetBreakpointsResponse> Handle(SetBreakpointsArguments request, CancellationToken cancellationToken)
143+
{
144+
ScriptFile scriptFile = null;
145+
146+
// When you set a breakpoint in the right pane of a Git diff window on a PS1 file,
147+
// the Source.Path comes through as Untitled-X. That's why we check for IsUntitledPath.
148+
if (!ScriptFile.IsUntitledPath(request.Source.Path) &&
149+
!_workspaceService.TryGetFile(
150+
request.Source.Path,
151+
out scriptFile))
152+
{
153+
string message = _debugStateService.NoDebug ? string.Empty : "Source file could not be accessed, breakpoint not set.";
154+
var srcBreakpoints = request.Breakpoints
155+
.Select(srcBkpt => LspDebugUtils.CreateBreakpoint(
156+
srcBkpt, request.Source.Path, message, verified: _debugStateService.NoDebug));
157+
158+
// Return non-verified breakpoint message.
159+
return new SetBreakpointsResponse
160+
{
161+
Breakpoints = new Container<Breakpoint>(srcBreakpoints)
162+
};
163+
}
164+
165+
// Verify source file is a PowerShell script file.
166+
string fileExtension = Path.GetExtension(scriptFile?.FilePath ?? "")?.ToLower();
167+
if (string.IsNullOrEmpty(fileExtension) || ((fileExtension != ".ps1") && (fileExtension != ".psm1")))
168+
{
169+
_logger.LogWarning(
170+
$"Attempted to set breakpoints on a non-PowerShell file: {request.Source.Path}");
171+
172+
string message = _debugStateService.NoDebug ? string.Empty : "Source is not a PowerShell script, breakpoint not set.";
173+
174+
var srcBreakpoints = request.Breakpoints
175+
.Select(srcBkpt => LspDebugUtils.CreateBreakpoint(
176+
srcBkpt, request.Source.Path, message, verified: _debugStateService.NoDebug));
177+
178+
// Return non-verified breakpoint message.
179+
return new SetBreakpointsResponse
180+
{
181+
Breakpoints = new Container<Breakpoint>(srcBreakpoints)
182+
};
183+
}
184+
185+
// At this point, the source file has been verified as a PowerShell script.
186+
BreakpointDetails[] breakpointDetails = request.Breakpoints
187+
.Select((srcBreakpoint) => BreakpointDetails.Create(
188+
scriptFile.FilePath,
189+
(int)srcBreakpoint.Line,
190+
(int?)srcBreakpoint.Column,
191+
srcBreakpoint.Condition,
192+
srcBreakpoint.HitCondition))
193+
.ToArray();
194+
195+
// If this is a "run without debugging (Ctrl+F5)" session ignore requests to set breakpoints.
196+
BreakpointDetails[] updatedBreakpointDetails = breakpointDetails;
197+
if (!_debugStateService.NoDebug)
198+
{
199+
_debugStateService.SetBreakpointInProgress = true;
200+
201+
try
202+
{
203+
updatedBreakpointDetails =
204+
await _debugService.SetLineBreakpointsAsync(
205+
scriptFile,
206+
breakpointDetails);
207+
}
208+
catch (Exception e)
209+
{
210+
// Log whatever the error is
211+
_logger.LogException($"Caught error while setting breakpoints in SetBreakpoints handler for file {scriptFile?.FilePath}", e);
212+
}
213+
finally
214+
{
215+
_debugStateService.SetBreakpointInProgress = false;
216+
}
217+
}
218+
219+
return new SetBreakpointsResponse
220+
{
221+
Breakpoints = new Container<Breakpoint>(updatedBreakpointDetails
222+
.Select(LspDebugUtils.CreateBreakpoint))
223+
};
224+
}
225+
}
226+
}

0 commit comments

Comments
 (0)