Skip to content

Commit ae298ad

Browse files
authored
Bump ReactiveUI to V23 and adapt generators (#392)
Bump ReactiveUI to 23 and adapt generators Upgrade ReactiveUI to 23.2.1 and update generators, tests, and docs to match API changes. Added a ReactiveUI version check provider and switched generated code to use RxState.DefaultExceptionHandler when ReactiveUI > 22 (falling back to RxApp.DefaultExceptionHandler otherwise). Updated generator wiring to combine the version provider, adjusted generated scheduler references in tests and README (RxSchedulers.MainThreadScheduler), bumped the console project's TargetFramework to net10.0 and switched a Roslyn analyzer project reference to the new Roslyn5000 project. Also added an Installation section to the README and minor attribute/definition adjustments.
1 parent 197effe commit ae298ad

11 files changed

Lines changed: 47 additions & 18 deletions

File tree

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ This documentation covers using ReactiveUI Source Generators to simplify and enh
88
- **ReactiveUI Version**: 19.5.31+
99

1010
## Table of Contents
11+
- [Installation](#installation)
1112
- [Overview](#overview)
1213
- [Supported Attributes & Features](#supported-attributes)
1314
- [Detailed Usage](#welcome-to-a-new-way---source-generators)
@@ -20,6 +21,12 @@ This documentation covers using ReactiveUI Source Generators to simplify and enh
2021
- [Compatibility Notes](#compatibility-notes)
2122
- [Credits](#credits)
2223

24+
## Installation
25+
26+
dotnet add package ReactiveUI.SourceGenerators
27+
28+
Ensure the package is loaded with `PrivateAssets="all"` to avoid issues with generated code in consuming projects.
29+
2330
## Overview
2431

2532
ReactiveUI Source Generators automatically generate ReactiveUI objects to streamline your code. These Source Generators are designed to work with ReactiveUI V19.5.31+ and support the following features:
@@ -35,7 +42,7 @@ ReactiveUI Source Generators automatically generate ReactiveUI objects to stream
3542
- `[ObservableAsProperty(InitialValue = "Default Value")]` Only valid for partial properties using (C# 13 Visual Studio Version 17.12.0)
3643
- `[ReactiveCommand]`
3744
- `[ReactiveCommand(CanExecute = nameof(IObservableBoolName))]` with CanExecute
38-
- `[ReactiveCommand(OutputScheduler = "RxApp.MainThreadScheduler")]` using a ReactiveUI Scheduler
45+
- `[ReactiveCommand(OutputScheduler = "RxSchedulers.MainThreadScheduler")]` using a ReactiveUI Scheduler
3946
- `[ReactiveCommand(OutputScheduler = nameof(_isheduler))]` using a Scheduler defined in the class
4047
- `[ReactiveCommand][property: AttributeToAddToCommand]` with Attribute passthrough
4148
- `[ReactiveCommand(AccessModifier = PropertyAccessModifier.Internal)]` sets the access modifier of the generated command property
@@ -547,7 +554,7 @@ using ReactiveUI.SourceGenerators;
547554

548555
public partial class MyReactiveClass
549556
{
550-
[ReactiveCommand(OutputScheduler = "RxApp.MainThreadScheduler")]
557+
[ReactiveCommand(OutputScheduler = "RxSchedulers.MainThreadScheduler")]
551558
private void Execute() { }
552559
}
553560
```

src/Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<PackageVersion Include="Splat" Version="19.3.1" />
1313
<PackageVersion Include="stylecop.analyzers" Version="1.2.0-beta.556" />
1414
<PackageVersion Include="Roslynator.Analyzers" Version="4.15.0" />
15-
<PackageVersion Include="ReactiveUI" Version="22.3.1" />
15+
<PackageVersion Include="ReactiveUI" Version="23.2.1" />
1616
<PackageVersion Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
1717
<PackageVersion Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
1818
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />

src/ReactiveUI.SourceGenerator.Tests/UnitTests/ReactiveCMDGeneratorTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public Task Scheduler()
148148
namespace TestNs;
149149
public partial class TestVM : ReactiveObject
150150
{
151-
[ReactiveCommand(OutputScheduler = "RxApp.MainThreadScheduler")]
151+
[ReactiveCommand(OutputScheduler = "RxSchedulers.MainThreadScheduler")]
152152
private int Test1() => 10;
153153
}
154154
""";

src/ReactiveUI.SourceGenerator.Tests/UnitTests/RxCmdExtTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ public partial class TestVM : ReactiveObject
462462
{
463463
public IObservable<bool> CanExecuteCommand => Observable.Return(true);
464464
465-
[ReactiveCommand(CanExecute = nameof(CanExecuteCommand), OutputScheduler = "RxApp.MainThreadScheduler")]
465+
[ReactiveCommand(CanExecute = nameof(CanExecuteCommand), OutputScheduler = "RxScheduler.MainThreadScheduler")]
466466
private async Task<string> ExecuteWithScheduler()
467467
{
468468
await Task.Delay(100);

src/ReactiveUI.SourceGenerators.Execute/ReactiveUI.SourceGenerators.Execute.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net8.0-windows</TargetFramework>
5+
<TargetFramework>net10.0-windows</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<UseWPF>true</UseWPF>
88
<UseWindowsForms>true</UseWindowsForms>
@@ -21,6 +21,6 @@
2121
<ItemGroup>
2222
<ProjectReference Include="..\ReactiveUI.SourceGenerators.Analyzers.CodeFixes\ReactiveUI.SourceGenerators.Analyzers.CodeFixes.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
2323
<ProjectReference Include="..\ReactiveUI.SourceGenerators.Execute.Nested3\ReactiveUI.SourceGenerators.Execute.Nested3.csproj" />
24-
<ProjectReference Include="..\ReactiveUI.SourceGenerators.Roslyn4120\ReactiveUI.SourceGenerators.Roslyn4120.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
24+
<ProjectReference Include="..\ReactiveUI.SourceGenerators.Roslyn5000\ReactiveUI.SourceGenerators.Roslyn5000.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
2525
</ItemGroup>
2626
</Project>

src/ReactiveUI.SourceGenerators.Roslyn/AttributeDefinitions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ internal static class AttributeDefinitions
1313
{
1414
public const string GeneratedCode = "global::System.CodeDom.Compiler.GeneratedCode";
1515
public const string Obsolete = "global::System.Obsolete";
16-
1716
public const string AccessModifierType = "ReactiveUI.SourceGenerators.AccessModifier";
17+
public const string ReactiveUI = "ReactiveUI";
18+
1819
public static string[] ExcludeFromCodeCoverage = ["[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]"];
1920

2021
public static string GetAccessModifierEnum() => $$"""

src/ReactiveUI.SourceGenerators.Roslyn/Core/Extensions/ContextExtensions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,11 @@ internal static void GetForwardedAttributes(
111111
var attributes = forwardedAttributeBuilder.ToImmutable();
112112
forwardedAttributes = attributes.Select(static a => a.ToString()).ToImmutableArray();
113113
}
114+
115+
internal static IncrementalValueProvider<bool> ReactiveUIVersionIsGreaterThan22(this in IncrementalGeneratorInitializationContext context) =>
116+
context.CompilationProvider.Select(static (compilation, token) =>
117+
{
118+
token.ThrowIfCancellationRequested();
119+
return compilation.ReferencedAssemblyNames.FirstOrDefault(a => a.Name == AttributeDefinitions.ReactiveUI)?.Version.Major > 22;
120+
});
114121
}

src/ReactiveUI.SourceGenerators.Roslyn/RoutedControlHost/RoutedControlHostGenerator.Execute.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,13 @@ public partial class RoutedControlHostGenerator
8080
classAttributesInfo);
8181
}
8282

83-
private static string GetRoutedControlHost(string containingTypeName, string containingNamespace, string containingClassVisibility, string containingType, RoutedControlHostInfo vmcInfo)
83+
private static string GetRoutedControlHost(string containingTypeName, string containingNamespace, string containingClassVisibility, string containingType, RoutedControlHostInfo vmcInfo, bool isNewerThan22)
8484
{
8585
// Prepare any forwarded property attributes
8686
var forwardedAttributesString = string.Join("\n ", AttributeDefinitions.ExcludeFromCodeCoverage.Concat(vmcInfo.ForwardedAttributes));
87+
var exceptionHandler = isNewerThan22
88+
? "RxState.DefaultExceptionHandler!.OnNext"
89+
: "RxApp.DefaultExceptionHandler!.OnNext";
8790

8891
return
8992
$$"""
@@ -162,7 +165,7 @@ namespace {{containingNamespace}}
162165
}
163166
164167
ResumeLayout();
165-
}, RxApp.DefaultExceptionHandler!.OnNext));
168+
}, {{exceptionHandler}}));
166169
}
167170
168171
/// <inheritdoc/>

src/ReactiveUI.SourceGenerators.Roslyn/RoutedControlHost/RoutedControlHostGenerator.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Microsoft.CodeAnalysis;
1010
using Microsoft.CodeAnalysis.CSharp.Syntax;
1111
using Microsoft.CodeAnalysis.Text;
12+
using ReactiveUI.SourceGenerators.Extensions;
1213
using ReactiveUI.SourceGenerators.Helpers;
1314

1415
namespace ReactiveUI.SourceGenerators.WinForms;
@@ -25,6 +26,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
2526
context.RegisterPostInitializationOutput(ctx =>
2627
ctx.AddSource($"{AttributeDefinitions.RoutedControlHostAttributeType}.g.cs", SourceText.From(AttributeDefinitions.GetRoutedControlHostAttribute(), Encoding.UTF8)));
2728

29+
var reactiveUiVersionProvider = context.ReactiveUIVersionIsGreaterThan22();
30+
2831
// Gather info for all annotated IViewFor Classes
2932
var rchInfo =
3033
context.SyntaxProvider
@@ -34,12 +37,13 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
3437
static (context, token) => GetClassInfo(context, token))
3538
.Where(x => x != null)
3639
.Select((x, _) => x!)
37-
.Collect();
40+
.Collect()
41+
.Combine(reactiveUiVersionProvider);
3842

3943
// Generate the requested properties and methods for IViewFor
4044
context.RegisterSourceOutput(rchInfo, static (context, input) =>
4145
{
42-
var groupedPropertyInfo = input.GroupBy(
46+
var groupedPropertyInfo = input.Left.GroupBy(
4347
static info => (info.FileHintName, info.TargetName, info.TargetNamespace, info.TargetVisibility, info.TargetType),
4448
static info => info)
4549
.ToImmutableArray();
@@ -58,7 +62,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
5862
continue;
5963
}
6064

61-
var source = GetRoutedControlHost(grouping.Key.TargetName, grouping.Key.TargetNamespace, grouping.Key.TargetVisibility, grouping.Key.TargetType, grouping.FirstOrDefault());
65+
var source = GetRoutedControlHost(grouping.Key.TargetName, grouping.Key.TargetNamespace, grouping.Key.TargetVisibility, grouping.Key.TargetType, grouping.FirstOrDefault(), input.Right);
6266
context.AddSource($"{grouping.Key.FileHintName}.RoutedControlHost.g.cs", source);
6367
}
6468
});

src/ReactiveUI.SourceGenerators.Roslyn/ViewModelControlHost/ViewModelControlHostGenerator.Execute.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,13 @@ public partial class ViewModelControlHostGenerator
7373
classAttributesInfo);
7474
}
7575

76-
private static string GetViewModelControlHost(string containingTypeName, string containingNamespace, string containingClassVisibility, string containingType, ViewModelControlHostInfo vmcInfo)
76+
private static string GetViewModelControlHost(string containingTypeName, string containingNamespace, string containingClassVisibility, string containingType, ViewModelControlHostInfo vmcInfo, bool isNewerThan22)
7777
{
7878
// Prepare any forwarded property attributes
7979
var forwardedAttributesString = string.Join("\n ", AttributeDefinitions.ExcludeFromCodeCoverage.Concat(vmcInfo.ForwardedAttributes));
80+
var exceptionHandler = isNewerThan22
81+
? "RxState.DefaultExceptionHandler!.OnNext"
82+
: "RxApp.DefaultExceptionHandler!.OnNext";
8083

8184
return
8285
$$"""
@@ -263,7 +266,7 @@ private IEnumerable<IDisposable> SetupBindings()
263266
view.ViewModel = x.ViewModel;
264267
Content = view;
265268
}
266-
}, RxApp.DefaultExceptionHandler!.OnNext);
269+
}, {{exceptionHandler}});
267270
}
268271
}
269272
}

0 commit comments

Comments
 (0)