Skip to content

Decouple CLI binary dependency from MSBuild task#1154

Merged
christianhelle merged 11 commits into
mainfrom
msbuild-cli-decouple
Jun 16, 2026
Merged

Decouple CLI binary dependency from MSBuild task#1154
christianhelle merged 11 commits into
mainfrom
msbuild-cli-decouple

Conversation

@christianhelle

@christianhelle christianhelle commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

Summary by CodeRabbit

  • Refactor
    • Updated MSBuild generation to run in-process via Core logic (no external subprocess execution).
    • Consolidated output planning and OpenAPI validation into the Core library to keep behavior consistent across CLI and MSBuild.
  • New Features
    • MSBuild NuGet packaging now includes the required task/runtime dependencies more reliably for task execution.
  • Documentation
    • Added a PRD describing how MSBuild is decoupled from the CLI.
  • Chores
    • Adjusted CI and test/build scripts to match the new build and generation flow.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR decouples Refitter.MSBuild from the CLI binary by moving OutputPlanner and OpenAPI validation types into Refitter.Core. RefitterGenerateTask is rewritten to invoke Core APIs in-process, removing all subprocess orchestration infrastructure. CI scripts and CLI call sites are updated accordingly.

Changes

MSBuild In-Process Decoupling

Layer / File(s) Summary
PRD and architecture documentation
docs/prd/decouple-msbuild-from-cli.md, AGENTS.md
New PRD document covering the decoupling decision, phases, packaging strategy with SuppressDependenciesWhenPacking, behavioral notes, and before/after architecture diagrams. AGENTS.md package boundary table updated to show Refitter.MSBuild now references Refitter.Core directly instead of requiring pre-built CLI binaries.
Validation types renamespaced into Refitter.Core.Validation
src/Refitter.Core/Validation/OpenApiStats.cs, src/Refitter.Core/Validation/OpenApiValidationException.cs, src/Refitter.Core/Validation/OpenApiValidationResult.cs, src/Refitter.Core/Validation/OpenApiValidator.cs
Namespace declarations changed from Refitter.Validation to Refitter.Core.Validation across all four validation types. ExcludeFromCodeCoverage justification argument removed from OpenApiValidationResult.
OutputPlanner and ApplyDefaults added to Refitter.Core
src/Refitter.Core/OutputPlanner.cs, src/Refitter.Core/RefitterSettingsLoader.cs
PlannedFile record and OutputPlanner public static class added to Refitter.Core with single-file/multi-file path planning methods accepting settingsFilePath and cliOutputPath directly. RefitterSettingsLoader.ApplyDefaults added as a public method to set defaults for GenerateMultipleFiles, OutputFolder, and OutputFilename.
Subprocess infrastructure removed; MSBuild.csproj updated
src/Refitter.MSBuild/IProcessRunner.cs, src/Refitter.MSBuild/IRuntimeResolver.cs, src/Refitter.MSBuild/DefaultProcessRunner.cs, src/Refitter.MSBuild/DefaultRuntimeResolver.cs, src/Refitter.MSBuild/ProcessExecutionResult.cs, src/Refitter.MSBuild/Refitter.MSBuild.csproj
Five files containing process/runtime abstractions are deleted. .csproj adds SuppressDependenciesWhenPacking=true, CopyLocalLockFileAssemblies, replaces CLI binary file globs with a ProjectReference to Refitter.Core, and adds an IncludeTransitiveDepsInPackage target to package built assemblies.
RefitterGenerateTask rewritten to use Core APIs in-process
src/Refitter.MSBuild/RefitterGenerateTask.cs
Execute() loop now calls ProcessRefitterFile() per .refitter file, which loads settings, applies defaults, invokes RefitGenerator, writes output via OutputPlanner, and optionally validates with OpenApiValidator. All subprocess configuration properties and CLI marker parsing helpers are removed.
CLI GenerateCommand, GenerationOrchestrator, and reporters updated
src/Refitter/GenerateCommand.cs, src/Refitter/GenerationOrchestrator.cs, src/Refitter/SettingsValidator.cs, src/Refitter/IGenerationReporter.cs, src/Refitter/RichGenerationReporter.cs, src/Refitter/SimpleGenerationReporter.cs
GenerateCommand delegates defaults to RefitterSettingsLoader.ApplyDefaults and passes explicit fields to OutputPlanner. GenerationOrchestrator updates OutputPlanner and OpenApiValidator call sites to use Core APIs. Reporters and interfaces update namespace imports from Refitter.Validation to Refitter.Core.Validation.
Validation test imports updated
src/Refitter.Tests/OpenApi/OpenApiStatsTests.cs, src/Refitter.Tests/OpenApi/OpenApiValidationExceptionTests.cs, src/Refitter.Tests/OpenApi/OpenApiValidationResultTests.cs, src/Refitter.Tests/OpenApi/OpenApiValidatorTests.cs, src/Refitter.Tests/GenerationOrchestratorTests.cs, src/Refitter.Tests/RichGenerationReporterTests.cs, src/Refitter.Tests/SimpleGenerationReporterTests.cs
All validation-related test files update namespace imports from Refitter.Validation to Refitter.Core.Validation to reference the moved types.
GenerateCommandTests and OutputPlannerTests refactored
src/Refitter.Tests/GenerateCommandTests.cs, src/Refitter.Tests/OutputPlannerTests.cs, src/Refitter.Tests/Scenarios/SettingsFileOutputPathTests.cs
Marker formatting test removed. Reflection-based private method invocations replaced with direct RefitterSettingsLoader.ApplyDefaults and ResolveRelativeSpecPaths calls. OutputPlannerTests comprehensively refactored to use new settingsFilePath/cliOutputPath overloads across single-file, multi-file, and contract-path scenarios with expanded edge-case coverage.
RefitterSettingsLoaderTests extended
src/Refitter.Tests/SettingsFile/RefitterSettingsLoaderTests.cs
New test cases verify ApplyDefaults behavior for GenerateMultipleFiles, OutputFolder, and OutputFilename derivation from settings file path. Additional tests confirm ResolveRelativeSpecPaths handles null/empty inputs correctly.
RefitterGenerateTaskTests refactored with Execute-level integration tests
src/Refitter.Tests/MSBuild/RefitterGenerateTaskTests.cs
Unit tests covering subprocess/marker parsing are removed. Four new integration tests added: Execute_Should_Skip_Validation_When_SkipValidation_Is_True, Execute_Should_Generate_Multiple_Files, Execute_Should_Apply_SettingsFileDefaults, and Execute_Should_Respect_ContractsOutputFolder. Delegating test stubs removed; reflection helper refactored.
CI workflow and build scripts updated
.github/workflows/msbuild.yml, test/MSBuild/build.ps1, test/MSBuild/build.sh
dotnet build step for Refitter.csproj removed; scripts proceed directly from dotnet clean to building Refitter.MSBuild.csproj and packing the NuGet task.
Configuration and ignore patterns
.gitignore
Added ignore patterns for test/MSBuild/nupkg-*/ and src/Refitter.MSBuild/nupkg-check/. Broadened generated-file ignore pattern to cover all test/MSBuild/Generated/**/*.cs files.
sequenceDiagram
  rect rgba(173, 216, 230, 0.5)
    note over RefitterGenerateTask,OpenApiValidator: New in-process flow
  end
  participant RefitterGenerateTask
  participant RefitterSettingsLoader
  participant RefitGenerator
  participant OutputPlanner
  participant OpenApiValidator

  RefitterGenerateTask->>RefitterSettingsLoader: LoadSettings(refitterFilePath)
  RefitterSettingsLoader-->>RefitterGenerateTask: RefitGeneratorSettings
  RefitterGenerateTask->>RefitterSettingsLoader: ApplyDefaults(settingsFilePath, settings)
  RefitterGenerateTask->>RefitGenerator: CreateAsync(settings)
  RefitGenerator-->>RefitterGenerateTask: generator
  RefitterGenerateTask->>RefitGenerator: GenerateAsync() / GenerateMultipleAsync()
  RefitGenerator-->>RefitterGenerateTask: code / GeneratorOutput
  RefitterGenerateTask->>OutputPlanner: PlanSingleFile / PlanMultipleFiles
  OutputPlanner-->>RefitterGenerateTask: PlannedFile[]
  RefitterGenerateTask->>RefitterGenerateTask: File.WriteAllText(plannedPath, content)
  RefitterGenerateTask->>OpenApiValidator: Validate(openApiPath)
  OpenApiValidator-->>RefitterGenerateTask: OpenApiValidationResult
  RefitterGenerateTask-->>RefitterGenerateTask: ITaskItem[] GeneratedFiles
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • christianhelle/refitter#1129: Directly precedes this PR — introduced the process/runtime abstractions (IProcessRunner, IRuntimeResolver, DefaultProcessRunner, DefaultRuntimeResolver, ProcessExecutionResult) that this PR removes from Refitter.MSBuild.
  • christianhelle/refitter#1128: Modifies GenerationOrchestrator.cs orchestration logic that this PR further updates to use the new Refitter.Core.Validation and refactored OutputPlanner APIs.
  • christianhelle/refitter#1095: Refactors GenerateCommand to delegate settings resolution to RefitterSettingsLoader and output planning to OutputPlanner, directly related to the same call-site changes in this PR.

