Skip to content

Commit 9fc1027

Browse files
authored
Merge pull request #489 from CommunityToolkit/dev/more-optimizations
Moar source generator optimizations
2 parents a0df371 + 90b91f8 commit 9fc1027

13 files changed

+162
-163
lines changed

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/INotifyPropertyChangedGenerator.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ public INotifyPropertyChangedGenerator()
3636
INotifyPropertyChangedInfo? info = null;
3737

3838
// Check if the type already implements INotifyPropertyChanged
39-
if (typeSymbol.AllInterfaces.Any(i => i.HasFullyQualifiedName("global::System.ComponentModel.INotifyPropertyChanged")))
39+
if (typeSymbol.AllInterfaces.Any(i => i.HasFullyQualifiedMetadataName("System.ComponentModel.INotifyPropertyChanged")))
4040
{
4141
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(DuplicateINotifyPropertyChangedInterfaceForINotifyPropertyChangedAttributeError, typeSymbol, typeSymbol));
4242

4343
goto End;
4444
}
4545

4646
// Check if the type uses [INotifyPropertyChanged] or [ObservableObject] already (in the type hierarchy too)
47-
if (typeSymbol.HasOrInheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") ||
48-
typeSymbol.InheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute"))
47+
if (typeSymbol.HasOrInheritsAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") ||
48+
typeSymbol.InheritsAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute"))
4949
{
5050
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(InvalidAttributeCombinationForINotifyPropertyChangedAttributeError, typeSymbol, typeSymbol));
5151

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableObjectGenerator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,24 @@ private protected override int ValidateTargetTypeAndGetInfo(INamedTypeSymbol typ
3232
diagnostics = ImmutableArray<DiagnosticInfo>.Empty;
3333

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

3939
goto End;
4040
}
4141

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

4747
goto End;
4848
}
4949

5050
// Check if the type uses [INotifyPropertyChanged] or [ObservableObject] already (in the type hierarchy too)
51-
if (typeSymbol.InheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") ||
52-
typeSymbol.HasOrInheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute"))
51+
if (typeSymbol.InheritsAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") ||
52+
typeSymbol.HasOrInheritsAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute"))
5353
{
5454
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(InvalidAttributeCombinationForObservableObjectAttributeError, typeSymbol, typeSymbol));
5555

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.Execute.cs

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

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservablePropertyGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
124124
// Filter only the type symbols with [NotifyPropertyChangedRecipients] and create diagnostics for them
125125
IncrementalValuesProvider<Diagnostic> notifyRecipientsErrors =
126126
classSymbols
127-
.Where(static item => item.HasAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.NotifyPropertyChangedRecipientsAttribute"))
127+
.Where(static item => item.HasAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.NotifyPropertyChangedRecipientsAttribute"))
128128
.Select(static (item, _) => Execute.GetIsNotifyingRecipientsDiagnosticForType(item))
129129
.Where(static item => item is not null)!;
130130

@@ -134,7 +134,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
134134
// Filter only the type symbols with [NotifyDataErrorInfo] and create diagnostics for them
135135
IncrementalValuesProvider<Diagnostic> notifyDataErrorInfoErrors =
136136
classSymbols
137-
.Where(static item => item.HasAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.NotifyDataErrorInfoAttribute"))
137+
.Where(static item => item.HasAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.NotifyDataErrorInfoAttribute"))
138138
.Select(static (item, _) => Execute.GetIsNotifyDataErrorInfoDiagnosticForType(item))
139139
.Where(static item => item is not null)!;
140140

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableRecipientGenerator.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ public ObservableRecipientGenerator()
3838
ObservableRecipientInfo? info = null;
3939

4040
// Check if the type already inherits from ObservableRecipient
41-
if (typeSymbol.InheritsFromFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableRecipient"))
41+
if (typeSymbol.InheritsFromFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableRecipient"))
4242
{
4343
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(DuplicateObservableRecipientError, typeSymbol, typeSymbol));
4444

4545
goto End;
4646
}
4747

4848
// Check if the type already inherits [ObservableRecipient]
49-
if (typeSymbol.InheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableRecipientAttribute"))
49+
if (typeSymbol.InheritsAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableRecipientAttribute"))
5050
{
5151
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(InvalidAttributeCombinationForObservableRecipientAttributeError, typeSymbol, typeSymbol));
5252

@@ -55,10 +55,10 @@ public ObservableRecipientGenerator()
5555

5656
// In order to use [ObservableRecipient], the target type needs to inherit from ObservableObject,
5757
// or be annotated with [ObservableObject] or [INotifyPropertyChanged] (with additional helpers).
58-
if (!typeSymbol.InheritsFromFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableObject") &&
59-
!typeSymbol.HasOrInheritsAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") &&
58+
if (!typeSymbol.InheritsFromFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableObject") &&
59+
!typeSymbol.HasOrInheritsAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableObjectAttribute") &&
6060
!typeSymbol.HasOrInheritsAttribute(static a =>
61-
a.AttributeClass?.HasFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute") == true &&
61+
a.AttributeClass?.HasFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute") == true &&
6262
!a.HasNamedArgument("IncludeAdditionalHelperMethods", false)))
6363
{
6464
diagnostics = ImmutableArray.Create(DiagnosticInfo.Create(MissingBaseObservableObjectFunctionalityError, typeSymbol, typeSymbol));
@@ -70,7 +70,7 @@ public ObservableRecipientGenerator()
7070
string typeName = typeSymbol.Name;
7171
bool hasExplicitConstructors = !(typeSymbol.InstanceConstructors.Length == 1 && typeSymbol.InstanceConstructors[0] is { Parameters.IsEmpty: true, IsImplicitlyDeclared: true });
7272
bool isAbstract = typeSymbol.IsAbstract;
73-
bool isObservableValidator = typeSymbol.InheritsFromFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableValidator");
73+
bool isObservableValidator = typeSymbol.InheritsFromFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableValidator");
7474
bool isRequiresUnreferencedCodeAttributeAvailable = compilation.HasAccessibleTypeWithMetadataName("System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute");
7575
bool hasOnActivatedMethod = typeSymbol.GetMembers().Any(m => m is IMethodSymbol { Parameters.IsEmpty: true, Name: "OnActivated" });
7676
bool hasOnDeactivatedMethod = typeSymbol.GetMembers().Any(m => m is IMethodSymbol { Parameters.IsEmpty: true, Name: "OnDeactivated" });

CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.Execute.cs

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using CommunityToolkit.Mvvm.SourceGenerators.ComponentModel.Models;
99
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
1010
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
11-
using CommunityToolkit.Mvvm.SourceGenerators.Messaging.Models;
1211
using Microsoft.CodeAnalysis;
1312
using Microsoft.CodeAnalysis.CSharp;
1413
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -31,7 +30,7 @@ private static class Execute
3130
/// <returns>Whether <paramref name="typeSymbol"/> inherits from <c>ObservableValidator</c>.</returns>
3231
public static bool IsObservableValidator(INamedTypeSymbol typeSymbol)
3332
{
34-
return typeSymbol.InheritsFromFullyQualifiedName("global::CommunityToolkit.Mvvm.ComponentModel.ObservableValidator");
33+
return typeSymbol.InheritsFromFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableValidator");
3534
}
3635

3736
/// <summary>
@@ -56,15 +55,15 @@ public static ValidationInfo GetInfo(INamedTypeSymbol typeSymbol)
5655
// all generators run in an undefined order and looking at the same original compilation, so the
5756
// current one wouldn't be able to see generated properties from other generators directly.
5857
if (memberSymbol is IFieldSymbol &&
59-
!attributes.Any(static a => a.AttributeClass?.HasFullyQualifiedName(
60-
"global::CommunityToolkit.Mvvm.ComponentModel.ObservablePropertyAttribute") == true))
58+
!attributes.Any(static a => a.AttributeClass?.HasFullyQualifiedMetadataName(
59+
"CommunityToolkit.Mvvm.ComponentModel.ObservablePropertyAttribute") == true))
6160
{
6261
continue;
6362
}
6463

6564
// Skip the current member if there are no validation attributes applied to it
66-
if (!attributes.Any(a => a.AttributeClass?.InheritsFromFullyQualifiedName(
67-
"global::System.ComponentModel.DataAnnotations.ValidationAttribute") == true))
65+
if (!attributes.Any(a => a.AttributeClass?.InheritsFromFullyQualifiedMetadataName(
66+
"System.ComponentModel.DataAnnotations.ValidationAttribute") == true))
6867
{
6968
continue;
7069
}
@@ -81,32 +80,11 @@ public static ValidationInfo GetInfo(INamedTypeSymbol typeSymbol)
8180
}
8281

8382
return new(
84-
typeSymbol.GetFullMetadataNameForFileName(),
83+
typeSymbol.GetFullyQualifiedMetadataName(),
8584
typeSymbol.GetFullyQualifiedName(),
8685
propertyNames.ToImmutable());
8786
}
8887

89-
/// <summary>
90-
/// Gets the <see cref="RecipientInfo"/> instance from the given info.
91-
/// </summary>
92-
/// <param name="typeSymbol">The type symbol for the target type being inspected.</param>
93-
/// <param name="interfaceSymbols">The input array of interface type symbols being handled.</param>
94-
/// <returns>A <see cref="RecipientInfo"/> instance for the current type being inspected.</returns>
95-
public static RecipientInfo GetInfo(INamedTypeSymbol typeSymbol, ImmutableArray<INamedTypeSymbol> interfaceSymbols)
96-
{
97-
using ImmutableArrayBuilder<string> names = ImmutableArrayBuilder<string>.Rent();
98-
99-
foreach (INamedTypeSymbol interfaceSymbol in interfaceSymbols)
100-
{
101-
names.Add(interfaceSymbol.TypeArguments[0].GetFullyQualifiedName());
102-
}
103-
104-
return new(
105-
typeSymbol.GetFullMetadataNameForFileName(),
106-
typeSymbol.GetFullyQualifiedName(),
107-
names.ToImmutable());
108-
}
109-
11088
/// <summary>
11189
/// Gets the head <see cref="CompilationUnitSyntax"/> instance.
11290
/// </summary>

CommunityToolkit.Mvvm.SourceGenerators/Extensions/INamedTypeSymbolExtensions.cs

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
using System;
65
using System.Collections.Generic;
7-
using System.Text;
8-
using CommunityToolkit.Mvvm.SourceGenerators.Helpers;
96
using Microsoft.CodeAnalysis;
107

118
namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
@@ -15,55 +12,6 @@ namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
1512
/// </summary>
1613
internal static class INamedTypeSymbolExtensions
1714
{
18-
/// <summary>
19-
/// Gets a valid filename for a given <see cref="INamedTypeSymbol"/> instance.
20-
/// </summary>
21-
/// <param name="symbol">The input <see cref="INamedTypeSymbol"/> instance.</param>
22-
/// <returns>The full metadata name for <paramref name="symbol"/> that is also a valid filename.</returns>
23-
public static string GetFullMetadataNameForFileName(this INamedTypeSymbol symbol)
24-
{
25-
using ImmutableArrayBuilder<char> builder = ImmutableArrayBuilder<char>.Rent();
26-
27-
static void BuildFrom(ISymbol? symbol, in ImmutableArrayBuilder<char> builder)
28-
{
29-
switch (symbol)
30-
{
31-
// Namespaces that are nested also append a leading '.'
32-
case INamespaceSymbol { ContainingNamespace.IsGlobalNamespace: false }:
33-
BuildFrom(symbol.ContainingNamespace, in builder);
34-
builder.Add('.');
35-
builder.AddRange(symbol.MetadataName.AsSpan());
36-
break;
37-
// Other namespaces (ie. the one right before global) skip the leading '.'
38-
case INamespaceSymbol { IsGlobalNamespace: false }:
39-
builder.AddRange(symbol.MetadataName.AsSpan());
40-
break;
41-
// Types with no namespace just have their metadata name directly written
42-
case ITypeSymbol { ContainingSymbol: INamespaceSymbol { IsGlobalNamespace: true } }:
43-
builder.AddRange(symbol.MetadataName.AsSpan());
44-
break;
45-
// Types with a containing non-global namespace also append a leading '.'
46-
case ITypeSymbol { ContainingSymbol: INamespaceSymbol namespaceSymbol }:
47-
BuildFrom(namespaceSymbol, in builder);
48-
builder.Add('.');
49-
builder.AddRange(symbol.MetadataName.AsSpan());
50-
break;
51-
// Nested types append a leading '+'
52-
case ITypeSymbol { ContainingSymbol: ITypeSymbol typeSymbol }:
53-
BuildFrom(typeSymbol, in builder);
54-
builder.Add('+');
55-
builder.AddRange(symbol.MetadataName.AsSpan());
56-
break;
57-
default:
58-
break;
59-
}
60-
}
61-
62-
BuildFrom(symbol, in builder);
63-
64-
return builder.ToString();
65-
}
66-
6715
/// <summary>
6816
/// Gets all member symbols from a given <see cref="INamedTypeSymbol"/> instance, including inherited ones.
6917
/// </summary>

CommunityToolkit.Mvvm.SourceGenerators/Extensions/ISymbolExtensions.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,18 @@ public static bool HasFullyQualifiedName(this ISymbol symbol, string name)
4747
}
4848

4949
/// <summary>
50-
/// Checks whether or not a given symbol has an attribute with the specified full name.
50+
/// Checks whether or not a given symbol has an attribute with the specified fully qualified metadata name.
5151
/// </summary>
5252
/// <param name="symbol">The input <see cref="ISymbol"/> instance to check.</param>
5353
/// <param name="name">The attribute name to look for.</param>
5454
/// <returns>Whether or not <paramref name="symbol"/> has an attribute with the specified name.</returns>
55-
public static bool HasAttributeWithFullyQualifiedName(this ISymbol symbol, string name)
55+
public static bool HasAttributeWithFullyQualifiedMetadataName(this ISymbol symbol, string name)
5656
{
5757
ImmutableArray<AttributeData> attributes = symbol.GetAttributes();
5858

5959
foreach (AttributeData attribute in attributes)
6060
{
61-
if (attribute.AttributeClass?.HasFullyQualifiedName(name) == true)
61+
if (attribute.AttributeClass?.HasFullyQualifiedMetadataName(name) == true)
6262
{
6363
return true;
6464
}
@@ -69,19 +69,19 @@ public static bool HasAttributeWithFullyQualifiedName(this ISymbol symbol, strin
6969

7070
#if !ROSLYN_4_3_1_OR_GREATER
7171
/// <summary>
72-
/// Tries to get an attribute with the specified full name.
72+
/// Tries to get an attribute with the specified fully qualified metadata name.
7373
/// </summary>
7474
/// <param name="symbol">The input <see cref="ISymbol"/> instance to check.</param>
7575
/// <param name="name">The attribute name to look for.</param>
7676
/// <param name="attributeData">The resulting attribute, if it was found.</param>
7777
/// <returns>Whether or not <paramref name="symbol"/> has an attribute with the specified name.</returns>
78-
public static bool TryGetAttributeWithFullyQualifiedName(this ISymbol symbol, string name, [NotNullWhen(true)] out AttributeData? attributeData)
78+
public static bool TryGetAttributeWithFullyQualifiedMetadataName(this ISymbol symbol, string name, [NotNullWhen(true)] out AttributeData? attributeData)
7979
{
8080
ImmutableArray<AttributeData> attributes = symbol.GetAttributes();
8181

8282
foreach (AttributeData attribute in attributes)
8383
{
84-
if (attribute.AttributeClass?.HasFullyQualifiedName(name) == true)
84+
if (attribute.AttributeClass?.HasFullyQualifiedMetadataName(name) == true)
8585
{
8686
attributeData = attribute;
8787

0 commit comments

Comments
 (0)