Skip to content

fix: resolve short scheduler names, report unusable [ReactiveCommand] methods, and convert properties to partial properties - #505

Merged
glennawatson merged 1 commit into
mainfrom
fix/command-diagnostics-and-schedulers
Sep 26, 2026
Merged

glennawatson merged 1 commit into
mainfrom
fix/command-diagnostics-and-schedulers

Conversation

@glennawatson

Copy link
Copy Markdown
Contributor

Summary

Scheduler names resolve as written, [ReactiveCommand] methods and schedulers the generator skips are reported, and the RXUISG0016 fix makes a [Reactive] partial property.

  • OutputScheduler and BackgroundScheduler names are bound as C# at the attribute. "RxSchedulers.MainThreadScheduler" resolves through the file's usings, as do members of the class and fully qualified names; a static member elsewhere is written fully qualified.
  • A new ReactiveCommandAnalyzer reports what the command generator skips. RXUISG0002 for a method with more than one parameter besides a CancellationToken, RXUISG0008 for an async void method, and RXUISG0021 (warning) for a scheduler name that does not resolve.
  • The analyzer and the generator compile one ReactiveCommandRules file. What the analyzer reports is exactly what the generator skips.
  • The RXUISG0016 code fix makes a [Reactive] partial property. It makes the containing types partial too, from C# 13, or C# 14 when the property has an initializer; otherwise it makes a [Reactive] field as before.
  • Analyzer release tracking is complete and recorded as released. Every change is under Release 4.0 in AnalyzerReleases.Shipped.md, including the removal of RXUISG0001 to RXUISG0008 from the generator.

Why

Several [ReactiveCommand] mistakes produced no command, or a command without its scheduler, and no diagnostic.

  • The README's "RxSchedulers.MainThreadScheduler" was silently ignored: only a class member or a global:: name worked, so a BackgroundScheduler command did not run in the background.
  • A method with two command parameters got no command, and an async void method got a command that could not observe it; RXUISG0001 to RXUISG0008 were still listed as shipped although nothing reported them.
  • The RXUISG0016 fix produced a [Reactive] field, whose property exists only in generated code that other generators, such as ReactiveUI.Binding's, cannot see.

Breaking changes

New diagnostics can now fail a build that compiled before.

  • RXUISG0002 and RXUISG0008 are errors: give the method at most one parameter besides a CancellationToken, and return Task instead of async void.
  • RXUISG0021 is a warning: name a scheduler that resolves, or remove the argument.
  • A scheduler name that was ignored before now takes effect, so the command runs or delivers on that scheduler.

How this was verified

Tests cover every rule the analyzer reports and every case it must not, the scheduler forms in generated output, and the code fix at C# 12, 13 and preview, compiling its output with the [Reactive] generator.

  • The existing Scheduler snapshot, which uses "RxSchedulers.MainThreadScheduler", recorded the dropped scheduler and now shows it; no other snapshot changed.

Notes for the reviewer

Start with ReactiveCommandRules.cs; the generator and analyzer changes are thin callers of it.

  • The scheduler type is read from the ReactiveUI command factories' outputScheduler parameter, so each ReactiveUI flavour gets its own without separate API detection.
  • The code fix checks the running compiler is Roslyn 4.14 or later before making a partial property: the 4.8 generator band, which Roslyn 4.12 and 4.13 load, does not generate partial properties.
  • CLAUDE.md now says analyzer rules are recorded in AnalyzerReleases.Shipped.md only.

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

… methods, and convert properties to partial properties

[ReactiveCommand] OutputScheduler and BackgroundScheduler names are bound as
C# at the attribute, so "RxSchedulers.MainThreadScheduler" resolves through the
file's usings; before, only a member of the class or a fully qualified name
worked and anything else was dropped without a word. A static member elsewhere
is written fully qualified, and the scheduler type is the one the ReactiveUI
command factories take.

A new ReactiveCommandAnalyzer reports what the generator skips, from the same
ReactiveCommandRules file the generator compiles: RXUISG0002 for a method with
more than one parameter besides a CancellationToken, RXUISG0008 for an async
void method, both restored with their original meaning, and RXUISG0021 for a
scheduler name that does not resolve.

The RXUISG0016 code fix makes a [Reactive] partial property, and its containing
types partial, from C# 13 (C# 14 with an initializer) when the compiler's
generator build supports partial properties; otherwise it makes a [Reactive]
field as before.

Analyzer release tracking records every rule change in AnalyzerReleases.Shipped.md
under Release 4.0, including the removal of RXUISG0001 to RXUISG0008 from the
generator; the Unshipped files stay empty.
@codecov

codecov Bot commented Sep 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.70%. Comparing base (ac6d0b7) to head (9cd14d6).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #505      +/-   ##
==========================================
+ Coverage   96.55%   96.70%   +0.15%     
==========================================
  Files          72       74       +2     
  Lines        3653     3759     +106     
  Branches      506      531      +25     
==========================================
+ Hits         3527     3635     +108     
+ Misses        126      124       -2     

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

@glennawatson
glennawatson merged commit 7158aa0 into main Sep 26, 2026
12 checks passed
@glennawatson
glennawatson deleted the fix/command-diagnostics-and-schedulers branch September 26, 2026 14:43
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.

1 participant