mirror of
https://github.com/CommunityToolkit/dotnet.git
synced 2026-10-19 05:31:42 +08:00
Don't propagate symbols in RelayCommandGenerator
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
|
||||
@@ -64,6 +65,32 @@ internal static class ISymbolExtensions
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get an attribute with the specified full name.
|
||||
/// </summary>
|
||||
/// <param name="symbol">The input <see cref="ISymbol"/> instance to check.</param>
|
||||
/// <param name="name">The attribute name to look for.</param>
|
||||
/// <param name="attributeData">The resulting attribute, if it was found.</param>
|
||||
/// <returns>Whether or not <paramref name="symbol"/> has an attribute with the specified name.</returns>
|
||||
public static bool TryGetAttributeWithFullyQualifiedName(this ISymbol symbol, string name, [NotNullWhen(true)] out AttributeData? attributeData)
|
||||
{
|
||||
ImmutableArray<AttributeData> attributes = symbol.GetAttributes();
|
||||
|
||||
foreach (AttributeData attribute in attributes)
|
||||
{
|
||||
if (attribute.AttributeClass?.HasFullyQualifiedName(name) == true)
|
||||
{
|
||||
attributeData = attribute;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
attributeData = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates the effective accessibility for a given symbol.
|
||||
/// </summary>
|
||||
|
||||
@@ -23,40 +23,33 @@ public sealed partial class RelayCommandGenerator : IIncrementalGenerator
|
||||
/// <inheritdoc/>
|
||||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||||
{
|
||||
// Get all method declarations with at least one attribute
|
||||
IncrementalValuesProvider<IMethodSymbol> methodSymbols =
|
||||
// Gather info for all annotated command methods (starting from method declarations with at least one attribute)
|
||||
IncrementalValuesProvider<(HierarchyInfo Hierarchy, Result<CommandInfo?> Info)> commandInfoWithErrors =
|
||||
context.SyntaxProvider
|
||||
.CreateSyntaxProvider(
|
||||
static (node, _) => node is MethodDeclarationSyntax { Parent: ClassDeclarationSyntax, AttributeLists.Count: > 0 },
|
||||
static (context, _) =>
|
||||
static (context, token) =>
|
||||
{
|
||||
if (!context.SemanticModel.Compilation.HasLanguageVersionAtLeastEqualTo(LanguageVersion.CSharp8))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return (IMethodSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!;
|
||||
IMethodSymbol methodSymbol = (IMethodSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node, token)!;
|
||||
|
||||
// Filter the methods using [RelayCommand]
|
||||
if (!methodSymbol.TryGetAttributeWithFullyQualifiedName("global::CommunityToolkit.Mvvm.Input.RelayCommandAttribute", out AttributeData? attribute))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
// Produce the incremental models
|
||||
HierarchyInfo hierarchy = HierarchyInfo.From(methodSymbol.ContainingType);
|
||||
CommandInfo? commandInfo = Execute.GetInfo(methodSymbol, attribute, out ImmutableArray<Diagnostic> diagnostics);
|
||||
|
||||
return (Hierarchy: hierarchy, new Result<CommandInfo?>(commandInfo, diagnostics));
|
||||
})
|
||||
.Where(static item => item is not null)!;
|
||||
|
||||
// Filter the methods using [RelayCommand]
|
||||
IncrementalValuesProvider<(IMethodSymbol Symbol, AttributeData Attribute)> methodSymbolsWithAttributeData =
|
||||
methodSymbols
|
||||
.Select(static (item, _) => (
|
||||
item,
|
||||
Attribute: item.GetAttributes().FirstOrDefault(a => a.AttributeClass?.HasFullyQualifiedName("global::CommunityToolkit.Mvvm.Input.RelayCommandAttribute") == true)))
|
||||
.Where(static item => item.Attribute is not null)!;
|
||||
|
||||
// Gather info for all annotated command methods
|
||||
IncrementalValuesProvider<(HierarchyInfo Hierarchy, Result<CommandInfo?> Info)> commandInfoWithErrors =
|
||||
methodSymbolsWithAttributeData
|
||||
.Select(static (item, _) =>
|
||||
{
|
||||
HierarchyInfo hierarchy = HierarchyInfo.From(item.Symbol.ContainingType);
|
||||
CommandInfo? commandInfo = Execute.GetInfo(item.Symbol, item.Attribute, out ImmutableArray<Diagnostic> diagnostics);
|
||||
|
||||
return (hierarchy, new Result<CommandInfo?>(commandInfo, diagnostics));
|
||||
});
|
||||
.Where(static item => item.Hierarchy is not null);
|
||||
|
||||
// Output the diagnostics
|
||||
context.ReportDiagnostics(commandInfoWithErrors.Select(static (item, _) => item.Info.Errors));
|
||||
@@ -66,7 +59,7 @@ public sealed partial class RelayCommandGenerator : IIncrementalGenerator
|
||||
commandInfoWithErrors
|
||||
.Where(static item => item.Info.Value is not null)
|
||||
.Select(static (item, _) => (item.Hierarchy, item.Info.Value!))
|
||||
.WithComparers(HierarchyInfo.Comparer.Default, CommandInfo.Comparer.Default);
|
||||
.WithComparers(HierarchyInfo.Comparer.Default, CommandInfo.Comparer.Default);
|
||||
|
||||
// Generate the commands
|
||||
context.RegisterSourceOutput(commandInfo, static (context, item) =>
|
||||
|
||||
Reference in New Issue
Block a user