Skip to content

Commit 7c9958c

Browse files
committed
Add InvalidTypeForNotifyPropertyChangedRecipientsError
1 parent 302b8a9 commit 7c9958c

File tree

4 files changed

+55
-30
lines changed

4 files changed

+55
-30
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
<Compile Include="$(MSBuildThisFileDirectory)ComponentModel\ObservableValidatorValidateAllPropertiesGenerator.Execute.cs" />
4040
<Compile Include="$(MSBuildThisFileDirectory)ComponentModel\TransitiveMembersGenerator.cs" />
4141
<Compile Include="$(MSBuildThisFileDirectory)ComponentModel\TransitiveMembersGenerator.Execute.cs" />
42+
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\InvalidClassLevelNotifyPropertyChangedRecipientsAttributeAnalyzer.cs" />
4243
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\ClassUsingAttributeInsteadOfInheritanceAnalyzer.cs" />
4344
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\FieldWithOrphanedDependentObservablePropertyAttributesAnalyzer.cs" />
4445
<Compile Include="$(MSBuildThisFileDirectory)Diagnostics\Analyzers\FieldReferenceForObservablePropertyFieldAnalyzer.cs" />

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

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -555,26 +555,6 @@ private static bool TryGetIsNotifyingRecipients(
555555
return false;
556556
}
557557

558-
/// <summary>
559-
/// Checks whether a given type using <c>[NotifyPropertyChangedRecipients]</c> is valid and creates a <see cref="Diagnostic"/> if not.
560-
/// </summary>
561-
/// <param name="typeSymbol">The input <see cref="INamedTypeSymbol"/> instance to process.</param>
562-
/// <returns>The <see cref="Diagnostic"/> for <paramref name="typeSymbol"/>, if not a valid type.</returns>
563-
public static Diagnostic? GetIsNotifyingRecipientsDiagnosticForType(INamedTypeSymbol typeSymbol)
564-
{
565-
// If the containing type is valid, track it
566-
if (!typeSymbol.InheritsFromFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableRecipient") &&
567-
!typeSymbol.HasOrInheritsAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableRecipientAttribute"))
568-
{
569-
return Diagnostic.Create(
570-
InvalidTypeForNotifyPropertyChangedRecipientsError,
571-
typeSymbol.Locations.FirstOrDefault(),
572-
typeSymbol);
573-
}
574-
575-
return null;
576-
}
577-
578558
/// <summary>
579559
/// Checks whether a given generated property should also validate its value.
580560
/// </summary>

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

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,6 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
121121
static (node, _) => node is ClassDeclarationSyntax { AttributeLists.Count: > 0 },
122122
static (context, _) => (INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!);
123123

124-
// Filter only the type symbols with [NotifyPropertyChangedRecipients] and create diagnostics for them
125-
IncrementalValuesProvider<Diagnostic> notifyRecipientsErrors =
126-
classSymbols
127-
.Where(static item => item.HasAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.NotifyPropertyChangedRecipientsAttribute"))
128-
.Select(static (item, _) => Execute.GetIsNotifyingRecipientsDiagnosticForType(item))
129-
.Where(static item => item is not null)!;
130-
131-
// Output the diagnostics for [NotifyPropertyChangedRecipients]
132-
context.ReportDiagnostics(notifyRecipientsErrors);
133-
134124
// Filter only the type symbols with [NotifyDataErrorInfo] and create diagnostics for them
135125
IncrementalValuesProvider<Diagnostic> notifyDataErrorInfoErrors =
136126
classSymbols
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections.Immutable;
6+
using System.Linq;
7+
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
8+
using Microsoft.CodeAnalysis;
9+
using Microsoft.CodeAnalysis.Diagnostics;
10+
using static CommunityToolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors;
11+
12+
namespace CommunityToolkit.Mvvm.SourceGenerators;
13+
14+
/// <summary>
15+
/// A diagnostic analyzer that generates an error when a class level <c>[NotifyPropertyChangedRecipients]</c> use is detected.
16+
/// </summary>
17+
[DiagnosticAnalyzer(LanguageNames.CSharp)]
18+
public sealed class InvalidClassLevelNotifyPropertyChangedRecipientsAttributeAnalyzer : DiagnosticAnalyzer
19+
{
20+
/// <inheritdoc/>
21+
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(InvalidTypeForNotifyPropertyChangedRecipientsError);
22+
23+
/// <inheritdoc/>
24+
public override void Initialize(AnalysisContext context)
25+
{
26+
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
27+
context.EnableConcurrentExecution();
28+
29+
context.RegisterSymbolAction(static context =>
30+
{
31+
// We're looking for all class declarations
32+
if (context.Symbol is not INamedTypeSymbol { TypeKind: TypeKind.Class, IsImplicitlyDeclared: false } classSymbol)
33+
{
34+
return;
35+
}
36+
37+
// Only inspect class that are using [NotifyPropertyChangedRecipients]
38+
if (!classSymbol.HasAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.NotifyPropertyChangedRecipientsAttribute"))
39+
{
40+
return;
41+
}
42+
43+
// If the containing type is not valid, emit a diagnostic
44+
if (!classSymbol.InheritsFromFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableRecipient") &&
45+
!classSymbol.HasOrInheritsAttributeWithFullyQualifiedMetadataName("CommunityToolkit.Mvvm.ComponentModel.ObservableRecipientAttribute"))
46+
{
47+
context.ReportDiagnostic(Diagnostic.Create(
48+
InvalidTypeForNotifyPropertyChangedRecipientsError,
49+
classSymbol.Locations.FirstOrDefault(),
50+
classSymbol));
51+
}
52+
}, SymbolKind.NamedType);
53+
}
54+
}

0 commit comments

Comments
 (0)