Skip to content

Commit 45795f2

Browse files
authored
Merge pull request #460 from CommunityToolkit/dev/generator-improvements
More MVVM Toolkit generator improvements
2 parents a8fd1db + 66dee36 commit 45795f2

25 files changed

+644
-185
lines changed

CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.projitems

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@
5454
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\UnsupportedCSharpLanguageVersionAnalyzer.cs" />
5555
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Suppressors\ObservablePropertyAttributeWithPropertyTargetDiagnosticSuppressor.cs" />
5656
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\DiagnosticDescriptors.cs" />
57-
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\DiagnosticExtensions.cs" />
5857
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\SuppressionDescriptors.cs" />
5958
<Compile Include="$(MSBuildThisFileDirectory)Extensions\AttributeDataExtensions.cs" />
6059
<Compile Include="$(MSBuildThisFileDirectory)Extensions\CompilationExtensions.cs" />
60+
<Compile Include="$(MSBuildThisFileDirectory)Extensions\DiagnosticsExtensions.cs" />
6161
<Compile Include="$(MSBuildThisFileDirectory)Extensions\HashCodeExtensions.cs" />
6262
<Compile Include="$(MSBuildThisFileDirectory)Extensions\IEqualityComparerExtensions.cs" />
6363
<Compile Include="$(MSBuildThisFileDirectory)Extensions\INamedTypeSymbolExtensions.cs" />
@@ -70,13 +70,16 @@
7070
<Compile Include="$(MSBuildThisFileDirectory)Extensions\TypeDeclarationSyntaxExtensions.cs" />
7171
<Compile Include="$(MSBuildThisFileDirectory)Helpers\Comparer{T,TSelf}.cs" />
7272
<Compile Include="$(MSBuildThisFileDirectory)Helpers\HashCode.cs" />
73+
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ImmutableArrayBuilder{T}.cs" />
74+
<Compile Include="$(MSBuildThisFileDirectory)Helpers\ObjectPool{T}.cs" />
7375
<Compile Include="$(MSBuildThisFileDirectory)Input\Models\CanExecuteExpressionType.cs" />
7476
<Compile Include="$(MSBuildThisFileDirectory)Input\Models\CommandInfo.cs" />
7577
<Compile Include="$(MSBuildThisFileDirectory)Input\RelayCommandGenerator.cs" />
7678
<Compile Include="$(MSBuildThisFileDirectory)Input\RelayCommandGenerator.Execute.cs" />
7779
<Compile Include="$(MSBuildThisFileDirectory)Messaging\IMessengerRegisterAllGenerator.cs" />
7880
<Compile Include="$(MSBuildThisFileDirectory)Messaging\IMessengerRegisterAllGenerator.Execute.cs" />
7981
<Compile Include="$(MSBuildThisFileDirectory)Messaging\Models\RecipientInfo.cs" />
82+
<Compile Include="$(MSBuildThisFileDirectory)Models\DiagnosticInfo.cs" />
8083
<Compile Include="$(MSBuildThisFileDirectory)Models\HierarchyInfo.cs" />
8184
<Compile Include="$(MSBuildThisFileDirectory)Models\HierarchyInfo.Syntax.cs" />
8285
<Compile Include="$(MSBuildThisFileDirectory)Models\Result.cs" />

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/INotifyPropertyChangedGenerator.cs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
using System.Collections.Immutable;
66
using System.Linq;
7-
using CommunityToolkit.Mvvm.SourceGenerators.Diagnostics;
87
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
8+
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
99
using CommunityToolkit.Mvvm.SourceGenerators.Input.Models;
10+
using CommunityToolkit.Mvvm.SourceGenerators.Models;
1011
using Microsoft.CodeAnalysis;
1112
using Microsoft.CodeAnalysis.CSharp.Syntax;
1213
using static CommunityToolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
@@ -28,16 +29,16 @@ public INotifyPropertyChangedGenerator()
2829
}
2930

3031
/// <inheritdoc/>
31-
protected override INotifyPropertyChangedInfo? ValidateTargetTypeAndGetInfo(INamedTypeSymbol typeSymbol, AttributeData attributeData, Compilation compilation, out ImmutableArray<Diagnostic> diagnostics)
32+
private protected override INotifyPropertyChangedInfo? ValidateTargetTypeAndGetInfo(INamedTypeSymbol typeSymbol, AttributeData attributeData, Compilation compilation, out ImmutableArray<DiagnosticInfo> diagnostics)
3233
{
33-
ImmutableArray<Diagnostic>.Builder builder = ImmutableArray.CreateBuilder<Diagnostic>();
34+
diagnostics = ImmutableArray<DiagnosticInfo>.Empty;
3435

3536
INotifyPropertyChangedInfo? info = null;
3637

3738
// Check if the type already implements INotifyPropertyChanged
3839
if (typeSymbol.AllInterfaces.Any(i => i.HasFullyQualifiedName("global::System.ComponentModel.INotifyPropertyChanged")))
3940
{
40-
builder.Add(DuplicateINotifyPropertyChangedInterfaceForINotifyPropertyChangedAttributeError, typeSymbol, typeSymbol);
41+
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(DuplicateINotifyPropertyChangedInterfaceForINotifyPropertyChangedAttributeError, typeSymbol, typeSymbol));
4142

4243
goto End;
4344
}
@@ -46,7 +47,7 @@ public INotifyPropertyChangedGenerator()
4647
if (typeSymbol.HasOrInheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") ||
4748
typeSymbol.InheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute"))
4849
{
49-
builder.Add(InvalidAttributeCombinationForINotifyPropertyChangedAttributeError, typeSymbol, typeSymbol);
50+
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(InvalidAttributeCombinationForINotifyPropertyChangedAttributeError, typeSymbol, typeSymbol));
5051

5152
goto End;
5253
}
@@ -56,8 +57,6 @@ public INotifyPropertyChangedGenerator()
5657
info = new INotifyPropertyChangedInfo(includeAdditionalHelperMethods);
5758

