mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 19:03:29 +08:00
- 为 ValidateSymbol 方法添加 Compilation 参数以支持类型解析 - 实现基于 Compilation 的接口类型验证,替代字符串比较方式 - 添加源代码生成器跟踪诊断功能,便于调试生成过程 - 在 AttributeClassGeneratorBase 中增加详细的执行流程跟踪日志 - 更新诊断描述符配置,添加跟踪信息的诊断支持 - 优化 ContextAwareGenerator 中的接口验证逻辑
100 lines
3.3 KiB
C#
100 lines
3.3 KiB
C#
using System;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using GFramework.SourceGenerators.Abstractions.logging;
|
||
using GFramework.SourceGenerators.Common.constants;
|
||
using GFramework.SourceGenerators.Common.generator;
|
||
using Microsoft.CodeAnalysis;
|
||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||
|
||
namespace GFramework.SourceGenerators.logging;
|
||
|
||
/// <summary>
|
||
/// 日志生成器,用于为标记了LogAttribute的类自动生成日志字段
|
||
/// </summary>
|
||
[Generator]
|
||
public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase
|
||
{
|
||
/// <summary>
|
||
/// 获取属性元数据的完整名称,用于标识日志属性的完全限定名
|
||
/// </summary>
|
||
protected override Type AttributeType => typeof(LogAttribute);
|
||
|
||
/// <summary>
|
||
/// 用于语法快速筛选
|
||
/// </summary>
|
||
protected override string AttributeShortNameWithoutSuffix => "Log";
|
||
|
||
|
||
/// <summary>
|
||
/// 对类进行额外语义校验(可选)
|
||
/// </summary>
|
||
protected override bool ValidateSymbol(
|
||
SourceProductionContext context,
|
||
Compilation compilation,
|
||
ClassDeclarationSyntax syntax,
|
||
INamedTypeSymbol symbol,
|
||
AttributeData attr)
|
||
{
|
||
// 可以加自定义规则,比如确保类是 public 或实现某接口
|
||
return true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 生成 Logger 字段的代码
|
||
/// </summary>
|
||
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("// <auto-generated />");
|
||
sb.AppendLine($"using {PathContests.CoreAbstractionsNamespace}.logging;");
|
||
sb.AppendLine($"using {PathContests.CoreNamespace}.logging;");
|
||
|
||
if (ns is not null)
|
||
{
|
||
sb.AppendLine($"namespace {ns};");
|
||
sb.AppendLine();
|
||
}
|
||
|
||
sb.AppendLine($"partial class {className}");
|
||
sb.AppendLine("{");
|
||
sb.AppendLine(" /// <summary>Auto-generated logger</summary>");
|
||
sb.AppendLine(
|
||
$" {access} {staticKeyword}readonly ILogger {fieldName} = new ConsoleLoggerFactory().GetLogger(\"{name}\");");
|
||
sb.AppendLine("}");
|
||
|
||
return sb.ToString().TrimEnd();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 可以自定义生成文件名
|
||
/// </summary>
|
||
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;
|
||
} |