Skip to content

Commit d1f7ef9

Browse files
committed
Move partial filtering logic to new extension
1 parent 61539a2 commit d1f7ef9

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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 Microsoft.CodeAnalysis;
6+
7+
namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
8+
9+
/// <summary>
10+
/// Extension methods for the <see cref="SyntaxNode"/> type.
11+
/// </summary>
12+
internal static class SyntaxNodeExtensions
13+
{
14+
/// <summary>
15+
/// Checks whether a given <see cref="SyntaxNode"/> represents the first (partial) declaration of a given symbol.
16+
/// </summary>
17+
/// <param name="syntaxNode">The input <see cref="SyntaxNode"/> instance.</param>
18+
/// <param name="symbol">The target <see cref="ISymbol"/> instance to check the syntax declaration for.</param>
19+
/// <returns>Whether <paramref name="syntaxNode"/> is the first (partial) declaration for <paramref name="symbol"/>.</returns>
20+
/// <remarks>
21+
/// This extension can be used to avoid accidentally generating repeated members for types that have multiple partial declarations.
22+
/// In order to keep this check efficient and without the need to collect all items and build some sort of hashset from them to
23+
/// remove duplicates, each syntax node is symply compared against the available declaring syntax references for the target symbol.
24+
/// If the syntax node matches the first syntax reference for the symbol, it is kept, otherwise it is considered a duplicate.
25+
/// </remarks>
26+
public static bool IsFirstSyntaxDeclarationForSymbol(this SyntaxNode syntaxNode, ISymbol symbol)
27+
{
28+
return
29+
symbol.DeclaringSyntaxReferences.Length > 0 &&
30+
symbol.DeclaringSyntaxReferences[0] is SyntaxReference syntaxReference &&
31+
syntaxReference.SyntaxTree == syntaxNode.SyntaxTree &&
32+
syntaxReference.Span == syntaxNode.Span;
33+
}
34+
}

CommunityToolkit.Mvvm.SourceGenerators/Messaging/IMessengerRegisterAllGenerator.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44

55
using System.Collections.Immutable;
66
using System.Linq;
7-
using System.Text;
87
using CommunityToolkit.Mvvm.SourceGenerators.Extensions;
98
using CommunityToolkit.Mvvm.SourceGenerators.Input.Models;
109
using Microsoft.CodeAnalysis;
1110
using Microsoft.CodeAnalysis.CSharp;
1211
using Microsoft.CodeAnalysis.CSharp.Syntax;
13-
using Microsoft.CodeAnalysis.Text;
1412

1513
namespace CommunityToolkit.Mvvm.SourceGenerators;
1614

@@ -32,11 +30,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
3230
.CreateSyntaxProvider(
3331
static (node, _) => node is ClassDeclarationSyntax,
3432
static (context, _) => (context.Node, Symbol: (INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!))
35-
.Where(static item =>
36-
item.Symbol.DeclaringSyntaxReferences.Length > 0 &&
37-
item.Symbol.DeclaringSyntaxReferences[0] is SyntaxReference syntaxReference &&
38-
syntaxReference.SyntaxTree == item.Node.SyntaxTree &&
39-
syntaxReference.Span == item.Node.Span)
33+
.Where(static item => item.Node.IsFirstSyntaxDeclarationForSymbol(item.Symbol))
4034
.Select(static (item, _) => item.Symbol);
4135

4236
// Get the target IRecipient<TMessage> interfaces and filter out other types

0 commit comments

Comments
 (0)