diff --git a/src/SharpIDE.Application/Features/Debugging/Debugger.cs b/src/SharpIDE.Application/Features/Debugging/Debugger.cs index 291c2a7..c33a8d7 100644 --- a/src/SharpIDE.Application/Features/Debugging/Debugger.cs +++ b/src/SharpIDE.Application/Features/Debugging/Debugger.cs @@ -16,6 +16,9 @@ public class Debugger } public async Task StepOver(int threadId, CancellationToken cancellationToken = default) => await _debuggingService.StepOver(threadId, cancellationToken); + public async Task StepInto(int threadId, CancellationToken cancellationToken = default) => await _debuggingService.StepInto(threadId, cancellationToken); + public async Task StepOut(int threadId, CancellationToken cancellationToken = default) => await _debuggingService.StepOut(threadId, cancellationToken); + public async Task Continue(int threadId, CancellationToken cancellationToken = default) => await _debuggingService.Continue(threadId, cancellationToken); public async Task> GetThreadsAtStopPoint() => await _debuggingService.GetThreadsAtStopPoint(); public async Task> GetStackFramesForThread(int threadId) => await _debuggingService.GetStackFramesForThread(threadId); public async Task> GetVariablesForStackFrame(int frameId) => await _debuggingService.GetVariablesForStackFrame(frameId); diff --git a/src/SharpIDE.Application/Features/Debugging/DebuggingService.cs b/src/SharpIDE.Application/Features/Debugging/DebuggingService.cs index 1dea5b9..05a413c 100644 --- a/src/SharpIDE.Application/Features/Debugging/DebuggingService.cs +++ b/src/SharpIDE.Application/Features/Debugging/DebuggingService.cs @@ -162,6 +162,24 @@ public class DebuggingService var nextRequest = new NextRequest(threadId); _debugProtocolHost.SendRequestSync(nextRequest); } + public async Task StepInto(int threadId, CancellationToken cancellationToken) + { + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + var stepInRequest = new StepInRequest(threadId); + _debugProtocolHost.SendRequestSync(stepInRequest); + } + public async Task StepOut(int threadId, CancellationToken cancellationToken) + { + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + var stepOutRequest = new StepOutRequest(threadId); + _debugProtocolHost.SendRequestSync(stepOutRequest); + } + public async Task Continue(int threadId, CancellationToken cancellationToken) + { + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + var continueRequest = new ContinueRequest(threadId); + _debugProtocolHost.SendRequestSync(continueRequest); + } public async Task> GetThreadsAtStopPoint() { diff --git a/src/SharpIDE.Application/Features/Run/RunService.cs b/src/SharpIDE.Application/Features/Run/RunService.cs index eae125b..410f9cb 100644 --- a/src/SharpIDE.Application/Features/Run/RunService.cs +++ b/src/SharpIDE.Application/Features/Run/RunService.cs @@ -150,10 +150,10 @@ public class RunService(ILogger logger, RoslynAnalysis roslynAnalysi await project.RunningCancellationTokenSource.CancelAsync().ConfigureAwait(false); } - public async Task SendDebuggerStepOver(int threadId) - { - await _debugger!.StepOver(threadId); - } + public async Task SendDebuggerStepOver(int threadId) => await _debugger!.StepOver(threadId); + public async Task SendDebuggerStepInto(int threadId) => await _debugger!.StepInto(threadId); + public async Task SendDebuggerStepOut(int threadId) => await _debugger!.StepOut(threadId); + public async Task SendDebuggerContinue(int threadId) => await _debugger!.Continue(threadId); public async Task> GetThreadsAtStopPoint() { diff --git a/src/SharpIDE.Godot/Features/CodeEditor/CodeEditorPanel.cs b/src/SharpIDE.Godot/Features/CodeEditor/CodeEditorPanel.cs index ed98ed4..59bbd6a 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/CodeEditorPanel.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/CodeEditorPanel.cs @@ -52,7 +52,19 @@ public partial class CodeEditorPanel : MarginContainer { if (@event.IsActionPressed(InputStringNames.StepOver)) { - SendDebuggerStepOver(); + SendDebuggerStepCommand(DebuggerStepAction.StepOver); + } + else if (@event.IsActionPressed(InputStringNames.DebuggerStepOut)) + { + SendDebuggerStepCommand(DebuggerStepAction.StepOut); + } + else if (@event.IsActionPressed(InputStringNames.DebuggerStepIn)) + { + SendDebuggerStepCommand(DebuggerStepAction.StepIn); + } + else if (@event.IsActionPressed(InputStringNames.DebuggerContinue)) + { + SendDebuggerStepCommand(DebuggerStepAction.Continue); } } @@ -142,7 +154,8 @@ public partial class CodeEditorPanel : MarginContainer }); } - private void SendDebuggerStepOver() + private enum DebuggerStepAction { StepOver, StepIn, StepOut, Continue } + private void SendDebuggerStepCommand(DebuggerStepAction debuggerStepAction) { if (_debuggerExecutionStopInfo is null) return; // ie not currently stopped var godotLine = _debuggerExecutionStopInfo.Line - 1; @@ -153,7 +166,15 @@ public partial class CodeEditorPanel : MarginContainer _debuggerExecutionStopInfo = null; _ = Task.GodotRun(async () => { - await _runService.SendDebuggerStepOver(threadId); + var task = debuggerStepAction switch + { + DebuggerStepAction.StepOver => _runService.SendDebuggerStepOver(threadId), + DebuggerStepAction.StepIn => _runService.SendDebuggerStepInto(threadId), + DebuggerStepAction.StepOut => _runService.SendDebuggerStepOut(threadId), + DebuggerStepAction.Continue => _runService.SendDebuggerContinue(threadId), + _ => throw new ArgumentOutOfRangeException(nameof(debuggerStepAction), debuggerStepAction, null) + }; + await task; }); } } diff --git a/src/SharpIDE.Godot/InputStringNames.cs b/src/SharpIDE.Godot/InputStringNames.cs index 7907e5f..1693453 100644 --- a/src/SharpIDE.Godot/InputStringNames.cs +++ b/src/SharpIDE.Godot/InputStringNames.cs @@ -7,6 +7,9 @@ public static class InputStringNames public static readonly StringName RenameSymbol = nameof(RenameSymbol); public static readonly StringName CodeFixes = nameof(CodeFixes); public static readonly StringName StepOver = nameof(StepOver); + public static readonly StringName DebuggerStepIn = nameof(DebuggerStepIn); + public static readonly StringName DebuggerStepOut = nameof(DebuggerStepOut); + public static readonly StringName DebuggerContinue = nameof(DebuggerContinue); public static readonly StringName FindInFiles = nameof(FindInFiles); public static readonly StringName FindFiles = nameof(FindFiles); public static readonly StringName SaveFile = nameof(SaveFile); diff --git a/src/SharpIDE.Godot/project.godot b/src/SharpIDE.Godot/project.godot index 968c8d5..5379150 100644 --- a/src/SharpIDE.Godot/project.godot +++ b/src/SharpIDE.Godot/project.godot @@ -73,6 +73,21 @@ RenameSymbol={ "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) ] } +DebuggerContinue={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194336,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +DebuggerStepIn={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194342,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +DebuggerStepOut={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194342,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} [rendering]