feat!: reflection-free source-generated request building#2210
Merged
Conversation
- Add TimestampQuery / TimestampPath rows (a DateTimeOffset whose invariant form needs escaping) so the span-escape encoder is measured against the reflection builder for both query and path values. - Add a custom-verb row so the cached HttpMethod path is exercised.
- IObservable methods now build inline, so RF006 no longer fires for them; move the shape from the reflection-fallback analyzer cases to the inline-supported cases, matching the generator's fallback contract.
…uest-building # Conflicts: # src/Refit/GeneratedParameterAttributeProvider.cs
- Resolved in favour of the request-building rework: the branch predates it and its path-parameter code is superseded by the inline rework. - Dropped PathFragmentModel (the rework has its own path models). - Kept the updated analyzer rule configuration. Co-Authored-By: Timothy Makkison <timmakkison@gmail.com>
- Move the nested attribute-array flatten out of the AllAttributesCache getter into a static FlattenAttributes helper that copies each array with Array.Copy, removing the nested loop that needed the suppression.
- Replace the StyleSharp SST2229/2230/2233 and stylesharp.* hot-path LINQ configuration with the PerformanceSharp PSH1100/1101/1102 and performancesharp.* equivalents in the root and tests .editorconfig. - Point the S103/S3880 duplicate-rule notes at their new owners and keep the 200-char line limit the repo enforces.
- Add runtime, generator, and reflection tests bringing every file touched by the reflection-free request-building feature to 100% line coverage. - Remove dead code surfaced by the coverage push: inline FindHttpMethodProperty so its unreachable return null folds into the covered fallback, drop the dead PropertyDeclarationSyntax getter arm, and delete the redundant adapter bounds guard (the source-generated binder indexes the same slots without one). - Bump StyleSharp/PerformanceSharp to 3.21.2, SonarAnalyzer.CSharp to 10.29.0.143774, TUnit to 1.59.0, Verify.TUnit to 31.24.1, and Serilog to 4.4.0; the analyzer update clears the SonarCloud SST2015/SST1462 build errors.
…dies - Implemented `Parser.Request.Query.Objects` to flatten complex query values into query pairs for Refit stubs. - Introduced `GeneratedRequestRunner.BodyContent` for serializing request bodies in various formats (JSON, JSON Lines, URL-encoded). - Added `GeneratedRequestRunner.Sending` to handle sending requests and processing responses, including support for observables and streaming responses.
- Split oversized files into behavior-named partial classes and extract long methods (SST1522/SST1523) across Refit.Reflection, Refit.Testing, and the test and benchmark projects. - Fix mechanical findings: buried ++/-- (SST2015), numeric-suffix casing (SST2244), redundant interface public (SST1491), replaceable collections (SST2305), per-call serializer options (PSH1416), and assorted others. - Suppress the few genuinely-unfixable findings with justifications: CS0501- mandated abstract on an explicit-interface re-abstraction, options capturing a per-call resolver, the interface-dispatch and sync-stream test surfaces, and the BCL-mirror [Flags] enum polyfill. - Behavior unchanged; the full solution builds analyzer-clean and all tests pass.
ChrisPulman
approved these changes
Jul 13, 2026
…mbdas in various files
- Add branch-covering tests across the generator, runtime, reflection, testing, analyzer and code-fix files, closing 74 of the 125 partial/uncovered branches flagged on the touched files. - Drive the real generated/parsed and reflection request-building surface for each untested condition outcome (attribute combos, param/return shapes, dotted paths, query objects, dictionaries, multipart parts, custom verbs, adapters, RFC-3986 escaping, cancellation linking, and error/fallback paths). - The remaining 51 branches are provably unreachable (compiler-generated string jump tables, dead null-conditionals on never-null operands, exhaustive switch defaults, async-iterator dispose-mode IL edges, contract-guaranteed non-null).
- Remove provably-dead branches surfaced by the coverage push: drop `?.`/`??` guards on operands the surrounding invariant proves non-null (Roslyn symbol namespaces/containers, JsonSerializerOptions.GetTypeInfo, a String JSON element's GetString, a CanRead property's getter, the resolved adapter type), and dead ternary/switch arms that cannot be reached. - Isolate the structurally-uncoverable branches into tiny private helpers marked [ExcludeFromCodeCoverage] (compiler string-switch jump tables, async-iterator dispose-mode IL edges, BCL-nullable defensive guards, analyzer-blocked arms), keeping the excluded surface minimal and the surrounding coverable logic intact. - Consolidate the duplicated known-verb string switch into one shared Parser.MapKnownHttpVerb, and the linked-cancellation-token pattern into one GeneratedRequestRunner.ResolveRequestCancellationToken. - Behavior unchanged: generator snapshots byte-identical, all tests pass, and every touched file now reports 100% branch coverage.
- Bump StyleSharp/PerformanceSharp to 3.22.0, which adds SST2307 (a generic method whose type parameter cannot be inferred from its parameters, so every caller must name it). - Disable Sonar S4018 as a duplicate of SST2307 and enable SST2307 as error, matching the repo's swap convention for Sonar/Sharp overlaps. - Swap every product and test [SuppressMessage] from S4018 to SST2307.
- Bump StyleSharp/PerformanceSharp to 3.23.1. - Swap S1541 -> SST1442 and S2360 -> SST2309, the Sonar rules now disabled as duplicates of the Sharp equivalents that fire on the same code. - Remove suppressions of rules set to none with no firing equivalent (CA1031, CA1040, CA1044, CA1835, CA2208, IDE0079, IDE1006, S100, S1118, S2326); delete the now-empty GlobalSuppressions.cs and the usings that orphaned. - Swap CA2227 -> SST2305 on the settable-collection test model where the Sharp rule does fire once the CA suppression is gone. - Clears the SonarScanner build, where disabled Sonar rules made those suppressions dead and tripped SST1462.
- Bump StyleSharp/PerformanceSharp to 3.25.2. - Swap the remaining Sonar S-rules (S1133, S2339, S2342, S2930, S3903, S4022, S4070, S6566, S6966) to their Sharp/CA/PSH equivalents, so the SonarScanner build no longer trips SST1462 on suppressions of the S-rules it strips. - Repair escaped-quote corruption in the S2930/S6566 swaps, whose rule titles contain \" and broke the substitution. - Drop now-dead suppressions (S4070, RCS1157, CA1849) and an orphaned using. - Disable SST2314: ObsoleteAttribute.DiagnosticId is unavailable on the net4x targets. - Relax SST2016 and SST2410 in the test tree for DateTime test models and short-lived test disposables.
d851392 to
dec46db
Compare
|
glennawatson
added a commit
to TimothyMakkison/refit
that referenced
this pull request
Jul 14, 2026
Integrate the reflection-free source-generated request building (reactiveui#2210) with the version-configuration move. Emitter no longer inlines the NET6+ version block; GeneratedRequestRunner.AddConfiguredRequestOptions applies it instead. Generator snapshots are regenerated in the following commit.
This was referenced Jul 14, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



What kind of change does this PR introduce?
Feature, performance, and a breaking release (V14). It completes the move to source-generated, reflection-free request building.
What is the new behavior?
Refit builds requests directly, so the common method shapes work in generated-only and Native AOT clients with no runtime reflection:
[AliasAs],[Query](Format,CollectionFormat), scalar collections, and query-object flattening.[QueryConverter]for shapes only known at runtime.[QueryName]valueless flags and[Encoded]per-parameter encoding opt-out.[Body]on POST/PUT/PATCH, and an all-scalar form body serialized straight-line with no descriptor array and no boxing.IReturnTypeAdapter.Generated code targets C# 7.3 and lights up newer syntax (nullable annotations and so on) when the consumer's language version allows.
What is the current behavior?
Most of these shapes went through the reflection request builder, which is not trim- or AOT-safe. The RF006 analyzer now flags any method that still needs reflection, so a generated-only build fails at compile time instead of throwing at runtime.
Closes #2185
Closes #2190
Closes #2191
Closes #2192
Closes #2168
Closes #2169
Closes #2002
Closes #2165
Closes #1101
Closes #2200
What might this PR break?
ValueTaskinstead ofTask(ApiResponse<T>.EnsureSuccess*Async, theIApiResponse<T>extensions,DefaultApiExceptionFactory.CreateAsync, and theRefitSettingsasync delegates).Refit.Reflectionpackage. Interfaces that all generate inline do not need it; RF006 names any method that does.RestService.For.Full detail is in
docs/breaking-changes.md.Checklist
mainbranchAdditional information
A lot of the path-parameter work here grew out of @TimothyMakkison's ideas. He was already exploring AOT path-parameter support in #2209 and said he planned to work on it. The
ISpanFormattablefast-write for path values is his idea, and that commit credits him as co-author. Thanks, @TimothyMakkison.Verified across net8 to net11: the full generator and runtime suites pass, the solution builds with no analyzer warnings, and generated code compiles down to the C# 7.3 baseline.