Skip to content

Update GeneratorPipeline to use injected IContractsPostProcessor adapters#1139

Merged
christianhelle merged 6 commits into
mainfrom
feat/generator-pipeline
Jun 14, 2026
Merged

Update GeneratorPipeline to use injected IContractsPostProcessor adapters#1139
christianhelle merged 6 commits into
mainfrom
feat/generator-pipeline

Conversation

@christianhelle

@christianhelle christianhelle commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Changes

  • New: \IContractsPostProcessor\ interface for composable post-generation contract transforms
  • New: \Swagger2OptionalReferenceNullabilityNormalizer\ — normalizes Swagger 2.0 optional reference type nullability (extracted from \GeneratorPipeline.NormalizeSwagger2OptionalReferencePropertyNullability)
  • New: \EnumStringConverterInjector\ — injects \JsonStringEnumConverter\ attributes on enum declarations (extracted from \GeneratorPipeline.SanitizeGeneratedContracts)
  • Refactor: \GeneratorPipeline\ now accepts \XmlDocumentationGenerator, \InterfaceGenerator, and \IEnumerable\ via constructor injection instead of creating them inline with
    ew\
  • Refactor: Three \internal static\ helpers (\SanitizeGeneratedContracts, \NormalizeSwagger2OptionalReferencePropertyNullability, \GenerateJsonSerializerContext) removed from \GeneratorPipeline's public surface — the first two live as post-processors, the third stays as a private method in \Run()\
  • Refactor: \RefitGenerator.RunPipeline()\ constructs the pipeline with real dependencies; private wrapper methods removed
  • Test: All affected tests updated to use the new API directly instead of reflection

Verification

  • ✅ Build succeeds with zero errors
  • ✅ All 2152 tests pass across all three test projects

Summary by CodeRabbit

  • Refactor
    • Restructured contract generation to use a modular post-processing flow, applying ordered transformations before generating serializer context, clients, and DI registration.
    • Added post-processing to normalize Swagger2 optional reference nullability when nullable reference types are enabled.
    • Added post-processing for enum JSON converter handling, including correct attribute removal/injection based on configuration and preservation of CRLF formatting.
  • Tests
    • Updated and simplified generator and contract-processing tests to validate the new post-processing behavior directly.

Add IContractsPostProcessor interface for post-generation contract
transformation. Create Swagger2OptionalReferenceNullabilityNormalizer
and EnumStringConverterInjector implementations, extracted from
GeneratorPipeline.SanitizeGeneratedContracts and
NormalizeSwagger2OptionalReferencePropertyNullability.
GeneratorPipeline now accepts XmlDocumentationGenerator, InterfaceGenerator,
and IContractsPostProcessor collection via constructor instead of creating
them inline. The three internal static helpers (SanitizeGeneratedContracts,
NormalizeSwagger2OptionalReferencePropertyNullability, GenerateJsonSerializerContext)
are removed from public API surface. SanitizeGeneratedContracts and
NormalizeSwagger2OptionalReferencePropertyNullability now live in the
IContractsPostProcessor implementations. GenerateJsonSerializerContext
remains as a private helper called inline in Run().
Removed private wrapper methods (SanitizeGeneratedContracts,
NormalizeSwagger2OptionalReferencePropertyNullability,
GenerateJsonSerializerContext) that leaked pipeline internals.
RunPipeline() now constructs GeneratorPipeline with real
XmlDocumentationGenerator, InterfaceGenerator, and post-processors.
Update GeneratorPipelineTests to construct GeneratorPipeline with
constructor args. Update RefitGeneratorAdvancedTests to test
Swagger2OptionalReferenceNullabilityNormalizer and
JsonSerializerContextGenerator directly instead of using
reflection on removed private methods.
Test was using reflection on removed RefitGenerator.SanitizeGeneratedContracts
method. Now tests EnumStringConverterInjector directly.
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b0f8360b-c638-4b8c-b57a-4e3279e00faf

📥 Commits

Reviewing files that changed from the base of the PR and between bc05459 and 64d086f.

📒 Files selected for processing (1)
  • src/Refitter.Tests/Regression/RefitGeneratorAdvancedTests.cs

📝 Walkthrough

Walkthrough

Introduces an IContractsPostProcessor interface and extracts two contract transformation behaviors—EnumStringConverterInjector and Swagger2OptionalReferenceNullabilityNormalizer—from GeneratorPipeline into discrete implementations. GeneratorPipeline and RefitGenerator are rewired to accept and apply these processors in sequence. Tests drop reflection-based invocations in favor of direct processor construction.

