From 7876647871e967dad63fe1a3d3ce8827864bc267 Mon Sep 17 00:00:00 2001
From: GeWuYou <95328647+GeWuYou@users.noreply.github.com>
Date: Wed, 14 Jan 2026 13:21:54 +0800
Subject: [PATCH] =?UTF-8?q?feat(generator):=20=E6=B7=BB=E5=8A=A0=E5=91=BD?=
=?UTF-8?q?=E5=90=8D=E7=B1=BB=E5=9E=8B=E7=AC=A6=E5=8F=B7=E6=89=A9=E5=B1=95?=
=?UTF-8?q?=E6=96=B9=E6=B3=95=E5=B9=B6=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97?=
=?UTF-8?q?=E7=94=9F=E6=88=90=E5=99=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新增 INamedTypeSymbolExtensions 扩展类,提供 GetFullClassName 方法获取完整类名
- 在 LoggerGenerator 中引入命名空间扩展,支持嵌套类型完整路径解析
- 重构 LoggerGenerator 的类名和参数解析逻辑,增强代码可读性
- 添加对 record 类型的支持,完善类型判断机制
- 优化泛型参数和约束的处理方式,提升代码生成准确性
---
.../extensions/INamedTypeSymbolExtensions.cs | 61 +++++++++++++++++++
.../logging/LoggerGenerator.cs | 36 +++++++----
2 files changed, 85 insertions(+), 12 deletions(-)
create mode 100644 GFramework.SourceGenerators.Common/extensions/INamedTypeSymbolExtensions.cs
diff --git a/GFramework.SourceGenerators.Common/extensions/INamedTypeSymbolExtensions.cs b/GFramework.SourceGenerators.Common/extensions/INamedTypeSymbolExtensions.cs
new file mode 100644
index 0000000..4865ea9
--- /dev/null
+++ b/GFramework.SourceGenerators.Common/extensions/INamedTypeSymbolExtensions.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis;
+
+namespace GFramework.SourceGenerators.Common.extensions;
+
+///
+/// 提供INamedTypeSymbol类型的扩展方法
+///
+public static class INamedTypeSymbolExtensions
+{
+ ///
+ /// 获取命名类型符号的完整类名(包括嵌套类型名称)
+ ///
+ /// 要获取完整类名的命名类型符号
+ /// 完整的类名,格式为"外层类名.内层类名.当前类名"
+ public static string GetFullClassName(this INamedTypeSymbol symbol)
+ {
+ var names = new Stack();
+ var current = symbol;
+
+ // 遍历包含类型链,将所有类型名称压入栈中
+ while (current != null)
+ {
+ names.Push(current.Name);
+ current = current.ContainingType;
+ }
+
+ // 将栈中的名称用点号连接,形成完整的类名
+ return string.Join(".", names);
+ }
+
+ ///
+ /// 获取命名类型符号的命名空间名称
+ ///
+ /// 要获取命名空间的命名类型符号
+ /// 命名空间名称,如果是全局命名空间则返回null
+ private static string? GetNamespace(this INamedTypeSymbol symbol)
+ {
+ return symbol.ContainingNamespace.IsGlobalNamespace
+ ? null
+ : symbol.ContainingNamespace.ToDisplayString();
+ }
+
+ ///
+ /// 根据类型种类解析对应的类型关键字
+ ///
+ /// 要解析类型的命名类型符号
+ /// 对应类型的字符串表示,如"class"、"struct"或"record"
+ private static string ResolveTypeKind(this INamedTypeSymbol symbol)
+ {
+ return symbol.TypeKind switch
+ {
+ TypeKind.Class => "class",
+ TypeKind.Struct => "struct",
+#if NET5_0_OR_GREATER || ROSLYN_3_7_OR_GREATER
+ TypeKind.Record => "record",
+#endif
+ _ => "class",
+ };
+ }
+}
\ No newline at end of file
diff --git a/GFramework.SourceGenerators/logging/LoggerGenerator.cs b/GFramework.SourceGenerators/logging/LoggerGenerator.cs
index 3aaa4a8..577ccff 100644
--- a/GFramework.SourceGenerators/logging/LoggerGenerator.cs
+++ b/GFramework.SourceGenerators/logging/LoggerGenerator.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using GFramework.SourceGenerators.Abstractions.logging;
using GFramework.SourceGenerators.Common.constants;
+using GFramework.SourceGenerators.Common.extensions;
using GFramework.SourceGenerators.Common.generator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -59,30 +60,32 @@ public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase
? null
: symbol.ContainingNamespace.ToDisplayString();
- var className = symbol.Name;
+ // 类名和嵌套类完整路径
+ var className = symbol.GetFullClassName();
- // 解析构造函数参数
- var name = className;
+ // 构造函数参数解析
+ var logName = className;
if (attr.ConstructorArguments.Length > 0)
{
var argValue = attr.ConstructorArguments[0].Value;
- name = argValue is string s && !string.IsNullOrWhiteSpace(s)
+ logName = 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 typeParams = symbol.TypeParameters.Length > 0
? "<" + string.Join(", ", symbol.TypeParameters.Select(tp => tp.Name)) + ">"
: "";
+ // 泛型约束
var constraints = symbol.TypeParameters
.Where(tp => tp.ConstraintTypes.Length > 0 || tp.HasReferenceTypeConstraint || tp.HasValueTypeConstraint ||
tp.HasConstructorConstraint)
@@ -98,6 +101,17 @@ public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase
return $"where {tp.Name} : {string.Join(", ", parts)}";
});
+ // 判断类型
+ var typeKind = symbol.TypeKind switch
+ {
+ TypeKind.Class => "class",
+ TypeKind.Struct => "struct",
+#if NET5_0_OR_GREATER || ROSLYN_3_7_OR_GREATER
+ TypeKind.Record => "record",
+#endif
+ _ => "class"
+ };
+
var sb = new StringBuilder();
sb.AppendLine("// ");
sb.AppendLine($"using {PathContests.CoreAbstractionsNamespace}.logging;");
@@ -109,16 +123,14 @@ public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase
sb.AppendLine();
}
- sb.AppendLine($"partial class {className}{typeParams}");
+ // 生成 partial 类
+ sb.AppendLine($"partial {typeKind} {className}{typeParams}");
foreach (var c in constraints)
- {
sb.AppendLine($" {c}");
- }
-
sb.AppendLine("{");
- sb.AppendLine(" /// Auto-generated logger");
+ sb.AppendLine($" /// Auto-generated logger");
sb.AppendLine(
- $" {access} {staticKeyword}readonly ILogger {fieldName} = LoggerFactoryResolver.Provider.CreateLogger(\"{name}\");");
+ $" {access} {staticKeyword}readonly ILogger {fieldName} = LoggerFactoryResolver.Provider.CreateLogger(\"{logName}\");");
sb.AppendLine("}");
return sb.ToString().TrimEnd();