From 56784ecfd36ec7c3c84af984c1494a1c8e81291a Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Sun, 18 Jan 2026 17:00:47 +1000 Subject: [PATCH] do not run project on failed build --- .../Features/Build/BuildService.cs | 11 +++++++++- .../Features/Run/RunService.cs | 20 +++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/SharpIDE.Application/Features/Build/BuildService.cs b/src/SharpIDE.Application/Features/Build/BuildService.cs index 5099ed9..1002b09 100644 --- a/src/SharpIDE.Application/Features/Build/BuildService.cs +++ b/src/SharpIDE.Application/Features/Build/BuildService.cs @@ -17,6 +17,8 @@ public enum BuildType Restore } public enum BuildStartedFlags { UserFacing = 0, Internal } +public enum SharpIdeBuildResult { Success = 0, Failure } + public class BuildService(ILogger logger) { private readonly ILogger _logger = logger; @@ -25,7 +27,7 @@ public class BuildService(ILogger logger) public EventWrapper BuildFinished { get; } = new(() => Task.CompletedTask); public ChannelTextWriter BuildTextWriter { get; } = new ChannelTextWriter(); private CancellationTokenSource? _cancellationTokenSource; - public async Task MsBuildAsync(string solutionOrProjectFilePath, BuildType buildType = BuildType.Build, BuildStartedFlags buildStartedFlags = BuildStartedFlags.UserFacing, CancellationToken cancellationToken = default) + public async Task MsBuildAsync(string solutionOrProjectFilePath, BuildType buildType = BuildType.Build, BuildStartedFlags buildStartedFlags = BuildStartedFlags.UserFacing, CancellationToken cancellationToken = default) { if (_cancellationTokenSource is not null) throw new InvalidOperationException("A build is already in progress."); _cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); @@ -63,6 +65,13 @@ public class BuildService(ILogger logger) BuildFinished.InvokeParallelFireAndForget(); _cancellationTokenSource = null; _logger.LogInformation(buildResult.Exception, "Build result: {BuildResult} in {ElapsedMilliseconds}ms", buildResult.OverallResult, timer.ElapsedMilliseconds); + var mappedResult = buildResult.OverallResult switch + { + BuildResultCode.Success => SharpIdeBuildResult.Success, + BuildResultCode.Failure => SharpIdeBuildResult.Failure, + _ => throw new ArgumentOutOfRangeException() + }; + return mappedResult; } public async Task CancelBuildAsync() diff --git a/src/SharpIDE.Application/Features/Run/RunService.cs b/src/SharpIDE.Application/Features/Run/RunService.cs index ee71f39..c148279 100644 --- a/src/SharpIDE.Application/Features/Run/RunService.cs +++ b/src/SharpIDE.Application/Features/Run/RunService.cs @@ -33,15 +33,23 @@ public partial class RunService(ILogger logger, RoslynAnalysis rosly var semaphoreSlim = _projectLocks.GetOrAdd(project, new SemaphoreSlim(1, 1)); var waitResult = await semaphoreSlim.WaitAsync(0).ConfigureAwait(false); if (waitResult is false) throw new InvalidOperationException($"Project {project.Name} is already running."); - if (project.RunningCancellationTokenSource is not null) throw new InvalidOperationException($"Project {project.Name} is already running with a cancellation token source."); - project.RunningCancellationTokenSource = new CancellationTokenSource(); - await _buildService.MsBuildAsync(project.FilePath); - - var launchProfiles = await LaunchSettingsParser.GetLaunchSettingsProfiles(project); - var launchProfile = launchProfiles.FirstOrDefault(); try { + if (project.RunningCancellationTokenSource is not null) throw new InvalidOperationException($"Project {project.Name} is already running with a cancellation token source."); + + var buildResult = await _buildService.MsBuildAsync(project.FilePath); + if (buildResult is not SharpIdeBuildResult.Success) + { + _logger.LogInformation("Build failed for project {ProjectName}. Aborting run/debug.", project.Name); + return; + } + + project.RunningCancellationTokenSource = new CancellationTokenSource(); + + var launchProfiles = await LaunchSettingsParser.GetLaunchSettingsProfiles(project); + var launchProfile = launchProfiles.FirstOrDefault(); + var fileName = launchProfile?.CommandName switch { "Executable" => launchProfile.ExecutablePath,