Changes

Contracts Post-Processor Pipeline

Layer / File(s) Summary
IContractsPostProcessor contract
src/Refitter.Core/IContractsPostProcessor.cs
Defines the IContractsPostProcessor internal interface with a Process(OpenApiDocument, RefitGeneratorSettings, string) method signature.
Post-processor implementations
src/Refitter.Core/EnumStringConverterInjector.cs, src/Refitter.Core/Swagger2OptionalReferenceNullabilityNormalizer.cs
EnumStringConverterInjector uses regex to remove existing JsonStringEnumConverter attributes and conditionally re-injects them on enum declarations when InlineJsonConverters is disabled. Swagger2OptionalReferenceNullabilityNormalizer uses Roslyn syntax rewriting to strip Nullable<T> wrapping from reference-type properties in Swagger2 documents, with a helper to classify which type syntaxes count as reference types.
Pipeline and generator wiring
src/Refitter.Core/GeneratorPipeline.cs, src/Refitter.Core/RefitGenerator.cs
GeneratorPipeline constructor accepts InterfaceGenerator and IEnumerable<IContractsPostProcessor>; Run applies each processor sequentially to transform contracts. RefitGenerator.RunPipeline removes the stored pipeline field, constructs XmlDocumentationGenerator and InterfaceGenerator explicitly, wires the two post-processors into a new GeneratorPipeline, and removes delegating helper methods.
Test updates
src/Refitter.Tests/GeneratorPipelineTests.cs, src/Refitter.Tests/Regression/RefitGeneratorAdvancedTests.cs, src/Refitter.Tests/Scenarios/InlineJsonConvertersTests.cs
Tests replace reflection-based calls to private RefitGenerator methods with direct construction and invocation of Swagger2OptionalReferenceNullabilityNormalizer, EnumStringConverterInjector, and JsonSerializerContextGenerator. A new test validates struct value-type nullability handling in the normalizer.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • christianhelle/refitter#1127: Embeds the Swagger2 nullability normalization and JSON enum converter handling inside GeneratorPipeline — this PR extracts those same behaviors into IContractsPostProcessor implementations.
  • christianhelle/refitter#786: Implements the same InlineJsonConverters/[JsonConverter(typeof(JsonStringEnumConverter))] enum attribute feature that EnumStringConverterInjector now encapsulates.

🐇 A pipeline once tangled, now neat and aligned,
Each processor hops in its own tidy line.
No reflection, no secrets, the classes stand tall,
IContractsPostProcessor — one interface for all!
The enum converters inject with grace,
And nullability normalizers find their place. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title accurately summarizes the main architectural change: refactoring GeneratorPipeline to use dependency-injected IContractsPostProcessor adapters instead of inline logic.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 feat/generator-pipeline

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.

@christianhelle christianhelle changed the title feat: GeneratorPipeline — injected seams and IContractsPostProcessor adapters Update GeneratorPipeline to use injected IContractsPostProcessor adapters Jun 14, 2026
@christianhelle christianhelle self-assigned this Jun 14, 2026
@christianhelle christianhelle added enhancement New feature, bug fix, or request .NET Pull requests that contain changes to .NET code labels Jun 14, 2026

@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: 1

🧹 Nitpick comments (2)
src/Refitter.Core/GeneratorPipeline.cs (1)

11-18: ⚡ Quick win

Remove unused docGenerator parameter.

The docGenerator parameter in the GeneratorPipeline constructor is not stored or used anywhere in the class. Since InterfaceGenerator is already constructed with docGenerator (as seen in RefitGenerator.RunPipeline at line 166), there's no need to pass it again to GeneratorPipeline.

♻️ Proposed fix
     internal GeneratorPipeline(
-        XmlDocumentationGenerator docGenerator,
         InterfaceGenerator interfaceGenerator,
         IEnumerable<IContractsPostProcessor> contractsPostProcessors)

