mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 19:03:29 +08:00
- 将 EnumExtensionsGenerator 的基类从 MetadataAttributeClassGeneratorBase 改为 AttributeEnumGeneratorBase - 修改 AttributeMetadataName 为静态私有字段 - 重写 ResolveAttribute 方法用于解析属性数据 - 更新 ValidateSymbol 方法参数类型为 EnumDeclarationSyntax - 调整命名空间生成逻辑,简化条件判断 - 重构 AttributeEnumGeneratorBase 基类实现 - 添加 ResolveAttribute 抽象方法用于属性解析 - 改进 Initialize 方法中的语法提供程序逻辑 - 添加 GetHintName 虚方法用于生成文件名提示
102 lines
3.7 KiB
C#
102 lines
3.7 KiB
C#
using System.Linq;
|
||
using Microsoft.CodeAnalysis;
|
||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||
|
||
namespace GFramework.SourceGenerators.Common.generator;
|
||
|
||
/// <summary>
|
||
/// 属性枚举生成器基类,用于基于特定属性的枚举进行源代码生成
|
||
/// </summary>
|
||
public abstract class AttributeEnumGeneratorBase : IIncrementalGenerator
|
||
{
|
||
/// <summary>
|
||
/// 获取属性的短名称(不包含后缀)
|
||
/// </summary>
|
||
protected abstract string AttributeShortNameWithoutSuffix { get; }
|
||
|
||
/// <summary>
|
||
/// 初始化增量生成器
|
||
/// </summary>
|
||
/// <param name="context">增量生成器初始化上下文</param>
|
||
public void Initialize(IncrementalGeneratorInitializationContext context)
|
||
{
|
||
// 创建语法提供程序,查找带有指定属性的枚举声明
|
||
var candidates = context.SyntaxProvider.CreateSyntaxProvider(
|
||
(node, _) =>
|
||
node is EnumDeclarationSyntax eds &&
|
||
eds.AttributeLists
|
||
.SelectMany(a => a.Attributes)
|
||
.Any(a => a.Name.ToString()
|
||
.Contains(AttributeShortNameWithoutSuffix)),
|
||
(ctx, _) =>
|
||
{
|
||
var syntax = (EnumDeclarationSyntax)ctx.Node;
|
||
var symbol = ctx.SemanticModel.GetDeclaredSymbol(syntax, cancellationToken: _) as INamedTypeSymbol;
|
||
return (syntax, symbol);
|
||
})
|
||
.Where(x => x.symbol is not null);
|
||
|
||
var combined = candidates.Combine(context.CompilationProvider);
|
||
|
||
// 注册源输出,生成最终的源代码
|
||
context.RegisterSourceOutput(combined, (spc, pair) =>
|
||
{
|
||
var ((syntax, symbol), compilation) = pair;
|
||
|
||
var attr = ResolveAttribute(compilation, symbol!);
|
||
if (attr is null)
|
||
return;
|
||
|
||
if (!ValidateSymbol(spc, compilation, syntax, symbol!, attr))
|
||
return;
|
||
|
||
spc.AddSource(
|
||
GetHintName(symbol!),
|
||
Generate(symbol!, attr));
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析指定符号上的属性数据
|
||
/// </summary>
|
||
/// <param name="compilation">编译对象</param>
|
||
/// <param name="symbol">命名类型符号</param>
|
||
/// <returns>属性数据对象,如果未找到则返回null</returns>
|
||
protected abstract AttributeData? ResolveAttribute(
|
||
Compilation compilation,
|
||
INamedTypeSymbol symbol);
|
||
|
||
/// <summary>
|
||
/// 验证符号是否符合生成要求
|
||
/// </summary>
|
||
/// <param name="context">源生产上下文</param>
|
||
/// <param name="compilation">编译对象</param>
|
||
/// <param name="syntax">枚举声明语法节点</param>
|
||
/// <param name="symbol">命名类型符号</param>
|
||
/// <param name="attr">属性数据</param>
|
||
/// <returns>验证是否通过</returns>
|
||
protected abstract bool ValidateSymbol(
|
||
SourceProductionContext context,
|
||
Compilation compilation,
|
||
EnumDeclarationSyntax syntax,
|
||
INamedTypeSymbol symbol,
|
||
AttributeData attr);
|
||
|
||
/// <summary>
|
||
/// 生成源代码
|
||
/// </summary>
|
||
/// <param name="symbol">命名类型符号</param>
|
||
/// <param name="attr">属性数据</param>
|
||
/// <returns>生成的源代码字符串</returns>
|
||
protected abstract string Generate(
|
||
INamedTypeSymbol symbol,
|
||
AttributeData attr);
|
||
|
||
/// <summary>
|
||
/// 获取生成文件的提示名称
|
||
/// </summary>
|
||
/// <param name="symbol">命名类型符号</param>
|
||
/// <returns>生成文件的提示名称</returns>
|
||
protected virtual string GetHintName(INamedTypeSymbol symbol)
|
||
=> $"{symbol.Name}.g.cs";
|
||
} |