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 : AttributeEnumGeneratorBase { private static string AttributeMetadataName => $"{PathContests.SourceGeneratorsAbstractionsPath}.enums.GenerateEnumExtensionsAttribute"; /// /// 仅用于 Syntax 粗筛选 /// protected override string AttributeShortNameWithoutSuffix => "GenerateEnumExtensions"; protected override AttributeData? ResolveAttribute(Compilation compilation, INamedTypeSymbol symbol) { var attrSymbol = compilation.GetTypeByMetadataName(AttributeMetadataName); if (attrSymbol is null) return null; return symbol.GetAttributes() .FirstOrDefault(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attrSymbol)); } protected override bool ValidateSymbol(SourceProductionContext context, Compilation compilation, EnumDeclarationSyntax syntax, INamedTypeSymbol symbol, AttributeData attr) { if (symbol.TypeKind == TypeKind.Enum) return true; var loc = syntax.Identifier.GetLocation(); context.ReportDiagnostic(Diagnostic.Create( CommonDiagnostics.ClassMustBePartial, loc, symbol.Name )); return false; } /// /// 生成枚举扩展方法的源代码 /// /// 枚举类型符号 /// 属性数据 /// 生成的源代码字符串 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;"); sb.AppendLine(!string.IsNullOrEmpty(ns) ? $"namespace {ns}" : "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($" /// 是否为 {memberName}"); sb.AppendLine( $" public static bool Is{memberName}(this {fullEnumName} value) => value == {fullEnumName}.{memberName};"); sb.AppendLine(); } // 生成 IsIn 方法 sb.AppendLine(" /// 判断是否属于指定集合"); 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"; }