refactor creation of debugger process
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages;
|
using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
|
|
||||||
@@ -10,9 +11,9 @@ public class Debugger
|
|||||||
public required SharpIdeProjectModel Project { get; init; }
|
public required SharpIdeProjectModel Project { get; init; }
|
||||||
public required int ProcessId { get; init; }
|
public required int ProcessId { get; init; }
|
||||||
private DebuggingService _debuggingService = new DebuggingService();
|
private DebuggingService _debuggingService = new DebuggingService();
|
||||||
public async Task Attach(string? debuggerExecutablePath, Dictionary<SharpIdeFile, List<Breakpoint>> breakpointsByFile, SharpIdeProjectModel project, CancellationToken cancellationToken)
|
public async Task Attach(DebuggerExecutableInfo? debuggerExecutableInfo, Dictionary<SharpIdeFile, List<Breakpoint>> breakpointsByFile, SharpIdeProjectModel project, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await _debuggingService.Attach(ProcessId, debuggerExecutablePath, breakpointsByFile, project, cancellationToken);
|
await _debuggingService.Attach(ProcessId, debuggerExecutableInfo, breakpointsByFile, project, cancellationToken);
|
||||||
}
|
}
|
||||||
public async Task SetBreakpointsForFile(SharpIdeFile file, List<Breakpoint> breakpoints, CancellationToken cancellationToken = default) => await _debuggingService.SetBreakpointsForFile(file, breakpoints, cancellationToken);
|
public async Task SetBreakpointsForFile(SharpIdeFile file, List<Breakpoint> breakpoints, CancellationToken cancellationToken = default) => await _debuggingService.SetBreakpointsForFile(file, breakpoints, cancellationToken);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using Ardalis.GuardClauses;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
|
|
||||||
|
namespace SharpIDE.Application.Features.Debugging;
|
||||||
|
|
||||||
|
public static class DebuggerProcessStreamHelper
|
||||||
|
{
|
||||||
|
public static (Stream Input, Stream Output, bool IsNetCoreDbg) NewDebuggerProcessStreamsForInfo(DebuggerExecutableInfo? debuggerExecutableInfoNullable)
|
||||||
|
{
|
||||||
|
if (debuggerExecutableInfoNullable is not {} debuggerExecutableInfo) throw new ArgumentNullException(nameof(debuggerExecutableInfoNullable), "Debugger executable info cannot be null.");
|
||||||
|
var debuggerExecutablePath = debuggerExecutableInfo.DebuggerExecutablePath;
|
||||||
|
Guard.Against.NullOrWhiteSpace(debuggerExecutablePath, nameof(debuggerExecutablePath), "Debugger executable path cannot be null or empty.");
|
||||||
|
var isNetCoreDbg = Path.GetFileNameWithoutExtension(debuggerExecutablePath).Equals("netcoredbg", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
var process = new Process
|
||||||
|
{
|
||||||
|
StartInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
//FileName = @"C:\Users\Matthew\Downloads\netcoredbg-win64\netcoredbg\netcoredbg.exe",
|
||||||
|
FileName = debuggerExecutablePath,
|
||||||
|
Arguments = "--interpreter=vscode",
|
||||||
|
RedirectStandardInput = true,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
process.Start();
|
||||||
|
return (process.StandardInput.BaseStream, process.StandardOutput.BaseStream, isNetCoreDbg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ using Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.Messages;
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using SharpIDE.Application.Features.Debugging.Signing;
|
using SharpIDE.Application.Features.Debugging.Signing;
|
||||||
using SharpIDE.Application.Features.Events;
|
using SharpIDE.Application.Features.Events;
|
||||||
|
using SharpIDE.Application.Features.Run;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
|
|
||||||
@@ -16,33 +17,14 @@ namespace SharpIDE.Application.Features.Debugging;
|
|||||||
public class DebuggingService
|
public class DebuggingService
|
||||||
{
|
{
|
||||||
private DebugProtocolHost _debugProtocolHost = null!;
|
private DebugProtocolHost _debugProtocolHost = null!;
|
||||||
public async Task Attach(int debuggeeProcessId, string? debuggerExecutablePath, Dictionary<SharpIdeFile, List<Breakpoint>> breakpointsByFile, SharpIdeProjectModel project, CancellationToken cancellationToken = default)
|
public async Task Attach(int debuggeeProcessId, DebuggerExecutableInfo? debuggerExecutableInfo, Dictionary<SharpIdeFile, List<Breakpoint>> breakpointsByFile, SharpIdeProjectModel project, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Guard.Against.NegativeOrZero(debuggeeProcessId, nameof(debuggeeProcessId), "Process ID must be a positive integer.");
|
Guard.Against.NegativeOrZero(debuggeeProcessId, nameof(debuggeeProcessId), "Process ID must be a positive integer.");
|
||||||
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
|
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(debuggerExecutablePath))
|
var (inputStream, outputStream, isNetCoreDbg) = DebuggerProcessStreamHelper.NewDebuggerProcessStreamsForInfo(debuggerExecutableInfo);
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(debuggerExecutablePath), "Debugger executable path cannot be null or empty.");
|
|
||||||
}
|
|
||||||
var isNetCoreDbg = Path.GetFileNameWithoutExtension(debuggerExecutablePath).Equals("netcoredbg", StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
var process = new Process
|
var debugProtocolHost = new DebugProtocolHost(inputStream, outputStream, false);
|
||||||
{
|
|
||||||
StartInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
//FileName = @"C:\Users\Matthew\Downloads\netcoredbg-win64\netcoredbg\netcoredbg.exe",
|
|
||||||
FileName = debuggerExecutablePath,
|
|
||||||
Arguments = "--interpreter=vscode",
|
|
||||||
RedirectStandardInput = true,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
process.Start();
|
|
||||||
|
|
||||||
var debugProtocolHost = new DebugProtocolHost(process.StandardInput.BaseStream, process.StandardOutput.BaseStream, false);
|
|
||||||
var initializedEventTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
var initializedEventTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
_debugProtocolHost = debugProtocolHost;
|
_debugProtocolHost = debugProtocolHost;
|
||||||
debugProtocolHost.LogMessage += (sender, args) =>
|
debugProtocolHost.LogMessage += (sender, args) =>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace SharpIDE.Application.Features.Run;
|
||||||
|
|
||||||
|
public readonly record struct DebuggerExecutableInfo
|
||||||
|
{
|
||||||
|
public required bool UseInMemorySharpDbg { get; init; }
|
||||||
|
public required string? DebuggerExecutablePath { get; init; }
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ public partial class RunService(ILogger<RunService> logger, RoslynAnalysis rosly
|
|||||||
private readonly ILogger<RunService> _logger = logger;
|
private readonly ILogger<RunService> _logger = logger;
|
||||||
private readonly RoslynAnalysis _roslynAnalysis = roslynAnalysis;
|
private readonly RoslynAnalysis _roslynAnalysis = roslynAnalysis;
|
||||||
|
|
||||||
public async Task RunProject(SharpIdeProjectModel project, bool isDebug = false, string? debuggerExecutablePath = null)
|
public async Task RunProject(SharpIdeProjectModel project, bool isDebug = false, DebuggerExecutableInfo? debuggerExecutableInfo = null)
|
||||||
{
|
{
|
||||||
Guard.Against.Null(project, nameof(project));
|
Guard.Against.Null(project, nameof(project));
|
||||||
Guard.Against.NullOrWhiteSpace(project.FilePath, nameof(project.FilePath), "Project file path cannot be null or empty.");
|
Guard.Against.NullOrWhiteSpace(project.FilePath, nameof(project.FilePath), "Project file path cannot be null or empty.");
|
||||||
@@ -93,7 +93,7 @@ public partial class RunService(ILogger<RunService> logger, RoslynAnalysis rosly
|
|||||||
// Attach debugger (which internally uses a DiagnosticClient to resume startup)
|
// Attach debugger (which internally uses a DiagnosticClient to resume startup)
|
||||||
var debugger = new Debugger { Project = project, ProcessId = process.ProcessId };
|
var debugger = new Debugger { Project = project, ProcessId = process.ProcessId };
|
||||||
_debugger = debugger;
|
_debugger = debugger;
|
||||||
await debugger.Attach(debuggerExecutablePath, Breakpoints.ToDictionary(), project, project.RunningCancellationTokenSource.Token).ConfigureAwait(false);
|
await debugger.Attach(debuggerExecutableInfo, Breakpoints.ToDictionary(), project, project.RunningCancellationTokenSource.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
project.Running = true;
|
project.Running = true;
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ public partial class RunMenuItem : HBoxContainer
|
|||||||
private async void OnDebugButtonPressed()
|
private async void OnDebugButtonPressed()
|
||||||
{
|
{
|
||||||
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Debug);
|
GodotGlobalEvents.Instance.BottomPanelTabExternallySelected.InvokeParallelFireAndForget(BottomPanelType.Debug);
|
||||||
await _runService.RunProject(Project, true, Singletons.AppState.IdeSettings.DebuggerExecutablePath).ConfigureAwait(false);
|
var debuggerExecutableInfo = new DebuggerExecutableInfo
|
||||||
|
{
|
||||||
|
UseInMemorySharpDbg = false,
|
||||||
|
DebuggerExecutablePath = Singletons.AppState.IdeSettings.DebuggerExecutablePath
|
||||||
|
};
|
||||||
|
await _runService.RunProject(Project, true, debuggerExecutableInfo).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user