mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 19:03:29 +08:00
- 统一调整代码注释的缩进格式,保持文档注释的一致性 - 简化对象初始化语法,移除不必要的参数名称指定 - 优化条件语句结构,移除多余的花括号 - 调整方法实现格式,使用表达式主体语法简化代码 - 标准化代码缩进和空格使用,提升代码可读性 - [skip ci]
113 lines
3.7 KiB
C#
113 lines
3.7 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>
|
||
/// 生成源代码
|
||
/// </summary>
|
||
/// <param name="context">源生产上下文</param>
|
||
/// <param name="compilation">编译对象</param>
|
||
/// <param name="symbol">命名类型符号</param>
|
||
/// <param name="attr">属性数据</param>
|
||
/// <returns>生成的源代码字符串</returns>
|
||
protected override string Generate(
|
||
SourceProductionContext context,
|
||
Compilation compilation,
|
||
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} = LoggerFactoryResolver.Provider.CreateLogger(\"{name}\");");
|
||
sb.AppendLine("}");
|
||
|
||
return sb.ToString().TrimEnd();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 可以自定义生成文件名
|
||
/// </summary>
|
||
protected override string GetHintName(INamedTypeSymbol symbol)
|
||
{
|
||
return $"{symbol.Name}.Logger.g.cs";
|
||
}
|
||
|
||
private static object? GetNamedArg(AttributeData attr, string name)
|
||
{
|
||
return attr.NamedArguments.FirstOrDefault(kv => kv.Key == name).Value.Value;
|
||
}
|
||
} |