// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using CommunityToolkit.Mvvm.SourceGenerators.Extensions; using static CommunityToolkit.Mvvm.SourceGenerators.Diagnostics.DiagnosticDescriptors; namespace CommunityToolkit.Mvvm.SourceGenerators; /// /// A source generator for the INotifyPropertyChangedAttribute type. /// [Generator] public sealed class INotifyPropertyChangedGenerator : TransitiveMembersGenerator { /// /// Initializes a new instance of the class. /// public INotifyPropertyChangedGenerator() : base("CommunityToolkit.Mvvm.ComponentModel.INotifyPropertyChangedAttribute") { } /// protected override DiagnosticDescriptor TargetTypeErrorDescriptor => INotifyPropertyChangedGeneratorError; /// protected override bool ValidateTargetType( GeneratorExecutionContext context, AttributeData attributeData, ClassDeclarationSyntax classDeclaration, INamedTypeSymbol classDeclarationSymbol, [NotNullWhen(false)] out DiagnosticDescriptor? descriptor) { INamedTypeSymbol iNotifyPropertyChangedSymbol = context.Compilation.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged")!; // Check if the type already implements INotifyPropertyChanged if (classDeclarationSymbol.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, iNotifyPropertyChangedSymbol))) { descriptor = DuplicateINotifyPropertyChangedInterfaceForINotifyPropertyChangedAttributeError; return false; } descriptor = null; return true; } /// protected override IEnumerable FilterDeclaredMembers( GeneratorExecutionContext context, AttributeData attributeData, ClassDeclarationSyntax classDeclaration, INamedTypeSymbol classDeclarationSymbol, ClassDeclarationSyntax sourceDeclaration) { // If requested, only include the event and the basic methods to raise it, but not the additional helpers if (attributeData.HasNamedArgument("IncludeAdditionalHelperMethods", false)) { return sourceDeclaration.Members.Where(static member => { return member is EventFieldDeclarationSyntax or MethodDeclarationSyntax { Identifier: { ValueText: "OnPropertyChanged" } }; }); } return sourceDeclaration.Members; } }