🐇 No more subprocess hops, no more CLI to spawn,
The MSBuild task calls Core—no markers to parse on!
OutputPlanner lives in Core, ApplyDefaults too,
The package shrinks, the scripts are lean,
And in-process paths shine through! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the primary objective of the changeset: decoupling the MSBuild task from its dependency on the CLI binary by moving orchestration logic into Refitter.Core.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch msbuild-cli-decouple

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/Refitter.MSBuild/Refitter.MSBuild.csproj (1)

13-27: ⚠️ Potential issue | 🔴 Critical

Add TreatWarningsAsErrors to the PropertyGroup.

Per coding guidelines, production projects in src/**/*.csproj must enable TreatWarningsAsErrors. This is already set in Refitter.Core.csproj but missing from this file. Add the following line to the <PropertyGroup> section:

<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.MSBuild/Refitter.MSBuild.csproj` around lines 13 - 27, The
PropertyGroup in the Refitter.MSBuild.csproj file is missing the
TreatWarningsAsErrors setting that is required per coding guidelines and already
present in Refitter.Core.csproj. Add a new line containing
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> to the PropertyGroup
section, placing it alongside the existing SuppressDependenciesWhenPacking
setting to ensure the project treats all build warnings as errors.
src/Refitter.Tests/MSBuild/RefitterGenerateTaskTests.cs (1)

232-262: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Test name and logic are inconsistent.

The test is named Execute_Should_Skip_Validation_When_SkipValidation_Is_True, suggesting it should verify that OpenAPI validation is skipped and generation succeeds. However, the test writes unparseable JSON ("not-valid-json" at line 239) and expects Execute() to return false (line 256).

This doesn't test whether validation is skipped; it tests that unparseable input causes failure regardless of the SkipValidation setting. The RefitGenerator will fail to parse the invalid JSON before OpenAPI validation even runs.

To properly test validation skipping, the test should:

  1. Write valid JSON representing an OpenAPI document that would fail OpenAPI schema validation (e.g., missing required OpenAPI fields but still parseable as JSON).
  2. Set SkipValidation = true.
  3. Expect Execute() to return true because validation is skipped and the document is parseable.

Alternatively, rename the test to reflect what it actually tests, such as Execute_Should_Fail_On_Unparseable_OpenAPI_Even_When_SkipValidation_Is_True.

🔧 Option 1: Fix the test logic to actually test validation skipping
     [Test]
     public void Execute_Should_Skip_Validation_When_SkipValidation_Is_True()
     {
         var workspace = CreateWorkspace();
 
         try
         {
             var openApiPath = Path.Combine(workspace, "petstore.json");
-            File.WriteAllText(openApiPath, "not-valid-json");
+            // Valid JSON but missing required OpenAPI fields like "info" or "paths"
+            File.WriteAllText(openApiPath, """{"openapi": "3.0.0"}""");
 
             var settingsPath = Path.Combine(workspace, "petstore.refitter");
             File.WriteAllText(
                 settingsPath,
                 """{"openApiPath": "petstore.json", "namespace": "Test"}""");
 
             var task = new RefitterGenerateTask
             {
                 BuildEngine = new RecordingBuildEngine(),
                 ProjectFileDirectory = workspace,
                 IncludePatterns = "petstore.refitter",
                 SkipValidation = true
             };
 
             var result = task.Execute();
 
-            result.Should().BeFalse();
+            // With SkipValidation = true and parseable (but invalid) OpenAPI, should succeed
+            result.Should().BeTrue();
         }
         finally
         {
             DeleteWorkspace(workspace);
         }
     }
🔧 Option 2: Rename the test to match its current behavior
     [Test]
-    public void Execute_Should_Skip_Validation_When_SkipValidation_Is_True()
+    public void Execute_Should_Fail_On_Unparseable_OpenAPI_Even_When_SkipValidation_Is_True()
     {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.Tests/MSBuild/RefitterGenerateTaskTests.cs` around lines 232 -
