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";
}