Skip to content

Commit 73ebfb5

Browse files
committed
Don't propagate symbols in IMessengerRegisterAllGenerator
1 parent bf98ede commit 73ebfb5

File tree

1 file changed

+31
-21
lines changed

1 file changed

+31
-21
lines changed

CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,37 +22,46 @@ public sealed partial class IMessengerRegisterAllGenerator : IIncrementalGenerat
2222
/// <inheritdoc/>
2323
public void Initialize(IncrementalGeneratorInitializationContext context)
2424
{
25-
// Get all class declarations. This pipeline step also needs to filter out duplicate recipient
26-
// definitions (it might happen if a recipient has partial declarations). To do this, all pairs
27-
// of class declarations and associated symbols are gathered, and then only the pair where the
28-
// class declaration is the first syntax reference for the associated symbol is kept.
29-
// Just like with the ObservableValidator generator, we also intentionally skip abstract types.
30-
IncrementalValuesProvider<INamedTypeSymbol> typeSymbols =
25+
// Get the recipient info for all target types
26+
IncrementalValuesProvider<RecipientInfo> recipientInfo =
3127
context.SyntaxProvider
3228
.CreateSyntaxProvider(
3329
static (node, _) => node is ClassDeclarationSyntax,
34-
static (context, _) =>
30+
static (context, token) =>
3531
{
3632
if (!context.SemanticModel.Compilation.HasLanguageVersionAtLeastEqualTo(LanguageVersion.CSharp8))
3733
{
3834
return default;
3935
}
4036

41-
return (context.Node, Symbol: (INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!);
42-
})
43-
.Where(static item => item.Symbol is { IsAbstract: false, IsGenericType: false } && item.Node.IsFirstSyntaxDeclarationForSymbol(item.Symbol))
44-
.Select(static (item, _) => item.Symbol);
37+
INamedTypeSymbol typeSymbol = (INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node, token)!;
4538

46-
// Get the target IRecipient<TMessage> interfaces and filter out other types
47-
IncrementalValuesProvider<(INamedTypeSymbol Type, ImmutableArray<INamedTypeSymbol> Interfaces)> typeAndInterfaceSymbols =
48-
typeSymbols
49-
.Select(static (item, _) => (item, Interfaces: Execute.GetInterfaces(item)))
50-
.Where(static item => !item.Interfaces.IsEmpty);
39+
// The type must be a non-abstract, non-generic type (just like with the ObservableValidator generator)
40+
if (typeSymbol is not { IsAbstract: false, IsGenericType: false })
41+
{
42+
return default;
43+
}
5144

52-
// Get the recipient info for all target types
53-
IncrementalValuesProvider<RecipientInfo> recipientInfo =
54-
typeAndInterfaceSymbols
55-
.Select(static (item, _) => Execute.GetInfo(item.Type, item.Interfaces))
45+
// This pipeline step also needs to filter out duplicate recipient definitions (it might happen if a
46+
// recipient has partial declarations). To do this, all pairs of class declarations and associated
47+
// symbols are gathered, and then only the pair where the class declaration is the first syntax
48+
// reference for the associated symbol is kept.
49+
if (!context.Node.IsFirstSyntaxDeclarationForSymbol(typeSymbol))
50+
{
51+
return default;
52+
}
53+
54+
ImmutableArray<INamedTypeSymbol> interfaceSymbols = Execute.GetInterfaces(typeSymbol);
55+
56+
// Check that the type implements at least one IRecipient<TMessage> interface
57+
if (interfaceSymbols.IsEmpty)
58+
{
59+
return default;
60+
}
61+
62+
return Execute.GetInfo(typeSymbol, interfaceSymbols);
63+
})
64+
.Where(static item => item is not null)!
5665
.WithComparer(RecipientInfo.Comparer.Default);
5766

5867
// Check whether the header file is needed
@@ -68,7 +77,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
6877

6978
// Gather the conditional flag and attribute availability
7079
IncrementalValueProvider<(bool IsHeaderFileNeeded, bool IsDynamicallyAccessedMembersAttributeAvailable)> headerFileInfo =
71-
isHeaderFileNeeded.Combine(isDynamicallyAccessedMembersAttributeAvailable);
80+
isHeaderFileNeeded
81+
.Combine(isDynamicallyAccessedMembersAttributeAvailable);
7282

7383
// Generate the header file with the attributes
7484
context.RegisterConditionalImplementationSourceOutput(headerFileInfo, static (context, item) =>

0 commit comments

Comments
 (0)