Skip to content

Commit

Permalink
Fix Make IViewFor use Generic type
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisPulman committed Sep 25, 2024
1 parent 49bf713 commit 03065af
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 10 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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<MyReactiveClass>]
public partial class MyReactiveControl : UserControl
{
public MyReactiveControl()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ namespace SGReactiveUI.SourceGenerators.Test.Maui
/// IViewForTest.
/// </summary>
/// <seealso cref="NavigationPage" />
[IViewFor(nameof(TestViewModel))]
[IViewFor<TestViewModel>]
public partial class IViewForTest : Shell;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace SGReactiveUI.SourceGenerators.Test
/// TestViewWinForms.
/// </summary>
/// <seealso cref="System.Windows.Forms.Form" />
[IViewFor(nameof(TestViewModel))]
[IViewFor<TestViewModel>]
public partial class TestViewWinForms : Form
{
/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/ReactiveUI.SourceGenerators.Execute/TestViewWpf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace SGReactiveUI.SourceGenerators.Test;
/// <summary>
/// TestView.
/// </summary>
[IViewFor(nameof(TestViewModel))]
[IViewFor<TestViewModel>]
public partial class TestViewWpf : Window
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ namespace ReactiveUI.SourceGenerators;
/// <param name="viewModelType">Type of the view model.</param>
[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<T> : Attribute;
#nullable restore
#pragma warning restore
""";
Expand Down
15 changes: 13 additions & 2 deletions src/ReactiveUI.SourceGenerators/IViewFor/IViewForGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<string>().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);
Expand Down Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<None Remove="bin\Debug\netstandard2.0\\ReactiveUI.SourceGenerators.dll" />
</ItemGroup>

<!-- This ensures the library will be packaged as a source generator when we use `dotnet pack` -->
<ItemGroup>
Expand Down

0 comments on commit 03065af

Please sign in to comment.