Skip to content

feat!: move to StyleSharp analyzers and ReactiveUI 26, add ReactiveUI.Validation.Reactive - #990

Merged
glennawatson merged 5 commits into
mainfrom
feature/stylesharp-reactiveui26
Oct 3, 2026
Merged

glennawatson merged 5 commits into
mainfrom
feature/stylesharp-reactiveui26

Conversation

@glennawatson

@glennawatson glennawatson commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This moves ReactiveUI.Validation to ReactiveUI 26 and the StyleSharp analyzer set. It also adds a package for apps that use ReactiveUI.Reactive.

  • The build uses StyleSharp, PerformanceSharp and SecuritySharp analyzers in place of StyleCop and Roslynator, with the same .editorconfig as ReactiveUI.Binding.SourceGenerators.
  • Every analyzer finding in the library, AndroidX, tests and samples is fixed.
  • NuGet packages are updated, including ReactiveUI 26, TUnit 1.72 and DynamicData.
  • New package ReactiveUI.Validation.Reactive builds the same source against ReactiveUI.Reactive. Its namespaces start with ReactiveUI.Validation.Reactive, and it takes System.Reactive IScheduler instances.
  • New package ReactiveUI.Validation.AndroidX.Reactive does the same for the AndroidX TextInputLayout bindings.
  • The Android builds no longer generate a public Resource class. The libraries ship no Android resources.
  • When no formatter is passed, the default formatter is found with GetServices. A dependency injection container that throws for an unregistered type falls back to SingleLineFormatter.
  • The public API is tracked with PublicApiSharp baselines under PublicAPI/<tfm>/PublicAPI.txt. They replace the Verify approval tests.
  • The MinVer floor is 8.0.

Why

Breaking changes

  • ReactiveUI 26 is required. Its WhenAnyValue needs a reference-type sender.
  • BasePropertyValidation<TViewModel, TViewModelProperty> and the ValidationRule extensions need TViewModel to be a class.
  • Optional parameters on public methods and constructors are now overloads. Source still compiles; compiled callers must rebuild. Calls that named only a later optional argument, such as strict: false, must pass the earlier ones too.
  • ValidationRule throws ArgumentException for an empty message. It still throws ArgumentNullException for a null one.
  • The public Resource class is removed from the Android assemblies.
  • ReactiveValidationObject and ObservableValidationBase are no longer abstract. Their constructors stay protected.

How this was verified

The full test suite runs twice, once against each package. New tests cover the formatter fallback with a container that throws for unregistered types.

Notes for the reviewer

  • Most of the diff is mechanical analyzer output: file headers, one-line summaries, static lambdas and named constants. It is safe to skim.
  • Start with ValidationBinding, ValidationTextFormatterResolver and ReactiveUI.Validation.Reactive.csproj.
  • Each library file switches its namespace on REACTIVE_SHIM. The library's own namespaces are imported in ReactiveUI.Validation.Usings.props, so the same file compiles into both packages.
  • Suppressions, each with a justification: SST1703 on both ViewForExtensions classes, SST2307 on ValidationBinding.ForViewModel, SST2309 on two interface members, CA1005 on ObservableValidation<TViewModel, TValue, TProp>, and SST1436 on the IsExternalInit polyfill. Each fix would break public API or is not possible in C#.
  • The ReactiveUI.Binding 9 generator skips WhenAnyValue calls whose selector returns an anonymous type or a private nested type, and the call then throws at run time. Two tests were adjusted for this. It needs a fix in ReactiveUI.Binding.SourceGenerators.

Checklist

  • I have read the Contribute guide
  • The PR title follows Conventional Commits
  • Tests cover this change, or the summary says why they do not
  • New or changed public API has XML documentation

….Validation.Reactive

- Replace StyleCop.Analyzers and Roslynator with StyleSharp, PerformanceSharp and SecuritySharp, matching ReactiveUI.Binding.SourceGenerators.
- Fix every analyzer finding in the library, AndroidX, tests and samples.
- Update NuGet packages, including ReactiveUI 26 and TUnit 1.72.
- Use the WhenAnyValueUnsafe overloads where an expression is passed in, since ReactiveUI 26 only intercepts literal lambdas.
- Resolve the default formatter with GetServices. Containers that throw from GetService for an unregistered type then fall back to the default formatter (#979).
- Add ReactiveUI.Validation.Reactive, built from the same source against ReactiveUI.Reactive (#967).
- Track the public API with PublicApiSharp baselines in place of the Verify approval tests.
- Raise the MinVer floor to 8.0.

BREAKING CHANGE: Requires ReactiveUI 26. View model type parameters need a class constraint. Optional parameters on public methods and constructors are now overloads, so callers must recompile.
- Set AndroidGenerateResourceDesigner to false for every Android target.
- The libraries ship no Android resources, so the designer only added an empty public Resource type.
- Build the AndroidX extensions a second time against ReactiveUI.AndroidX.Reactive and ReactiveUI.Validation.Reactive.
- Apps on ReactiveUI.Reactive get the TextInputLayout bindings under ReactiveUI.Validation.Reactive.Extensions.
- Copy .gitattributes from ReactiveUI.Binding.SourceGenerators.
- A Windows checkout with core.autocrlf rewrites files to CRLF, and the line-ending analyzer then fails the Windows build.
@codecov

codecov Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (76e7ee6) to head (807ccdb).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #990   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           21        23    +2     
  Lines          665       694   +29     
  Branches       114       104   -10     
=========================================
+ Hits           665       694   +29     

☔ 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.

- Remove the validity subject in BasePropertyValidation. Nothing ever pushed a value into it.
- Bind ValidationContext properties by name. The generated ToProperty never runs the lambda, which left those lines uncovered.
- Cover the Dispose(false) paths, the parameterless overloads and the non-generic enumerators.
@glennawatson
glennawatson merged commit e68c8a6 into main Oct 3, 2026
8 checks passed
@glennawatson
glennawatson deleted the feature/stylesharp-reactiveui26 branch October 3, 2026 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Custom DI container with RxUI - Unable to resolve type IValidationTextFormatter [Bug]: Compatibility with ReactiveUI.Reactive 24.0.0

2 participants