Skip to content

Commit 708d77a

Browse files
authored
breaking: Remove .NET Standard 2.0, modernize AOT compatibility (#4257)
BREAKING CHANGES: 1. Removed .NET Standard 2.0 support - minimum target is now net8.0 or net462 2. Removed RxApp.cs - replaced with RxAppBuilder pattern 3. Removed PlatformRegistrationManager.cs - replaced with modern builder pattern 4. Solution file renamed: ReactiveUI.sln → reactiveui.slnx (SLNX format) 5. Removed polyfill attributes now built into modern .NET: - CallerArgumentExpressionAttribute - DoesNotReturnIfAttribute - NotNullAttribute - IsExternalInit 6. Removed platform-specific ComponentModelTypeConverter implementations 7. Removed legacy DefaultViewLocator.AOT.cs ## Migration Guide ### .NET Standard 2.0 Removal Projects targeting .NET Standard 2.0 must upgrade to at least .NET 8.0. ReactiveUI now requires modern .NET with built-in nullable reference types, init properties, and AOT attributes. **Before:** - Supported: netstandard2.0, net462+, net8+ - Used polyfill attributes for modern C# features **After:** - Minimum: net8.0 for cross-platform, net462 for Windows-only legacy, net9.0 for maui platforms - Uses built-in .NET attributes for nullable/AOT support ### RxApp Removal The static RxApp class has been removed in favor of the builder pattern. **Before:** ```csharp RxApp.MainThreadScheduler.Schedule(() => { }); RxApp.TaskpoolScheduler.Schedule(() => { }); After: // Use RxSchedulers for AOT-safe scheduler access RxSchedulers.MainThreadScheduler.Schedule(() => { }); RxSchedulers.TaskpoolScheduler.Schedule(() => { }); // Or use builder pattern for initialization var builder = RxAppBuilder.CreateReactiveUIBuilder(resolver) .WithCoreServices() .BuildApp(); ``` Solution File Renamed Before: src/ReactiveUI.sln (legacy text format) After: src/reactiveui.slnx (XML-based format) Impact: - Update CI/CD scripts referencing ReactiveUI.sln → reactiveui.slnx - Requires Visual Studio 2022 17.10+ or JetBrains Rider 2024.1+ for IDE support - All dotnet CLI commands work identically (no syntax changes) Major Enhancements Test Coverage (80%+ achieved) - Reorganized test projects for better coverage analysis - Removed duplicate/obsolete test projects: - ReactiveUI.AOTTests (consolidated into main tests) - ReactiveUI.Builder.Tests (consolidated) - ReactiveUI.Splat.Tests (functionality moved to core) - ReactiveUI.Testing.Tests (consolidated) - Fixed intermittent test failures with proper Locator scoping - Added comprehensive MAUI activation tests - Enhanced builder API tests with WithInstance coverage AOT Compatibility Improvements This branch addresses numerous AOT warnings and improves trimming compatibility: - Removed reflection-heavy PlatformRegistrationManager - Removed ComponentModelTypeConverter (used reflection) - Streamlined view locator implementation (removed AOT-specific version) - All polyfill attributes removed (used UnconditionalSuppressMessage) - Improved DynamicallyAccessedMembers usage throughout codebase Bug Fixes - Nested property binding: Fixed redundant setter calls that caused performance issues and unexpected behavior when binding to nested properties - MAUI activation: Resolved activation lifecycle issues in MAUI controls - Test flakiness: Fixed race conditions in Locator-dependent tests by introducing LocatorScope pattern API Enhancements - Builder API: Added BuilderMixins with WithInstance pattern for better testability - XML Documentation: Comprehensive docs added to: - All public interfaces (IActivatableView, IViewFor, etc.) - Suspension APIs (ISuspensionHost, ISuspensionDriver) - Interaction APIs (IInteraction, IInteractionContext) - View locator and activation APIs - Usage Examples: Added code examples to public API documentation Documentation Improvements Added comprehensive educational documentation (CLAUDE.md, copilot-instructions.md): SLNX Format Documentation - What SLNX is (XML-based solution format, VS 2022 17.10+) - Key differences from .sln (structured XML vs proprietary text) - IDE compatibility requirements - CLI usage (identical to .sln files) Microsoft Testing Platform (MTP) Documentation - What MTP is and why ReactiveUI uses it (modern test platform replacing VSTest) - How MTP differs from VSTest (argument syntax, configuration) - Configuration files explained (global.json, testconfig.json, Directory.Build.props) - Best practices: - Never use --no-build flag (causes stale binary issues) - Correct argument placement: dotnet test flags BEFORE --, TUnit flags AFTER -- - How to see Console.WriteLine output (--output Detailed) - Non-parallel test execution rationale Command Reference Improvements - Fixed coverage argument placement (--coverage goes BEFORE --) - Reorganized command-line flags by tool (dotnet test vs TUnit) - Removed contradictory examples (--no-build) - All solution references updated to reactiveui.slnx Key Deletions - src/ReactiveUI.sln → migrated to reactiveui.slnx - src/ReactiveUI/RxApp.cs → replaced with RxAppBuilder pattern - src/ReactiveUI/PlatformRegistrationManager.cs → replaced with builder pattern - src/ReactiveUI/RegistrationNamespace.cs → obsolete with new registration approach - src/ReactiveUI/Helpers/*.cs → polyfill attributes removed (4 files) - src/ReactiveUI/IsExternalInit.cs → built into modern .NET - src/ReactiveUI.*/GlobalUsings.cs → removed from Maui/WinUI (2 files) - src/ReactiveUI/Platforms/*/ComponentModelTypeConverter.cs → reflection-based, removed (3 files) - src/ReactiveUI/View/DefaultViewLocator.AOT.cs → consolidated with main implementation - Multiple test projects consolidated (ReactiveUI.AOTTests, Builder.Tests, Splat.Tests, etc.) Platform Support Matrix Before: - netstandard2.0 (cross-platform) - net462, net472, net481 (Windows legacy) - net8.0, net9.0, net10.0 (modern) After: - net462, net472, net481 (Windows legacy - minimum for Windows-only projects) - net8.0, net9.0, net10.0 (cross-platform minimum) - net8.0/9.0/10.0-windows10.0.19041.0 (Windows-specific features) - iOS, tvOS, macOS, Android, MAUI targets unchanged Co-authored-by: Christian Fischerauer [email protected]
1 parent c53052f commit 708d77a

File tree

812 files changed

+49025
-35776
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

812 files changed

+49025
-35776
lines changed

.claude/settings.local.json

Lines changed: 0 additions & 12 deletions
This file was deleted.

.editorconfig

Lines changed: 524 additions & 392 deletions
Large diffs are not rendered by default.

.github/copilot-instructions.md

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,21 @@ Invoke-WebRequest -Uri https://dot.net/v1/dotnet-install.ps1 -OutFile dotnet-ins
4141

4242
### Solution Files
4343

44-
* Main solution: `src/ReactiveUI.sln` (repository `root/src` directory)
44+
* Main solution: `src/reactiveui.slnx` (repository `root/src` directory)
4545
* Integration tests: `integrationtests/` directory contains platform-specific solutions. These are not required for most tasks to compile.
4646

47+
**About SLNX Format:**
48+
49+
This repository uses **SLNX** (XML-based solution format) introduced in Visual Studio 2022 17.10+, instead of the legacy `.sln` format.
50+
51+
**Key characteristics:**
52+
- Structured XML format vs. proprietary text format
53+
- Better support for complex multi-platform projects like ReactiveUI
54+
- Full compatibility with `dotnet` CLI (works identically to .sln)
55+
- Requires Visual Studio 2022 17.10+ or JetBrains Rider 2024.1+ for IDE support
56+
57+
All commands in this document reference `src/reactiveui.slnx`.
58+
4759
---
4860

4961
## 🛠️ Build & Test Commands
@@ -67,24 +79,42 @@ dotnet workload restore
6779
cd ..
6880
6981
# Restore NuGet packages
70-
dotnet restore src/ReactiveUI.sln
82+
dotnet restore src/reactiveui.slnx
7183
7284
# Build the solution (requires Windows for platform-specific targets)
73-
dotnet build src/ReactiveUI.sln -c Release -warnaserror
85+
dotnet build src/reactiveui.slnx -c Release -warnaserror
7486
```
7587

7688
### Test Commands (Microsoft Testing Platform)
7789

7890
**CRITICAL:** This repository uses MTP configured in `src/global.json`. All TUnit-specific arguments must be passed after `--`.
7991

92+
**Microsoft Testing Platform (MTP) Overview:**
93+
94+
MTP is the modern test execution platform replacing VSTest, providing:
95+
- Native integration with `dotnet test` command
96+
- Better performance and modern architecture for .NET 6.0+
97+
- Enhanced test filtering and parallel execution control
98+
- Required for TUnit framework (ReactiveUI's chosen test framework)
99+
100+
**Key Differences from VSTest:**
101+
- Arguments passed AFTER `--`: `dotnet test -- --treenode-filter "..."`
102+
- Configured via `global.json` (specifies "Microsoft.Testing.Platform")
103+
- Test settings in `testconfig.json` (parallel execution, coverage format)
104+
105+
**Best Practices:**
106+
- **Never use `--no-build`** - always build before testing to avoid stale binaries
107+
- Use `--output Detailed` BEFORE `--` to see Console.WriteLine output
108+
- TUnit runs non-parallel (`"parallel": false`) to prevent test interference
109+
80110
**Note:** Commands below assume repository root as working directory. Use `src/` prefix for paths.
81111

82112
```powershell
83113
# Run all tests
84-
dotnet test src/ReactiveUI.sln -c Release --no-build
114+
dotnet test src/reactiveui.slnx -c Release
85115
86116
# Run tests with code coverage (Microsoft Code Coverage)
87-
dotnet test src/ReactiveUI.sln -- --coverage --coverage-output-format cobertura
117+
dotnet test src/reactiveui.slnx --coverage --coverage-output-format cobertura
88118
89119
# Run specific test project
90120
dotnet test --project src/tests/ReactiveUI.Tests/ReactiveUI.Tests.csproj
@@ -96,16 +126,16 @@ dotnet test --project src/tests/ReactiveUI.Tests/ReactiveUI.Tests.csproj -- --tr
96126
dotnet test --project src/tests/ReactiveUI.Tests/ReactiveUI.Tests.csproj -- --treenode-filter "/*/*/MyClassName/*"
97127
98128
# Filter by test property (e.g., Category)
99-
dotnet test src/ReactiveUI.sln -- --treenode-filter "/*/*/*/*[Category=Integration]"
129+
dotnet test src/reactiveui.slnx -- --treenode-filter "/*/*/*/*[Category=Integration]"
100130
101131
# List all available tests
102132
dotnet test --project src/tests/ReactiveUI.Tests/ReactiveUI.Tests.csproj -- --list-tests
103133
104134
# Fail fast (stop on first failure)
105-
dotnet test src/ReactiveUI.sln -- --fail-fast
135+
dotnet test src/reactiveui.slnx -- --fail-fast
106136
107137
# Generate TRX report with coverage
108-
dotnet test src/ReactiveUI.sln -- --coverage --coverage-output-format cobertura --report-trx --output Detailed
138+
dotnet test src/reactiveui.slnx --coverage --coverage-output-format cobertura -- --report-trx --output Detailed
109139
```
110140

111141
**TUnit Treenode-Filter Syntax:**
@@ -118,10 +148,14 @@ Examples:
118148
- All tests in namespace: `--treenode-filter "/*/MyNamespace/*/*"`
119149
- Filter by property: `--treenode-filter "/*/*/*/*[Category=Integration]"`
120150

121-
**Key TUnit Command-Line Flags:**
122-
- `--treenode-filter` - Filter tests by path or properties
151+
**Key Command-Line Flags:**
152+
153+
**dotnet test flags (BEFORE `--`):**
123154
- `--coverage` - Enable Microsoft Code Coverage
124155
- `--coverage-output-format` - Set format (cobertura, xml, coverage)
156+
157+
**TUnit flags (AFTER `--`):**
158+
- `--treenode-filter` - Filter tests by path or properties
125159
- `--report-trx` - Generate TRX reports
126160
- `--output` - Verbosity (Normal or Detailed)
127161
- `--list-tests` - Display tests without running
@@ -528,11 +562,66 @@ _total = this.WhenAnyValue(
528562

529563
```powershell
530564
# Build with warnings as errors (includes StyleCop violations)
531-
dotnet build src/ReactiveUI.sln -c Release -warnaserror
565+
dotnet build src/reactiveui.slnx -c Release -warnaserror
532566
```
533567

534568
**Important:** Style violations will cause build failures. Use an IDE with EditorConfig support (Visual Studio, VS Code, Rider) to automatically format code according to project standards.
535569

570+
### Zero Pragma Policy for Warning Suppression
571+
572+
**CRITICAL: This project enforces a strict zero pragma policy.**
573+
574+
* **NO `#pragma warning disable` statements are allowed** in any code files
575+
* **All StyleCop analyzer warnings (SA****) MUST be fixed**, never suppressed
576+
* **Code analyzer warnings (CA****) may ONLY be suppressed as an absolute last resort** using `[SuppressMessage]` attribute with these requirements:
577+
1. You have attempted to fix the warning first
578+
2. Fixing it would make the code worse or is not technically feasible
579+
3. You use `[SuppressMessage]` attribute (NOT pragma)
580+
4. You provide a clear, valid justification in the `Justification` parameter
581+
582+
#### Examples
583+
584+
```csharp
585+
// ❌ WRONG - Never use pragma directives
586+
#pragma warning disable CA1062
587+
public void ProcessData(object data)
588+
{
589+
data.ToString(); // CA1062: Validate parameter is non-null
590+
}
591+
#pragma warning restore CA1062
592+
593+
// ✅ CORRECT - Fix the issue
594+
public void ProcessData(object data)
595+
{
596+
ArgumentNullException.ThrowIfNull(data);
597+
data.ToString();
598+
}
599+
600+
// ⚠️ ACCEPTABLE - SuppressMessage with justification (last resort only)
601+
[SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods",
602+
Justification = "TUnit framework guarantees non-null parameters from test data sources")]
603+
public async Task ValidateConverter(IBindingTypeConverter converter, int expectedAffinity)
604+
{
605+
var affinity = converter.GetAffinityForObjects(); // converter is never null
606+
await Assert.That(affinity).IsEqualTo(expectedAffinity);
607+
}
608+
```
609+
610+
#### Common StyleCop Fixes (Must Be Fixed, Never Suppressed)
611+
612+
* **SA1202** (Static members before instance members): Reorder class members
613+
* **SA1204** (Static members before non-static): Move static members to top
614+
* **SA1402** (One type per file): Convert file-scoped types to nested private classes
615+
* **SA1611** (Parameter documentation missing): Add `<param>` XML tags
616+
* **SA1615** (Return value documentation missing): Add `<returns>` XML tags
617+
* **SA1600** (Elements should be documented): Add XML documentation to public members
618+
619+
#### Enforcement
620+
621+
* Builds fail with `-warnaserror` if any analyzer warnings exist
622+
* Any pragma directives will be flagged and rejected during code review
623+
* `SuppressMessage` usage requires clear justification and approval
624+
536625
---
537626

538627
## 📋 Testing Guidelines

.github/workflows/ci-build.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ jobs:
2020
with:
2121
configuration: Release
2222
productNamespacePrefix: "ReactiveUI"
23-
solutionFile: "ReactiveUI.sln"
2423
installWorkloads: true
2524
secrets:
2625
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,3 +450,6 @@ src/Tools/
450450
**/*.GeneratedMSBuildEditorConfig.editorconfig
451451
/app
452452
.dotnet/
453+
454+
# Claude Settings
455+
.claude/

0 commit comments

Comments
 (0)