using System; using System.Linq; using System.Text; using GFramework.SourceGenerators.Abstractions.logging; using GFramework.SourceGenerators.Common.generator; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace GFramework.SourceGenerators.logging; /// /// 日志生成器,用于为标记了LogAttribute的类自动生成日志字段 /// [Generator] public sealed class LoggerGenerator : AttributeClassGeneratorBase { /// /// 强类型 Attribute /// protected override Type AttributeType => typeof(LogAttribute); /// /// 用于语法快速筛选 /// protected override string AttributeShortNameWithoutSuffix => "Log"; /// /// 对类进行额外语义校验(可选) /// protected override bool ValidateSymbol( SourceProductionContext context, ClassDeclarationSyntax syntax, INamedTypeSymbol symbol, AttributeData attr) { // 可以加自定义规则,比如确保类是 public 或实现某接口 return true; } /// /// 生成 Logger 字段的代码 /// protected override string Generate(INamedTypeSymbol symbol, AttributeData attr) { var ns = symbol.ContainingNamespace.IsGlobalNamespace ? null : symbol.ContainingNamespace.ToDisplayString(); var className = symbol.Name; // 解析构造函数参数 var name = className; if (attr.ConstructorArguments.Length > 0) { var argValue = attr.ConstructorArguments[0].Value; name = argValue is string s && !string.IsNullOrWhiteSpace(s) ? s : className; } // 解析命名参数 var fieldName = GetNamedArg(attr, "FieldName")?.ToString() ?? "_log"; var access = GetNamedArg(attr, "AccessModifier")?.ToString() ?? "private"; var isStaticObj = GetNamedArg(attr, "IsStatic"); var isStatic = isStaticObj is not bool b || b; // 默认 true var staticKeyword = isStatic ? "static " : ""; var sb = new StringBuilder(); sb.AppendLine("// "); sb.AppendLine("using GFramework.Core.logging;"); if (ns is not null) { sb.AppendLine($"namespace {ns};"); sb.AppendLine(); } sb.AppendLine($"partial class {className}"); sb.AppendLine("{"); sb.AppendLine(" /// Auto-generated logger"); sb.AppendLine( $" {access} {staticKeyword}readonly ILogger {fieldName} = new ConsoleLoggerFactory().GetLogger(\"{name}\");"); sb.AppendLine("}"); return sb.ToString().TrimEnd(); } /// /// 可以自定义生成文件名 /// protected override string GetHintName(INamedTypeSymbol symbol) => $"{symbol.Name}.Logger.g.cs"; private static object? GetNamedArg(AttributeData attr, string name) => attr.NamedArguments.FirstOrDefault(kv => kv.Key == name).Value.Value; }