262, The test method Execute_Should_Skip_Validation_When_SkipValidation_Is_True
has inconsistent logic: it writes unparseable JSON and expects Execute() to
return false, but this doesn't actually test validation skipping since JSON
parsing fails before validation runs. To fix this, replace the unparseable JSON
with valid JSON that would normally fail OpenAPI schema validation (such as JSON
missing required OpenAPI fields like "openapi" or "info"), keep SkipValidation
set to true, and change the assertion so result.Should().BeTrue() instead of
BeFalse(), since the validation should be skipped and the valid JSON should be
successfully processed.
🧹 Nitpick comments (5)
docs/prd/decouple-msbuild-from-cli.md (2)

245-245: 💤 Low value

Add language specifier to fenced code block.

The fenced code block for the target architecture diagram should include a language specifier (e.g., ```text) to comply with markdown linting rules.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/prd/decouple-msbuild-from-cli.md` at line 245, The fenced code block in
the target architecture diagram section is missing a language specifier, which
violates markdown linting rules. Add a language specifier such as `text`
immediately after the opening triple backticks (change ``` to ```text) for the
fenced code block at line 245 to comply with markdown linting requirements.

221-221: 💤 Low value

Add language specifier to fenced code block.

The fenced code block for the architecture diagram should include a language specifier (e.g., ```text) to comply with markdown linting rules.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/prd/decouple-msbuild-from-cli.md` at line 221, Add a language specifier
to the opening fence of the architecture diagram code block to comply with
markdown linting rules. Change the opening fence from ` ``` ` to ` ```text ` (or
another appropriate language identifier based on the diagram content) so that
the fenced code block follows markdown best practices for syntax highlighting
and linting compliance.
src/Refitter.Core/OutputPlanner.cs (2)

109-120: 💤 Low value

Consider using the CombineWithSettingsRoot helper in GetContractsOutputPath.

The GetContractsOutputPath method manually combines paths using Path.GetFullPath(Path.Combine(...)) at line 118-119, while the GetMultiFileOutputPath method uses the CombineWithSettingsRoot helper (lines 97, 99). This inconsistency could lead to subtle path-resolution differences. Consider refactoring to use the same helper for consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.Core/OutputPlanner.cs` around lines 109 - 120, The
GetContractsOutputPath method is manually constructing the path using
Path.GetFullPath(Path.Combine(...)), while the GetMultiFileOutputPath method
uses the CombineWithSettingsRoot helper for the same purpose, creating
inconsistency in path resolution. Refactor the GetContractsOutputPath method to
use the CombineWithSettingsRoot helper instead of the manual path combination,
passing the root variable and refitGeneratorSettings.ContractsOutputFolder as
arguments, then combine the result with the outputFile.Filename as before.

22-131: ⚡ Quick win

Replace var with explicit types throughout OutputPlanner.

The coding guidelines discourage use of the var keyword (csharp_style_var_* = false:silent per .editorconfig). This file uses var extensively at lines 22, 25, 48, 54, 61, 75, 81, 88, 92, 114, 118, and 131. Consider replacing with explicit types for consistency with the project's coding standards. As per coding guidelines, "Discourage use of var keyword."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.Core/OutputPlanner.cs` around lines 22 - 131, Replace all
instances of the `var` keyword with explicit types throughout the OutputPlanner
class to comply with the project's coding guidelines that discourage use of
`var`. Specifically, in the PlanFiles method, replace `var planned` with
`List<PlannedFile>` and `var outputFile` with `GeneratedCode`; in
GetSingleFileOutputPath, replace `var root` with `string`, `var
cliOverridesOutput` with `bool`, and `var filename` with `string`; in
GetMultiFileOutputPath, replace `var root` with `string` and `var outputFolder`
with `string?`; in GetContractsOutputPath, replace `var root` with `string` and
`var contractsFolder` with `string`; and in CombineWithSettingsRoot, replace
`var combinedPath` with `string`. This ensures consistency with the project's
editorconfig settings which set `csharp_style_var_* = false:silent`.

Source: Coding guidelines

src/Refitter.MSBuild/RefitterGenerateTask.cs (1)

67-134: ⚡ Quick win

Consider extracting helpers to reduce cognitive complexity.

SonarCloud flags this method's cognitive complexity at 22 (threshold: 15). The method handles settings loading, generation, file I/O, directory creation, and validation. Extracting helpers would improve readability and testability.

The directory creation logic is also duplicated (lines 90-92 and 106-108):

♻️ Suggested helper extraction
private static void EnsureDirectoryExists(string filePath)
{
    var dir = Path.GetDirectoryName(filePath);
    if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
        Directory.CreateDirectory(dir);
}

private static void WriteGeneratedFile(string outputPath, string content, List<string> generatedFiles)
{
    EnsureDirectoryExists(outputPath);
    File.WriteAllText(outputPath, content);
    generatedFiles.Add(Path.GetFullPath(outputPath));
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.MSBuild/RefitterGenerateTask.cs` around lines 67 - 134, The
ProcessRefitterFile method has a cognitive complexity of 22 (exceeding the
threshold of 15) due to handling multiple responsibilities including settings
loading, generation, file I/O, and validation. Extract helper methods to reduce
complexity and eliminate duplication. Create an EnsureDirectoryExists helper
method to encapsulate the duplicated directory creation logic that appears in
the multi-file generation branch and single-file generation branch. Create a
WriteGeneratedFile helper method that calls EnsureDirectoryExists and handles
writing the content to disk and tracking the generated file path. Use these
helpers to replace the duplicated directory creation and file writing logic
throughout the ProcessRefitterFile method, improving readability and
testability.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Refitter.Core/OutputPlanner.cs`:
- Around line 5-136: Add XML documentation comments to all public methods in the
OutputPlanner class to comply with coding guidelines. For each public method
(PlanSingleFile, PlanMultipleFiles, GetSingleFileOutputPath,
GetMultiFileOutputPath, ShouldRerouteToContractsFolder, and
GetContractsOutputPath), add a triple-slash XML documentation comment above the
method signature that describes the method's purpose, parameters, and return
value. Include appropriate summary, param, and returns tags to fully document
each method's functionality.

In `@src/Refitter.MSBuild/RefitterGenerateTask.cs`:
- Around line 79-131: The validation of the OpenAPI spec runs after files are
written to disk, causing orphaned files to remain if validation fails. Move the
validation logic that checks SkipValidation and calls
OpenApiValidator.Validate() to execute before the file generation blocks (the
if/else blocks that call GenerateMultipleFiles() or Generate()). This way,
invalid OpenAPI specs will throw exceptions before any files are written to
disk, preventing orphaned output. Reorganize the code so the validation block
executes first, then only proceed with generating and writing files if
validation passes.

In `@src/Refitter/GenerateCommand.cs`:
- Around line 92-106: Remove the two private GetOutputPath helper methods from
the GenerateCommand class. The first static GetOutputPath method that takes
Settings and RefitGeneratorSettings parameters, and the second instance
GetOutputPath method that takes Settings, RefitGeneratorSettings, and
GeneratedCode parameters are both unused throughout the codebase and serve only
as unnecessary wrappers around OutputPlanner calls. Since these methods are
private, they cannot be called from outside the file, so they can be safely
deleted without affecting any other code.

---

Outside diff comments:
In `@src/Refitter.MSBuild/Refitter.MSBuild.csproj`:
- Around line 13-27: The PropertyGroup in the Refitter.MSBuild.csproj file is
missing the TreatWarningsAsErrors setting that is required per coding guidelines
and already present in Refitter.Core.csproj. Add a new line containing
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> to the PropertyGroup
section, placing it alongside the existing SuppressDependenciesWhenPacking
setting to ensure the project treats all build warnings as errors.

In `@src/Refitter.Tests/MSBuild/RefitterGenerateTaskTests.cs`:
- Around line 232-262: The test method
Execute_Should_Skip_Validation_When_SkipValidation_Is_True has inconsistent
logic: it writes unparseable JSON and expects Execute() to return false, but
this doesn't actually test validation skipping since JSON parsing fails before
validation runs. To fix this, replace the unparseable JSON with valid JSON that
would normally fail OpenAPI schema validation (such as JSON missing required
OpenAPI fields like "openapi" or "info"), keep SkipValidation set to true, and
change the assertion so result.Should().BeTrue() instead of BeFalse(), since the
validation should be skipped and the valid JSON should be successfully
processed.

---

Nitpick comments:
In `@docs/prd/decouple-msbuild-from-cli.md`:
- Line 245: The fenced code block in the target architecture diagram section is
missing a language specifier, which violates markdown linting rules. Add a
language specifier such as `text` immediately after the opening triple backticks
(change ``` to ```text) for the fenced code block at line 245 to comply with
markdown linting requirements.
- Line 221: Add a language specifier to the opening fence of the architecture
diagram code block to comply with markdown linting rules. Change the opening
fence from ` ``` ` to ` ```text ` (or another appropriate language identifier
based on the diagram content) so that the fenced code block follows markdown
best practices for syntax highlighting and linting compliance.

In `@src/Refitter.Core/OutputPlanner.cs`:
- Around line 109-120: The GetContractsOutputPath method is manually
constructing the path using Path.GetFullPath(Path.Combine(...)), while the
GetMultiFileOutputPath method uses the CombineWithSettingsRoot helper for the
same purpose, creating inconsistency in path resolution. Refactor the
GetContractsOutputPath method to use the CombineWithSettingsRoot helper instead
of the manual path combination, passing the root variable and
refitGeneratorSettings.ContractsOutputFolder as arguments, then combine the
result with the outputFile.Filename as before.
- Around line 22-131: Replace all instances of the `var` keyword with explicit
types throughout the OutputPlanner class to comply with the project's coding
guidelines that discourage use of `var`. Specifically, in the PlanFiles method,
replace `var planned` with `List<PlannedFile>` and `var outputFile` with
`GeneratedCode`; in GetSingleFileOutputPath, replace `var root` with `string`,
`var cliOverridesOutput` with `bool`, and `var filename` with `string`; in
GetMultiFileOutputPath, replace `var root` with `string` and `var outputFolder`
with `string?`; in GetContractsOutputPath, replace `var root` with `string` and
`var contractsFolder` with `string`; and in CombineWithSettingsRoot, replace
`var combinedPath` with `string`. This ensures consistency with the project's
editorconfig settings which set `csharp_style_var_* = false:silent`.

In `@src/Refitter.MSBuild/RefitterGenerateTask.cs`:
- Around line 67-134: The ProcessRefitterFile method has a cognitive complexity
of 22 (exceeding the threshold of 15) due to handling multiple responsibilities
including settings loading, generation, file I/O, and validation. Extract helper
methods to reduce complexity and eliminate duplication. Create an
EnsureDirectoryExists helper method to encapsulate the duplicated directory
creation logic that appears in the multi-file generation branch and single-file
generation branch. Create a WriteGeneratedFile helper method that calls
EnsureDirectoryExists and handles writing the content to disk and tracking the
generated file path. Use these helpers to replace the duplicated directory
creation and file writing logic throughout the ProcessRefitterFile method,
improving readability and testability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 687ee52c-daa7-408f-9b93-5386ae1661bb

📥 Commits

Reviewing files that changed from the base of the PR and between a7456a2 and d7ced96.

📒 Files selected for processing (36)
  • .github/workflows/msbuild.yml
  • AGENTS.md
  • docs/prd/decouple-msbuild-from-cli.md
  • src/Refitter.Core/OutputPlanner.cs
  • src/Refitter.Core/RefitterSettingsLoader.cs
  • src/Refitter.Core/Validation/OpenApiStats.cs
  • src/Refitter.Core/Validation/OpenApiValidationException.cs
  • src/Refitter.Core/Validation/OpenApiValidationResult.cs
  • src/Refitter.Core/Validation/OpenApiValidator.cs
  • src/Refitter.MSBuild/DefaultProcessRunner.cs
  • src/Refitter.MSBuild/DefaultRuntimeResolver.cs
  • src/Refitter.MSBuild/IProcessRunner.cs
  • src/Refitter.MSBuild/IRuntimeResolver.cs
  • src/Refitter.MSBuild/ProcessExecutionResult.cs
  • src/Refitter.MSBuild/Refitter.MSBuild.csproj
  • src/Refitter.MSBuild/RefitterGenerateTask.cs
  • src/Refitter.Tests/GenerateCommandTests.cs
  • src/Refitter.Tests/GenerationOrchestratorTests.cs
  • src/Refitter.Tests/MSBuild/RefitterGenerateTaskTests.cs
  • src/Refitter.Tests/OpenApi/OpenApiStatsTests.cs
  • src/Refitter.Tests/OpenApi/OpenApiValidationExceptionTests.cs
  • src/Refitter.Tests/OpenApi/OpenApiValidationResultTests.cs
  • src/Refitter.Tests/OpenApi/OpenApiValidatorTests.cs
  • src/Refitter.Tests/OutputPlannerTests.cs
  • src/Refitter.Tests/RichGenerationReporterTests.cs
  • src/Refitter.Tests/Scenarios/SettingsFileOutputPathTests.cs
  • src/Refitter.Tests/SimpleGenerationReporterTests.cs
  • src/Refitter/GenerateCommand.cs
  • src/Refitter/GenerationOrchestrator.cs
  • src/Refitter/IGenerationReporter.cs
  • src/Refitter/OutputPlanner.cs
  • src/Refitter/RichGenerationReporter.cs
  • src/Refitter/SettingsValidator.cs
  • src/Refitter/SimpleGenerationReporter.cs
  • test/MSBuild/build.ps1
  • test/MSBuild/build.sh
💤 Files with no reviewable changes (9)
  • src/Refitter.MSBuild/DefaultRuntimeResolver.cs
  • src/Refitter.MSBuild/IProcessRunner.cs
  • src/Refitter.MSBuild/ProcessExecutionResult.cs
  • src/Refitter.MSBuild/IRuntimeResolver.cs
  • src/Refitter/OutputPlanner.cs
  • test/MSBuild/build.ps1
  • test/MSBuild/build.sh
  • src/Refitter.MSBuild/DefaultProcessRunner.cs
  • .github/workflows/msbuild.yml

Comment on lines +5 to +136
public static class OutputPlanner
{
public const string DefaultOutputPath = "Output.cs";

public static PlannedFile PlanSingleFile(
string? settingsFilePath,
string? cliOutputPath,
RefitGeneratorSettings refitGeneratorSettings,
string code) =>
new(GetSingleFileOutputPath(settingsFilePath, cliOutputPath, refitGeneratorSettings), code);

public static IReadOnlyList<PlannedFile> PlanMultipleFiles(
string? settingsFilePath,
string? cliOutputPath,
RefitGeneratorSettings refitGeneratorSettings,
GeneratorOutput generatorOutput)
{
var planned = new List<PlannedFile>(generatorOutput.Files.Count);
foreach (var outputFile in generatorOutput.Files)
{
var path = ShouldRerouteToContractsFolder(refitGeneratorSettings, outputFile)
? GetContractsOutputPath(settingsFilePath, refitGeneratorSettings, outputFile)
: GetMultiFileOutputPath(settingsFilePath, cliOutputPath, refitGeneratorSettings, outputFile);

planned.Add(new PlannedFile(path, outputFile.Content));
}

return planned;
}

public static string GetSingleFileOutputPath(
string? settingsFilePath,
string? cliOutputPath,
RefitGeneratorSettings refitGeneratorSettings)
{
if (IsDirectCliGeneration(settingsFilePath))
{
if (HasExplicitCliOutputOverride(cliOutputPath))
return cliOutputPath!;

return DefaultOutputPath;
}

var root = string.IsNullOrWhiteSpace(settingsFilePath)
? string.Empty
: Path.GetDirectoryName(settingsFilePath) ?? string.Empty;

var cliOverridesOutput = HasExplicitCliOutputOverride(cliOutputPath);

string outputPath;
if (cliOverridesOutput)
{
outputPath = cliOutputPath!;
}
else
{
var filename = refitGeneratorSettings.OutputFilename ?? "Output.cs";
outputPath = !string.IsNullOrWhiteSpace(refitGeneratorSettings.OutputFolder)
? Path.Combine(refitGeneratorSettings.OutputFolder, filename)
: filename;
}

if (!string.IsNullOrWhiteSpace(root) && !Path.IsPathRooted(outputPath))
outputPath = Path.Combine(root, outputPath);

return outputPath;
}

public static string GetMultiFileOutputPath(
string? settingsFilePath,
string? cliOutputPath,
RefitGeneratorSettings refitGeneratorSettings,
GeneratedCode outputFile)
{
if (IsDirectCliGeneration(settingsFilePath))
{
var outputDirectory = HasExplicitCliOutputOverride(cliOutputPath)
? cliOutputPath!
: ".";

return Path.Combine(outputDirectory, outputFile.Filename);
}

var root = string.IsNullOrWhiteSpace(settingsFilePath)
? string.Empty
: Path.GetDirectoryName(settingsFilePath) ?? string.Empty;

var outputFolder = HasExplicitCliOutputOverride(cliOutputPath)
? cliOutputPath
: refitGeneratorSettings.OutputFolder;

if (!string.IsNullOrWhiteSpace(outputFolder))
return CombineWithSettingsRoot(root, outputFolder!, outputFile.Filename);

return CombineWithSettingsRoot(root, outputFile.Filename);
}

public static bool ShouldRerouteToContractsFolder(
RefitGeneratorSettings refitGeneratorSettings,
GeneratedCode outputFile) =>
!string.IsNullOrWhiteSpace(refitGeneratorSettings.ContractsOutputFolder)
&& refitGeneratorSettings.ContractsOutputFolder != RefitGeneratorSettings.DefaultOutputFolder
&& outputFile.Filename == $"{TypenameConstants.Contracts}.cs";

public static string GetContractsOutputPath(
string? settingsFilePath,
RefitGeneratorSettings refitGeneratorSettings,
GeneratedCode outputFile)
{
var root = string.IsNullOrWhiteSpace(settingsFilePath)
? string.Empty
: Path.GetDirectoryName(settingsFilePath) ?? string.Empty;

var contractsFolder = Path.GetFullPath(Path.Combine(root, refitGeneratorSettings.ContractsOutputFolder!));
return Path.Combine(contractsFolder, outputFile.Filename);
}

private static bool IsDirectCliGeneration(string? settingsFilePath) =>
string.IsNullOrWhiteSpace(settingsFilePath);

private static bool HasExplicitCliOutputOverride(string? cliOutputPath) =>
!string.IsNullOrWhiteSpace(cliOutputPath) &&
cliOutputPath != DefaultOutputPath;

private static string CombineWithSettingsRoot(string root, params string[] segments)
{
var combinedPath = Path.Combine(segments);
return !string.IsNullOrWhiteSpace(root) && !Path.IsPathRooted(combinedPath)
? Path.Combine(root, combinedPath)
: combinedPath;
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Add XML documentation for all public methods in OutputPlanner.

The coding guidelines require XML documentation for public APIs. All public methods in this new OutputPlanner class lack XML documentation comments. As per coding guidelines, "Include XML documentation for public APIs in C# code."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.Core/OutputPlanner.cs` around lines 5 - 136, Add XML
documentation comments to all public methods in the OutputPlanner class to
comply with coding guidelines. For each public method (PlanSingleFile,
PlanMultipleFiles, GetSingleFileOutputPath, GetMultiFileOutputPath,
ShouldRerouteToContractsFolder, and GetContractsOutputPath), add a triple-slash
XML documentation comment above the method signature that describes the method's
purpose, parameters, and return value. Include appropriate summary, param, and
returns tags to fully document each method's functionality.

Source: Coding guidelines

Comment on lines +79 to 131
if (settings.GenerateMultipleFiles)
{
FileName = "dotnet",
Arguments = args,
WorkingDirectory = Path.GetDirectoryName(file)!,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
UseShellExecute = false,
CreateNoWindow = true,
};

var processResult = ProcessRunner.Run(
startInfo,
data => HandleProcessStandardOutput(data, outputLines, outputLines, TryLogCommandLine),
data => HandleProcessErrorOutput(data, TryLogError));

if (processResult.TimedOut)
{
failed = true;
var timeoutDescription = FormatTimeout(ProcessTimeoutMilliseconds);
TryLogError(
processResult.TerminationException is null
? $"Refitter process timed out after {timeoutDescription} and was terminated"
: $"Refitter process timed out after {timeoutDescription}. Failed to terminate timed-out process: {processResult.TerminationException.Message}");

return new();
var output = generator.GenerateMultipleFiles();
foreach (var outputFile in output.Files)
{
var outputPath = OutputPlanner.GetMultiFileOutputPath(
filePath,
cliOutputPath: null,
settings,
outputFile);

var dir = Path.GetDirectoryName(outputPath);
if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);

File.WriteAllText(outputPath, outputFile.Content);
generatedFiles.Add(Path.GetFullPath(outputPath));
}
}

if (processResult.ExitCode != 0)
else
{
failed = true;
TryLogError($"Refitter process exited with code {processResult.ExitCode}");
return new List<string>();
}
var code = generator.Generate().Replace("\r\n", "\n");
var outputPath = OutputPlanner.GetSingleFileOutputPath(
filePath,
cliOutputPath: null,
settings);

return ResolveGeneratedFiles(outputLines, file, out failed, TryLogError);
}
var dir = Path.GetDirectoryName(outputPath);
if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir))
Directory.CreateDirectory(dir);

internal static string? ResolveRefitterDll(
string? packageFolder,
IReadOnlyList<string>? installedRuntimes,
Action<string> logCommandLine,
Func<string, bool> fileExists)
{
if (string.IsNullOrWhiteSpace(packageFolder))
{
return null;
File.WriteAllText(outputPath, code);
generatedFiles.Add(Path.GetFullPath(outputPath));
}

var bundledRuntimes = PreferredRuntimeOrder
.Select(candidate => new
{
candidate.TargetFramework,
candidate.RuntimePrefix,
Path = Path.GetFullPath(Path.Combine(packageFolder, "..", candidate.TargetFramework, "refitter.dll")),
})
.ToArray();

if (installedRuntimes is not null)
if (!SkipValidation)
{
var detectedRuntimes = installedRuntimes
.Where(installed => !string.IsNullOrWhiteSpace(installed))
.ToArray();
var openApiPaths = settings.OpenApiPaths is { Length: > 0 }
? settings.OpenApiPaths
: settings.OpenApiPath is not null
? [settings.OpenApiPath]
: [];

foreach (var runtime in bundledRuntimes.Where(runtime => fileExists(runtime.Path)))
foreach (var specPath in openApiPaths)
{
if (detectedRuntimes.Any(installed =>
installed.StartsWith(runtime.RuntimePrefix, StringComparison.Ordinal)))
if (!string.IsNullOrWhiteSpace(specPath))
{
logCommandLine($"Detected {GetDisplayFramework(runtime.TargetFramework)} runtime. Using {GetDisplayFramework(runtime.TargetFramework)} version of Refitter.");
return runtime.Path;
var validationResult = OpenApiValidator.Validate(specPath)
.GetAwaiter().GetResult();
validationResult.ThrowIfInvalid();
}
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validation runs after generation, leaving orphaned files on failure.

The current flow writes generated files to disk (lines 79-112) before validating the OpenAPI spec (lines 114-131). If validation fails and throws, the exception bubbles up to Execute() which sets hasErrors = true and returns false, but the generated files remain on disk.

Consider validating first so invalid specs don't produce partial/orphaned output:

♻️ Suggested refactor: validate before generating
 private List<string> ProcessRefitterFile(string filePath)
 {
     var baseDirectory = Path.GetDirectoryName(Path.GetFullPath(filePath))!;
     var json = File.ReadAllText(filePath);
     var settings = RefitterSettingsLoader.Load(json, baseDirectory);
     RefitterSettingsLoader.ApplyDefaults(filePath, settings);
 
+    if (!SkipValidation)
+    {
+        ValidateOpenApiSpecs(settings);
+    }
+
     var generator = RefitGenerator.CreateAsync(settings)
         .GetAwaiter().GetResult();
 
     var generatedFiles = new List<string>();
 
     if (settings.GenerateMultipleFiles)
     {
         // ... generation logic ...
     }
     else
     {
         // ... generation logic ...
     }
 
-    if (!SkipValidation)
-    {
-        // ... validation logic ...
-    }
-
     return generatedFiles;
 }
+
+private void ValidateOpenApiSpecs(RefitterSettings settings)
+{
+    var openApiPaths = settings.OpenApiPaths is { Length: > 0 }
+        ? settings.OpenApiPaths
+        : settings.OpenApiPath is not null
+            ? new[] { settings.OpenApiPath }
+            : Array.Empty<string>();
+
+    foreach (var specPath in openApiPaths.Where(p => !string.IsNullOrWhiteSpace(p)))
+    {
+        var validationResult = OpenApiValidator.Validate(specPath)
+            .GetAwaiter().GetResult();
+        validationResult.ThrowIfInvalid();
+    }
+}
🧰 Tools
🪛 GitHub Check: SonarCloud Code Analysis

[warning] 122-122: Loops should be simplified using the "Where" LINQ method

See more on https://sonarcloud.io/project/issues?id=christianhelle_refitter&issues=AZ7Qy_gdaocEy_afE5Mq&open=AZ7Qy_gdaocEy_afE5Mq&pullRequest=1154


[warning] 118-120: Extract this nested ternary operation into an independent statement.

See more on https://sonarcloud.io/project/issues?id=christianhelle_refitter&issues=AZ7Qy_gdaocEy_afE5Mp&open=AZ7Qy_gdaocEy_afE5Mp&pullRequest=1154

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.MSBuild/RefitterGenerateTask.cs` around lines 79 - 131, The
validation of the OpenAPI spec runs after files are written to disk, causing
orphaned files to remain if validation fails. Move the validation logic that
checks SkipValidation and calls OpenApiValidator.Validate() to execute before
the file generation blocks (the if/else blocks that call GenerateMultipleFiles()
or Generate()). This way, invalid OpenAPI specs will throw exceptions before any
files are written to disk, preventing orphaned output. Reorganize the code so
the validation block executes first, then only proceed with generating and
writing files if validation passes.

Comment on lines 92 to +106
private static string GetOutputPath(Settings settings, RefitGeneratorSettings refitGeneratorSettings) =>
OutputPlanner.GetSingleFileOutputPath(settings, refitGeneratorSettings);
OutputPlanner.GetSingleFileOutputPath(
settings.SettingsFilePath,
settings.OutputPath,
refitGeneratorSettings);

private string GetOutputPath(
Settings settings,
RefitGeneratorSettings refitGeneratorSettings,
GeneratedCode outputFile) =>
OutputPlanner.GetMultiFileOutputPath(settings, refitGeneratorSettings, outputFile);

internal static void ApplySettingsFileDefaults(string settingsFilePath, RefitGeneratorSettings refitGeneratorSettings)
{
if (!string.IsNullOrWhiteSpace(refitGeneratorSettings.ContractsOutputFolder))
refitGeneratorSettings.GenerateMultipleFiles = true;

if (string.IsNullOrWhiteSpace(refitGeneratorSettings.OutputFolder))
refitGeneratorSettings.OutputFolder = RefitGeneratorSettings.DefaultOutputFolder;

if (string.IsNullOrWhiteSpace(refitGeneratorSettings.OutputFilename))
{
var refitterFileName = Path.GetFileNameWithoutExtension(settingsFilePath);
if (string.IsNullOrEmpty(refitterFileName))
refitterFileName = "Output";
refitGeneratorSettings.OutputFilename = $"{refitterFileName}.cs";
}
}
OutputPlanner.GetMultiFileOutputPath(
settings.SettingsFilePath,
settings.OutputPath,
refitGeneratorSettings,
outputFile);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for any remaining calls to these private GetOutputPath helpers
rg -n 'GetOutputPath\s*\(' --type cs

Repository: christianhelle/refitter

Length of output: 1012


🏁 Script executed:

cd src/Refitter && wc -l GenerateCommand.cs

Repository: christianhelle/refitter

Length of output: 90


🏁 Script executed:

# Read the GenerateCommand.cs file to see the context and any calls to GetOutputPath
cat -n src/Refitter/GenerateCommand.cs | head -150 | tail -100

Repository: christianhelle/refitter

Length of output: 4771


🏁 Script executed:

# Check if GetOutputPath is called in GenerateCommand.cs with different search patterns
rg -n 'GetOutputPath' src/Refitter/GenerateCommand.cs

Repository: christianhelle/refitter

Length of output: 216


Remove these unused private GetOutputPath helper methods.

The two private GetOutputPath methods (lines 92–106) are not called anywhere in this file or the rest of the codebase. Since they're private, they cannot be invoked from other files. They appear to be obsolete wrappers around OutputPlanner calls.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter/GenerateCommand.cs` around lines 92 - 106, Remove the two
private GetOutputPath helper methods from the GenerateCommand class. The first
static GetOutputPath method that takes Settings and RefitGeneratorSettings
parameters, and the second instance GetOutputPath method that takes Settings,
RefitGeneratorSettings, and GeneratedCode parameters are both unused throughout
the codebase and serve only as unnecessary wrappers around OutputPlanner calls.
Since these methods are private, they cannot be called from outside the file, so
they can be safely deleted without affecting any other code.

@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.67123% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.74%. Comparing base (a7456a2) to head (bb84065).

Files with missing lines Patch % Lines
src/Refitter.Core/OutputPlanner.cs 83.63% 0 Missing and 9 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1154      +/-   ##
==========================================
+ Coverage   94.57%   94.74%   +0.16%     
==========================================
  Files          65       69       +4     
  Lines        3095     3156      +61     
==========================================
+ Hits         2927     2990      +63     
- Misses         58       62       +4     
+ Partials      110      104       -6     
Flag Coverage Δ
unittests 94.74% <87.67%> (+0.16%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@christianhelle christianhelle self-assigned this Jun 16, 2026
@christianhelle christianhelle added enhancement New feature, bug fix, or request .NET Pull requests that contain changes to .NET code labels Jun 16, 2026
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Refitter.MSBuild/Refitter.MSBuild.csproj (1)

4-16: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Missing TreatWarningsAsErrors property.

Per coding guidelines, production projects under src/Refitter.MSBuild/ should enable TreatWarningsAsErrors. This property is not present in the PropertyGroup.

🛠️ Proposed fix
     <PropertyGroup>
         <TargetFramework>netstandard2.0</TargetFramework>
+        <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
         <Product>Refitter MSBuild Tasks</Product>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Refitter.MSBuild/Refitter.MSBuild.csproj` around lines 4 - 16, The
PropertyGroup in the Refitter.MSBuild.csproj file is missing the
TreatWarningsAsErrors property required by coding guidelines. Add the
TreatWarningsAsErrors property set to true within the PropertyGroup section that
contains TargetFramework, Product, PackageId, AssemblyName, RootNamespace,
Title, Description, GenerateDependencyFile, BuildOutputTargetFolder,
CopyLocalLockFileAssemblies, and SuppressDependenciesWhenPacking properties.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/Refitter.MSBuild/Refitter.MSBuild.csproj`:
- Around line 4-16: The PropertyGroup in the Refitter.MSBuild.csproj file is
missing the TreatWarningsAsErrors property required by coding guidelines. Add
the TreatWarningsAsErrors property set to true within the PropertyGroup section
that contains TargetFramework, Product, PackageId, AssemblyName, RootNamespace,
Title, Description, GenerateDependencyFile, BuildOutputTargetFolder,
CopyLocalLockFileAssemblies, and SuppressDependenciesWhenPacking properties.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: afee6881-27d3-4f4f-9c4e-71c92df15983

📥 Commits

Reviewing files that changed from the base of the PR and between d7ced96 and bb84065.

📒 Files selected for processing (4)
  • .gitignore
  • src/Refitter.MSBuild/Refitter.MSBuild.csproj
  • src/Refitter.Tests/OutputPlannerTests.cs
  • src/Refitter.Tests/SettingsFile/RefitterSettingsLoaderTests.cs
✅ Files skipped from review due to trivial changes (1)
  • .gitignore

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature, bug fix, or request .NET Pull requests that contain changes to .NET code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant