using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace GFramework.SourceGenerators.Common.generator; /// /// 属性枚举生成器基类,用于基于特定属性的枚举进行源代码生成 /// public abstract class AttributeEnumGeneratorBase : IIncrementalGenerator { /// /// 获取属性的短名称(不包含后缀) /// protected abstract string AttributeShortNameWithoutSuffix { get; } /// /// 初始化增量生成器 /// /// 增量生成器初始化上下文 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, _) 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)); }); } /// /// 解析指定符号上的属性数据 /// /// 编译对象 /// 命名类型符号 /// 属性数据对象,如果未找到则返回null protected abstract AttributeData? ResolveAttribute( Compilation compilation, INamedTypeSymbol symbol); /// /// 验证符号是否符合生成要求 /// /// 源生产上下文 /// 编译对象 /// 枚举声明语法节点 /// 命名类型符号 /// 属性数据 /// 验证是否通过 protected abstract bool ValidateSymbol( SourceProductionContext context, Compilation compilation, EnumDeclarationSyntax syntax, INamedTypeSymbol symbol, AttributeData attr); /// /// 生成源代码 /// /// 命名类型符号 /// 属性数据 /// 生成的源代码字符串 protected abstract string Generate( INamedTypeSymbol symbol, AttributeData attr); /// /// 获取生成文件的提示名称 /// /// 命名类型符号 /// 生成文件的提示名称 protected virtual string GetHintName(INamedTypeSymbol symbol) { return $"{symbol.Name}.g.cs"; } }