5859
End:
59-
diagnostics = builder.ToImmutable();
60-
6160
return info;
6261
}
6362

@@ -67,9 +66,17 @@ protected override ImmutableArray<MemberDeclarationSyntax> FilterDeclaredMembers
6766
// If requested, only include the event and the basic methods to raise it, but not the additional helpers
6867
if (!info.IncludeAdditionalHelperMethods)
6968
{
70-
return memberDeclarations.Where(static member => member
71-
is EventFieldDeclarationSyntax
72-
or MethodDeclarationSyntax { Identifier.ValueText: "OnPropertyChanged" }).ToImmutableArray();
69+
using ImmutableArrayBuilder<MemberDeclarationSyntax> selectedMembers = ImmutableArrayBuilder<MemberDeclarationSyntax>.Rent();
70+
71+
foreach (MemberDeclarationSyntax memberDeclaration in memberDeclarations)
72+
{
73+
if (memberDeclaration is EventFieldDeclarationSyntax or MethodDeclarationSyntax { Identifier.ValueText: "OnPropertyChanged" })
74+
{
75+
selectedMembers.Add(memberDeclaration);
76+
}
77+
}
78+
79+
return selectedMembers.ToImmutable();
7380
}
7481

7582
return memberDeclarations;

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/AttributeInfo.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,24 @@ public static AttributeInfo From(AttributeData attributeData)
3232
{
3333
string typeName = attributeData.AttributeClass!.GetFullyQualifiedName();
3434

35+
using ImmutableArrayBuilder<TypedConstantInfo> constructorArguments = ImmutableArrayBuilder<TypedConstantInfo>.Rent();
36+
using ImmutableArrayBuilder<(string, TypedConstantInfo)> namedArguments = ImmutableArrayBuilder<(string, TypedConstantInfo)>.Rent();
37+
3538
// Get the constructor arguments
36-
ImmutableArray<TypedConstantInfo> constructorArguments =
37-
attributeData.ConstructorArguments
38-
.Select(TypedConstantInfo.From)
39-
.ToImmutableArray();
39+
foreach (TypedConstant typedConstant in attributeData.ConstructorArguments)
40+
{
41+
constructorArguments.Add(TypedConstantInfo.From(typedConstant));
42+
}
4043

4144
// Get the named arguments
42-
ImmutableArray<(string, TypedConstantInfo)>.Builder namedArguments = ImmutableArray.CreateBuilder<(string, TypedConstantInfo)>();
43-
44-
foreach (KeyValuePair<string, TypedConstant> arg in attributeData.NamedArguments)
45+
foreach (KeyValuePair<string, TypedConstant> namedConstant in attributeData.NamedArguments)
4546
{
46-
namedArguments.Add((arg.Key, TypedConstantInfo.From(arg.Value)));
47+
namedArguments.Add((namedConstant.Key, TypedConstantInfo.From(namedConstant.Value)));
4748
}
4849

4950
return new(
5051
typeName,
51-
constructorArguments,
52+
constructorArguments.ToImmutable(),
5253
namedArguments.ToImmutable());
5354
}
5455

