diff --git a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs
index 320db7f0f..3fdbf8aaa 100644
--- a/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs
+++ b/CommunityToolkit.Mvvm.SourceGenerators/ComponentModel/ObservableValidatorValidateAllPropertiesGenerator.cs
@@ -21,31 +21,43 @@ public sealed partial class ObservableValidatorValidateAllPropertiesGenerator :
///
public void Initialize(IncrementalGeneratorInitializationContext context)
{
- // Get all class declarations. We intentionally skip generating code for abstract types, as that would never be used.
- // The methods that are generated by this generator are retrieved through reflection using the type of the invoking
- // instance as discriminator, which means a type that is abstract could never be used (since it couldn't be instantiated).
- IncrementalValuesProvider typeSymbols =
+ // Get the types that inherit from ObservableValidator and gather their info
+ IncrementalValuesProvider validationInfo =
context.SyntaxProvider
.CreateSyntaxProvider(
static (node, _) => node is ClassDeclarationSyntax,
- static (context, _) =>
+ static (context, token) =>
{
if (!context.SemanticModel.Compilation.HasLanguageVersionAtLeastEqualTo(LanguageVersion.CSharp8))
{
return default;
}
- return (context.Node, Symbol: (INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!);
- })
- .Where(static item => item.Symbol is { IsAbstract: false, IsGenericType: false } && item.Node.IsFirstSyntaxDeclarationForSymbol(item.Symbol))
- .Select(static (item, _) => item.Symbol);
+ INamedTypeSymbol typeSymbol = (INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node, token)!;
- // Get the types that inherit from ObservableValidator and gather their info
- IncrementalValuesProvider validationInfo =
- typeSymbols
- .Where(Execute.IsObservableValidator)
- .Select(static (item, _) => Execute.GetInfo(item))
- .WithComparer(ValidationInfo.Comparer.Default);
+ // Skip generating code for abstract types, as that would never be used. The methods that are generated by
+ // this generator are retrieved through reflection using the type of the invoking instance as discriminator,
+ // which means a type that is abstract could never be used (since it couldn't be instantiated).
+ if (typeSymbol is not { IsAbstract: false, IsGenericType: false })
+ {
+ return default;
+ }
+
+ // Just like in IMessengerRegisterAllGenerator, only select the first declaration for this type symbol
+ if (!context.Node.IsFirstSyntaxDeclarationForSymbol(typeSymbol))
+ {
+ return default;
+ }
+
+ // Only select types inheriting from ObservableValidator
+ if (!Execute.IsObservableValidator(typeSymbol))
+ {
+ return default;
+ }
+
+ return Execute.GetInfo(typeSymbol);
+ })
+ .Where(static item => item is not null)!;
// Check whether the header file is needed
IncrementalValueProvider isHeaderFileNeeded =