From 03065af57a88d4d74d1bd4711213dda5884d7a1e Mon Sep 17 00:00:00 2001 From: Chris Pulman Date: Thu, 26 Sep 2024 00:55:02 +0100 Subject: [PATCH] Fix Make IViewFor use Generic type --- README.md | 6 +++--- .../IViewForTest.cs | 2 +- .../TestViewWinForms.cs | 2 +- .../TestViewWpf.cs | 2 +- .../Core/Extensions/ITypeSymbolExtensions.cs | 2 +- .../Core/Helpers/AttributeDefinitions.cs | 2 +- .../IViewFor/IViewForGenerator.cs | 15 +++++++++++++-- .../ReactiveUI.SourceGenerators.csproj | 3 +++ 8 files changed, 24 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9c9043f..2027d2b 100644 --- a/README.md +++ b/README.md @@ -304,8 +304,8 @@ public partial class MyReactiveClass ### IViewFor usage -IVIewFor is used to link a View to a ViewModel, this is used to link the ViewModel to the View in a way that ReactiveUI can use it to bind the ViewModel to the View. -The ViewModel is passed as a string to the IViewFor Attribute. +IViewFor is used to link a View to a ViewModel, this is used to link the ViewModel to the View in a way that ReactiveUI can use it to bind the ViewModel to the View. +The ViewModel is passed as a type to the IViewFor Attribute using generics. The class must inherit from a UI Control from any of the following platforms and namespaces: - Maui (Microsoft.Maui) - WinUI (Microsoft.UI.Xaml) @@ -317,7 +317,7 @@ The class must inherit from a UI Control from any of the following platforms and ```csharp using ReactiveUI.SourceGenerators; -[IViewFor(nameof(MyReactiveClass))] +[IViewFor] public partial class MyReactiveControl : UserControl { public MyReactiveControl() diff --git a/src/ReactiveUI.SourceGenerators.Execute.Maui/IViewForTest.cs b/src/ReactiveUI.SourceGenerators.Execute.Maui/IViewForTest.cs index 818f109..a142399 100644 --- a/src/ReactiveUI.SourceGenerators.Execute.Maui/IViewForTest.cs +++ b/src/ReactiveUI.SourceGenerators.Execute.Maui/IViewForTest.cs @@ -11,6 +11,6 @@ namespace SGReactiveUI.SourceGenerators.Test.Maui /// IViewForTest. /// /// - [IViewFor(nameof(TestViewModel))] + [IViewFor] public partial class IViewForTest : Shell; } diff --git a/src/ReactiveUI.SourceGenerators.Execute/TestViewWinForms.cs b/src/ReactiveUI.SourceGenerators.Execute/TestViewWinForms.cs index 5dacdb7..6abc7d7 100644 --- a/src/ReactiveUI.SourceGenerators.Execute/TestViewWinForms.cs +++ b/src/ReactiveUI.SourceGenerators.Execute/TestViewWinForms.cs @@ -11,7 +11,7 @@ namespace SGReactiveUI.SourceGenerators.Test /// TestViewWinForms. /// /// - [IViewFor(nameof(TestViewModel))] + [IViewFor] public partial class TestViewWinForms : Form { /// diff --git a/src/ReactiveUI.SourceGenerators.Execute/TestViewWpf.cs b/src/ReactiveUI.SourceGenerators.Execute/TestViewWpf.cs index b54d352..c215ab2 100644 --- a/src/ReactiveUI.SourceGenerators.Execute/TestViewWpf.cs +++ b/src/ReactiveUI.SourceGenerators.Execute/TestViewWpf.cs @@ -12,7 +12,7 @@ namespace SGReactiveUI.SourceGenerators.Test; /// /// TestView. /// -[IViewFor(nameof(TestViewModel))] +[IViewFor] public partial class TestViewWpf : Window { /// diff --git a/src/ReactiveUI.SourceGenerators/Core/Extensions/ITypeSymbolExtensions.cs b/src/ReactiveUI.SourceGenerators/Core/Extensions/ITypeSymbolExtensions.cs index 9608183..f048339 100644 --- a/src/ReactiveUI.SourceGenerators/Core/Extensions/ITypeSymbolExtensions.cs +++ b/src/ReactiveUI.SourceGenerators/Core/Extensions/ITypeSymbolExtensions.cs @@ -208,7 +208,7 @@ public static bool HasFullyQualifiedMetadataName(this ITypeSymbol symbol, string symbol.AppendFullyQualifiedMetadataName(builder); - return builder.WrittenSpan.SequenceEqual(name.AsSpan()); + return builder.WrittenSpan.StartsWith(name.AsSpan()); } public static bool ContainsFullyQualifiedMetadataName(this ITypeSymbol symbol, string name) diff --git a/src/ReactiveUI.SourceGenerators/Core/Helpers/AttributeDefinitions.cs b/src/ReactiveUI.SourceGenerators/Core/Helpers/AttributeDefinitions.cs index 1813feb..8ae6dc2 100644 --- a/src/ReactiveUI.SourceGenerators/Core/Helpers/AttributeDefinitions.cs +++ b/src/ReactiveUI.SourceGenerators/Core/Helpers/AttributeDefinitions.cs @@ -153,7 +153,7 @@ namespace ReactiveUI.SourceGenerators; /// Type of the view model. [global::System.CodeDom.Compiler.GeneratedCode("ReactiveUI.SourceGenerators.IViewForGenerator", "1.1.0.0")] [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] -internal sealed class IViewForAttribute(string? viewModelType) : Attribute; +internal sealed class IViewForAttribute : Attribute; #nullable restore #pragma warning restore """; diff --git a/src/ReactiveUI.SourceGenerators/IViewFor/IViewForGenerator.cs b/src/ReactiveUI.SourceGenerators/IViewFor/IViewForGenerator.cs index 0dfb2b8..63bbc7a 100644 --- a/src/ReactiveUI.SourceGenerators/IViewFor/IViewForGenerator.cs +++ b/src/ReactiveUI.SourceGenerators/IViewFor/IViewForGenerator.cs @@ -3,6 +3,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. +using System; using System.CodeDom.Compiler; using System.Collections.Immutable; using System.IO; @@ -57,8 +58,11 @@ public void Initialize(IncrementalGeneratorInitializationContext context) var classSymbol = symbol as INamedTypeSymbol; var classNamespace = classSymbol?.ContainingNamespace.ToString(); var className = declaredClass.Identifier.ValueText; - var constructorArgument = attributeData.GetConstructorArguments().First(); - if (constructorArgument is string viewModelTypeName) + token.ThrowIfCancellationRequested(); + + var genericArgument = GetGenericType(attributeData); + token.ThrowIfCancellationRequested(); + if (genericArgument is string viewModelTypeName && viewModelTypeName.Length > 0) { token.ThrowIfCancellationRequested(); GatherForwardedAttributes(attributeData, semanticModel, declaredClass, token, out var classAttributesInfo); @@ -193,4 +197,11 @@ static void GatherForwardedAttributes( classAttributesInfo = classAttributesInfoBuilder.ToImmutable(); } + + private static string? GetGenericType(AttributeData attributeData) + { + var success = attributeData?.AttributeClass?.ToDisplayString(); + var start = success?.IndexOf('<') + 1 ?? 0; + return success?.Substring(start, success.Length - start - 1); + } } diff --git a/src/ReactiveUI.SourceGenerators/ReactiveUI.SourceGenerators.csproj b/src/ReactiveUI.SourceGenerators/ReactiveUI.SourceGenerators.csproj index 85b821f..644422a 100644 --- a/src/ReactiveUI.SourceGenerators/ReactiveUI.SourceGenerators.csproj +++ b/src/ReactiveUI.SourceGenerators/ReactiveUI.SourceGenerators.csproj @@ -41,6 +41,9 @@ + + +