From 678066da2387df40496b3f66ca476e92a718171b Mon Sep 17 00:00:00 2001 From: glopesdev Date: Mon, 2 Nov 2026 22:30:35 +0000 Subject: [PATCH] Exit with an error code when code generation fails Generate commands now exit with code 1 when code generation reports errors, with the errors printed by the same handler as every other error. The verify command prints the device metadata path only after the file has loaded. --- .../Generate/GenerateATxmegaFirmwareCommand.cs | 10 ++++------ .../Generate/GenerateCSharpInterfaceCommand.cs | 4 ++-- .../Generate/GeneratePythonInterfaceCommand.cs | 4 ++-- src/Harp.Toolkit/Generate/GeneratorHelper.cs | 16 +++++++++++----- .../Verify/GeneratedInterfaceCompiler.cs | 3 +-- src/Harp.Toolkit/Verify/VerifyCommand.cs | 3 +-- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/Harp.Toolkit/Generate/GenerateATxmegaFirmwareCommand.cs b/src/Harp.Toolkit/Generate/GenerateATxmegaFirmwareCommand.cs index 5cb4120..8f7247c 100644 --- a/src/Harp.Toolkit/Generate/GenerateATxmegaFirmwareCommand.cs +++ b/src/Harp.Toolkit/Generate/GenerateATxmegaFirmwareCommand.cs @@ -32,12 +32,10 @@ public GenerateATxmegaFirmwareCommand() var generator = new FirmwareGenerator(deviceMetadata, portPinMetadata); var headers = generator.GenerateHeaders(); var implementation = generateImplementation ? generator.GenerateImplementation() : default; - if (GeneratorHelper.AssertNoGeneratorErrors(generator.Errors)) - { - GenerateCommand.WriteFileContents(outputPath.FullName, headers); - if (generateImplementation) - GenerateCommand.WriteFileContents(outputPath.FullName, implementation); - } + GeneratorHelper.AssertNoGeneratorErrors(generator.Errors); + GenerateCommand.WriteFileContents(outputPath.FullName, headers); + if (generateImplementation) + GenerateCommand.WriteFileContents(outputPath.FullName, implementation); }); } } diff --git a/src/Harp.Toolkit/Generate/GenerateCSharpInterfaceCommand.cs b/src/Harp.Toolkit/Generate/GenerateCSharpInterfaceCommand.cs index c7f214f..300f54f 100644 --- a/src/Harp.Toolkit/Generate/GenerateCSharpInterfaceCommand.cs +++ b/src/Harp.Toolkit/Generate/GenerateCSharpInterfaceCommand.cs @@ -23,8 +23,8 @@ public GenerateCSharpInterfaceCommand() var deviceMetadata = metadataPathArgument.Load(parseResult); var generator = new InterfaceGenerator(deviceMetadata, namespaceOption.GetValue(parseResult, deviceMetadata)); var implementation = generator.GenerateImplementation(); - if (GeneratorHelper.AssertNoGeneratorErrors(generator.Errors)) - GenerateCommand.WriteFileContents(outputPath.FullName, implementation); + GeneratorHelper.AssertNoGeneratorErrors(generator.Errors); + GenerateCommand.WriteFileContents(outputPath.FullName, implementation); }); } } diff --git a/src/Harp.Toolkit/Generate/GeneratePythonInterfaceCommand.cs b/src/Harp.Toolkit/Generate/GeneratePythonInterfaceCommand.cs index 81074c0..05fba47 100644 --- a/src/Harp.Toolkit/Generate/GeneratePythonInterfaceCommand.cs +++ b/src/Harp.Toolkit/Generate/GeneratePythonInterfaceCommand.cs @@ -28,8 +28,8 @@ public GeneratePythonInterfaceCommand() var deviceMetadata = metadataPathArgument.Load(parseResult); var generator = new PythonGenerator(deviceMetadata, package); var implementation = generator.GenerateImplementation(); - if (GeneratorHelper.AssertNoGeneratorErrors(generator.Errors)) - GenerateCommand.WriteFileContents(outputPath.FullName, implementation); + GeneratorHelper.AssertNoGeneratorErrors(generator.Errors); + GenerateCommand.WriteFileContents(outputPath.FullName, implementation); }); } } diff --git a/src/Harp.Toolkit/Generate/GeneratorHelper.cs b/src/Harp.Toolkit/Generate/GeneratorHelper.cs index fb73563..11165f8 100644 --- a/src/Harp.Toolkit/Generate/GeneratorHelper.cs +++ b/src/Harp.Toolkit/Generate/GeneratorHelper.cs @@ -5,7 +5,7 @@ namespace Harp.Toolkit.Generate; public static class GeneratorHelper { - public static bool AssertNoGeneratorErrors(CompilerErrorCollection errors) + public static void AssertNoGeneratorErrors(CompilerErrorCollection errors) { if (errors.Count > 0) { @@ -16,10 +16,16 @@ public static bool AssertNoGeneratorErrors(CompilerErrorCollection errors) var warningString = error.IsWarning ? "warning" : "error"; errorLog.AppendLine($"{error.FileName}: {warningString}: {error.ErrorText}"); } - Console.Error.WriteLine(errorLog.ToString()); - return !errors.HasErrors; - } - return true; + var message = errorLog.ToString(); + if (errors.HasErrors) + { + var exception = new InvalidOperationException(message); + exception.SetDescription(message); + throw exception; + } + + Console.Error.WriteLine(message); + } } } diff --git a/src/Harp.Toolkit/Verify/GeneratedInterfaceCompiler.cs b/src/Harp.Toolkit/Verify/GeneratedInterfaceCompiler.cs index a2239b0..b615b80 100644 --- a/src/Harp.Toolkit/Verify/GeneratedInterfaceCompiler.cs +++ b/src/Harp.Toolkit/Verify/GeneratedInterfaceCompiler.cs @@ -19,8 +19,7 @@ public static IReadOnlyDictionary Compile(DeviceMetadata deviceOnlyMe { var generator = new InterfaceGenerator(deviceOnlyMetadata, @namespace); var implementation = generator.GenerateImplementation(); - if (!GeneratorHelper.AssertNoGeneratorErrors(generator.Errors)) - throw new InvalidOperationException("Interface generation from device.yml completed with errors."); + GeneratorHelper.AssertNoGeneratorErrors(generator.Errors); var syntaxTree = CSharpSyntaxTree.ParseText(implementation.Device); var compilation = CSharpCompilation.Create( diff --git a/src/Harp.Toolkit/Verify/VerifyCommand.cs b/src/Harp.Toolkit/Verify/VerifyCommand.cs index 5f14086..b450652 100644 --- a/src/Harp.Toolkit/Verify/VerifyCommand.cs +++ b/src/Harp.Toolkit/Verify/VerifyCommand.cs @@ -86,10 +86,9 @@ static async Task RunVerification(string portName, FileInfo? reportFile, bo string? deviceRawYaml = null; if (metadataPath is not null) { - AnsiConsole.Markup($"Loading device metadata from [bold]{metadataPath.FullName}[/]..."); deviceRawYaml = await File.ReadAllTextAsync(metadataPath.FullName, cancellationToken); deviceMetadata = MetadataPathOption.Parse(metadataPath, deviceRawYaml); - AnsiConsole.MarkupLine($" [green]Done![/] ({deviceMetadata.Registers.Count} registers)"); + AnsiConsole.MarkupLine($"Loaded device metadata from [bold]{metadataPath.FullName}[/] ({deviceMetadata.Registers.Count} registers)."); } using var connection = await VerifyConnection.OpenAsync(portName, cancellationToken);