using System.Linq; using System.Text; using GFramework.SourceGenerators.Common.constants; using GFramework.SourceGenerators.Common.diagnostics; using GFramework.SourceGenerators.Common.generator; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace GFramework.SourceGenerators.enums; /// /// 枚举扩展方法生成器,用于自动生成枚举相关的扩展方法 /// [Generator] public sealed class EnumExtensionsGenerator : MetadataAttributeClassGeneratorBase { protected override string AttributeMetadataName => $"{PathContests.SourceGeneratorsAbstractionsPath}.enums.GenerateEnumExtensionsAttribute"; /// /// 仅用于 Syntax 粗筛选 /// protected override string AttributeShortNameWithoutSuffix => "GenerateEnumExtensions"; /// /// 验证符号是否为有效的枚举类型 /// /// 源生产上下文 /// 编译对象 /// 类声明语法节点 /// 命名类型符号 /// 属性数据 /// 验证是否通过 protected override bool ValidateSymbol( SourceProductionContext context, Compilation compilation, ClassDeclarationSyntax syntax, INamedTypeSymbol symbol, AttributeData attr) { if (symbol.TypeKind != TypeKind.Enum) { var loc = syntax.Identifier.GetLocation(); context.ReportDiagnostic(Diagnostic.Create( CommonDiagnostics.ClassMustBePartial, // 可以定义一个新的 Enum 专用 Diagnostic loc, symbol.Name )); return false; } return true; } /// /// 生成枚举扩展方法的源代码 /// /// 枚举类型符号 /// 属性数据 /// 生成的源代码字符串 protected override string Generate(INamedTypeSymbol symbol, AttributeData attr) { var ns = symbol.ContainingNamespace.IsGlobalNamespace ? null : symbol.ContainingNamespace.ToDisplayString(); var enumName = symbol.Name; var fullEnumName = symbol.ToDisplayString(); var members = symbol.GetMembers() .OfType() .Where(f => f.ConstantValue != null) .ToArray(); var sb = new StringBuilder(); sb.AppendLine("// "); sb.AppendLine("using System;"); if (!string.IsNullOrEmpty(ns)) { sb.AppendLine($"namespace {ns}"); sb.AppendLine("{"); } else { sb.AppendLine("namespace EnumExtensionsGenerated"); sb.AppendLine("{"); } sb.AppendLine($" public static partial class {enumName}Extensions"); sb.AppendLine(" {"); // 生成 IsX 方法 foreach (var memberName in members.Select(m => m.Name)) { sb.AppendLine($" /// Auto-generated: 是否为 {memberName}"); sb.AppendLine( $" public static bool Is{memberName}(this {fullEnumName} value) => value == {fullEnumName}.{memberName};"); sb.AppendLine(); } // 生成 IsIn 方法 sb.AppendLine(" /// Auto-generated: 判断是否属于指定集合"); sb.AppendLine($" public static bool IsIn(this {fullEnumName} value, params {fullEnumName}[] values)"); sb.AppendLine(" {"); sb.AppendLine(" if (values == null) return false;"); sb.AppendLine(" foreach (var v in values) if (value == v) return true;"); sb.AppendLine(" return false;"); sb.AppendLine(" }"); sb.AppendLine(" }"); sb.AppendLine("}"); // namespace return sb.ToString(); } /// /// 获取生成文件的提示名称 /// /// 命名类型符号 /// 生成文件的提示名称 protected override string GetHintName(INamedTypeSymbol symbol) => $"{symbol.Name}.EnumExtensions.g.cs"; }