@@ -64,8 +65,8 @@ public static AttributeInfo From(INamedTypeSymbol typeSymbol, SemanticModel sema
6465
{
6566
string typeName = typeSymbol.GetFullyQualifiedName();
6667

67-
ImmutableArray<TypedConstantInfo>.Builder constructorArguments = ImmutableArray.CreateBuilder<TypedConstantInfo>();
68-
ImmutableArray<(string, TypedConstantInfo)>.Builder namedArguments = ImmutableArray.CreateBuilder<(string, TypedConstantInfo)>();
68+
using ImmutableArrayBuilder<TypedConstantInfo> constructorArguments = ImmutableArrayBuilder<TypedConstantInfo>.Rent();
69+
using ImmutableArrayBuilder<(string, TypedConstantInfo)> namedArguments = ImmutableArrayBuilder<(string, TypedConstantInfo)>.Rent();
6970

7071
foreach (AttributeArgumentSyntax argument in arguments)
7172
{

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/TypedConstantInfo.Factory.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Collections.Immutable;
77
using System.Linq;
88
using System.Threading;
9+
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
910
using Microsoft.CodeAnalysis;
1011
using Microsoft.CodeAnalysis.CSharp.Syntax;
1112
using Microsoft.CodeAnalysis.Operations;
@@ -127,7 +128,7 @@ public static TypedConstantInfo From(
127128
return new Array(elementTypeName, ImmutableArray<TypedConstantInfo>.Empty);
128129
}
129130

130-
ImmutableArray<TypedConstantInfo>.Builder items = ImmutableArray.CreateBuilder<TypedConstantInfo>(initializerExpression.Expressions.Count);
131+
using ImmutableArrayBuilder<TypedConstantInfo> items = ImmutableArrayBuilder<TypedConstantInfo>.Rent();
131132

132133
// Enumerate all array elements and extract serialized info for them
133134
foreach (ExpressionSyntax initializationExpression in initializerExpression.Expressions)
@@ -140,7 +141,7 @@ public static TypedConstantInfo From(
140141
items.Add(From(initializationOperation, semanticModel, initializationExpression, token));
141142
}
142143

143-
return new Array(elementTypeName, items.MoveToImmutable());
144+
return new Array(elementTypeName, items.ToImmutable());
144145
}
145146

146147
throw new ArgumentException("Invalid attribute argument value");

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/Models/ValidationInfo.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,16 @@ internal sealed record ValidationInfo(
2222
string TypeName,
2323
ImmutableArray<string> PropertyNames)
2424
{
25+
/// <inheritdoc/>
26+
public bool Equals(ValidationInfo? obj) => Comparer.Default.Equals(this, obj);
27+
28+
/// <inheritdoc/>
29+
public override int GetHashCode() => Comparer.Default.GetHashCode(this);
30+
2531
/// <summary>
2632
/// An <see cref="IEqualityComparer{T}"/> implementation for <see cref="ValidationInfo"/>.
2733
/// </summary>
28-
public sealed class Comparer : Comparer<ValidationInfo, Comparer>
34+
private sealed class Comparer : Comparer<ValidationInfo, Comparer>
2935
{
3036
/// <inheritdoc/>
3137
protected override void AddToHashCode(ref HashCode hashCode, ValidationInfo obj)

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableObjectGenerator.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
using System.Collections.Immutable;
66
using System.Linq;
7-
using CommunityToolkit.Mvvm.SourceGenerators.Diagnostics;
87
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
8+
using CommunityToolkit.Mvvm.SourceGenerators.Models;
99
using Microsoft.CodeAnalysis;
1010
using Microsoft.CodeAnalysis.CSharp.Syntax;
1111
using static CommunityToolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
@@ -27,22 +27,22 @@ public ObservableObjectGenerator()
2727
}
2828

2929
/// <inheritdoc/>
30-
protected override object? ValidateTargetTypeAndGetInfo(INamedTypeSymbol typeSymbol, AttributeData attributeData, Compilation compilation, out ImmutableArray<Diagnostic> diagnostics)
30+
private protected override object? ValidateTargetTypeAndGetInfo(INamedTypeSymbol typeSymbol, AttributeData attributeData, Compilation compilation, out ImmutableArray<DiagnosticInfo> diagnostics)
3131
{
32-
ImmutableArray<Diagnostic>.Builder builder = ImmutableArray.CreateBuilder<Diagnostic>();
32+
diagnostics = ImmutableArray<DiagnosticInfo>.Empty;
3333

3434
// Check if the type already implements INotifyPropertyChanged...
3535
if (typeSymbol.AllInterfaces.Any(i => i.HasFullyQualifiedName("global::System.ComponentModel.INotifyPropertyChanged")))
3636
{
37-
builder.Add(DuplicateINotifyPropertyChangedInterfaceForObservableObjectAttributeError, typeSymbol, typeSymbol);
37+
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(DuplicateINotifyPropertyChangedInterfaceForObservableObjectAttributeError, typeSymbol, typeSymbol));
3838

3939
goto End;
4040
}
4141

4242
// ...or INotifyPropertyChanging
4343
if (typeSymbol.AllInterfaces.Any(i => i.HasFullyQualifiedName("global::System.ComponentModel.INotifyPropertyChanging")))
4444
{
45-
builder.Add(DuplicateINotifyPropertyChangingInterfaceForObservableObjectAttributeError, typeSymbol, typeSymbol);
45+
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(DuplicateINotifyPropertyChangingInterfaceForObservableObjectAttributeError, typeSymbol, typeSymbol));
4646

4747
goto End;
4848
}
@@ -51,14 +51,12 @@ public ObservableObjectGenerator()
5151
if (typeSymbol.InheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") ||
5252
typeSymbol.HasOrInheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute"))
5353
{
54-
builder.Add(InvalidAttributeCombinationForObservableObjectAttributeError, typeSymbol, typeSymbol);
54+
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(InvalidAttributeCombinationForObservableObjectAttributeError, typeSymbol, typeSymbol));
5555

5656
goto End;
5757
}
5858

5959
End:
60-
diagnostics = builder.ToImmutable();
61-
6260
return null;
6361
}
6462

0 commit comments

Comments
 (0)