Also update the call site in RefitGenerator.cs line 168:

         var pipeline = new GeneratorPipeline(
-            docGenerator,
             interfaceGenerator,

And update GeneratorPipelineTests.cs line 136:

         var pipeline = new GeneratorPipeline(
-            docGenerator,
             interfaceGenerator,
🤖 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/GeneratorPipeline.cs` around lines 11 - 18, The
docGenerator parameter in the GeneratorPipeline constructor is unused and should
be removed since InterfaceGenerator is already constructed with the docGenerator
elsewhere. Remove the docGenerator parameter from the GeneratorPipeline
constructor signature in src/Refitter.Core/GeneratorPipeline.cs (lines 11-18).
Update the constructor call in RefitGenerator.cs line 168 to not pass the
docGenerator argument. Update the GeneratorPipeline instantiation in
GeneratorPipelineTests.cs line 136 to remove the docGenerator argument from the
constructor call.
src/Refitter.Core/IContractsPostProcessor.cs (1)

2-2: 💤 Low value

Remove redundant using directive.

The using Refitter.Core; directive on line 2 is redundant since this file already declares namespace Refitter.Core; on line 4.

♻️ Proposed fix
 using NSwag;
-using Refitter.Core;
 
 namespace Refitter.Core;
🤖 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/IContractsPostProcessor.cs` at line 2, Remove the redundant
using Refitter.Core directive since the file is already declared within the
namespace Refitter.Core. Delete the using statement and keep only the namespace
declaration, as a file does not need to import the namespace it belongs to.
🤖 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/Swagger2OptionalReferenceNullabilityNormalizer.cs`:
- Around line 39-49: The `IsReferenceType` method assumes all
`IdentifierNameSyntax`, `GenericNameSyntax`, `QualifiedNameSyntax`, and
`AliasQualifiedNameSyntax` nodes are reference types, but this heuristic may
incorrectly handle custom struct types. Add test case coverage for optional
struct properties (such as `MyStruct?`) to document and verify the normalizer's
behavior when custom value types appear as optional properties, explicitly
capturing whether the normalizer correctly preserves or incorrectly unwraps
nullable semantics for struct types. This test should complement the existing
coverage for arrays, generic types, and qualified names.

---

Nitpick comments:
In `@src/Refitter.Core/GeneratorPipeline.cs`:
- Around line 11-18: The docGenerator parameter in the GeneratorPipeline
constructor is unused and should be removed since InterfaceGenerator is already
constructed with the docGenerator elsewhere. Remove the docGenerator parameter
from the GeneratorPipeline constructor signature in
src/Refitter.Core/GeneratorPipeline.cs (lines 11-18). Update the constructor
call in RefitGenerator.cs line 168 to not pass the docGenerator argument. Update
the GeneratorPipeline instantiation in GeneratorPipelineTests.cs line 136 to
remove the docGenerator argument from the constructor call.

In `@src/Refitter.Core/IContractsPostProcessor.cs`:
- Line 2: Remove the redundant using Refitter.Core directive since the file is
already declared within the namespace Refitter.Core. Delete the using statement
and keep only the namespace declaration, as a file does not need to import the
namespace it belongs to.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7d1b1707-0295-4f8f-b5b6-91ffe07f1fbb

📥 Commits

Reviewing files that changed from the base of the PR and between 7d03c6a and bc05459.

📒 Files selected for processing (8)
  • src/Refitter.Core/EnumStringConverterInjector.cs
  • src/Refitter.Core/GeneratorPipeline.cs
  • src/Refitter.Core/IContractsPostProcessor.cs
  • src/Refitter.Core/RefitGenerator.cs
  • src/Refitter.Core/Swagger2OptionalReferenceNullabilityNormalizer.cs
  • src/Refitter.Tests/GeneratorPipelineTests.cs
  • src/Refitter.Tests/Regression/RefitGeneratorAdvancedTests.cs
  • src/Refitter.Tests/Scenarios/InlineJsonConvertersTests.cs

Comment thread src/Refitter.Core/Swagger2OptionalReferenceNullabilityNormalizer.cs
@christianhelle
christianhelle enabled auto-merge June 14, 2026 11:07
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • src/Refitter.Tests/Regression/RefitGeneratorAdvancedTests.cs

Commit: 64d086f2c7717a3852b07953bebaabbdb636d701

The changes have been pushed to the feat/generator-pipeline branch.

Time taken: 3m 10s

Fixed 1 file(s) based on 1 unresolved review comment.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
@christianhelle
christianhelle merged commit b47490f into main Jun 14, 2026
5 of 10 checks passed
@christianhelle
christianhelle deleted the feat/generator-pipeline branch June 14, 2026 11:12
@sonarqubecloud

Copy link
Copy Markdown

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