diff --git a/GFramework.Generator/AnalyzerReleases.Unshipped.md b/GFramework.Generator/AnalyzerReleases.Unshipped.md
index 6e2cad7..805387c 100644
--- a/GFramework.Generator/AnalyzerReleases.Unshipped.md
+++ b/GFramework.Generator/AnalyzerReleases.Unshipped.md
@@ -5,4 +5,5 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
-GFLOG001 | GFramework.Logging | Error | Diagnostics
\ No newline at end of file
+GFLOG001 | GFramework.Logging | Error | Diagnostics
+GFW_LOG001 | GFramework.Logging | Warning | Diagnostics
\ No newline at end of file
diff --git a/GFramework.Generator/generator/logging/Diagnostic.cs b/GFramework.Generator/generator/logging/Diagnostic.cs
index 6dd2100..b52210e 100644
--- a/GFramework.Generator/generator/logging/Diagnostic.cs
+++ b/GFramework.Generator/generator/logging/Diagnostic.cs
@@ -7,8 +7,9 @@ namespace GFramework.Generator.generator.logging;
///
internal static class Diagnostics
{
+
///
- /// 定义一个诊断描述符,用于检查使用[Log]特性的类是否声明为partial
+ /// 定义诊断描述符:要求使用[Log]特性的类必须声明为partial
///
///
/// 当类使用[Log]特性但未声明为partial时,编译器将报告此错误
@@ -22,4 +23,17 @@ internal static class Diagnostics
DiagnosticSeverity.Error,
isEnabledByDefault: true
);
+
+ ///
+ /// 定义诊断描述符:LogAttribute无法生成Logger的错误情况
+ ///
+ public static readonly DiagnosticDescriptor LogAttributeInvalid =
+ new(
+ id: "GFW_LOG001",
+ title: "LogAttribute 无法生成 Logger",
+ messageFormat: "类 '{0}' 上的 LogAttribute 无法生效:{1}",
+ category: "GFramework.Logging",
+ DiagnosticSeverity.Warning,
+ isEnabledByDefault: true);
+
}
diff --git a/GFramework.Generator/generator/logging/LoggerGenerator.cs b/GFramework.Generator/generator/logging/LoggerGenerator.cs
index 7c24473..f3bd42a 100644
--- a/GFramework.Generator/generator/logging/LoggerGenerator.cs
+++ b/GFramework.Generator/generator/logging/LoggerGenerator.cs
@@ -30,14 +30,14 @@ namespace GFramework.Generator.generator.logging
// 2. 在 SyntaxProvider 阶段就拿到 SemanticModel
var candidates =
context.SyntaxProvider.CreateSyntaxProvider(
- static (node, _) => node is ClassDeclarationSyntax,
- static (ctx, _) =>
- {
- var classDecl = (ClassDeclarationSyntax)ctx.Node;
- var symbol = ctx.SemanticModel.GetDeclaredSymbol(classDecl);
- return (ClassDecl: classDecl, Symbol: symbol);
- })
- .Where(x => x.Symbol is not null);
+ static (node, _) => node is ClassDeclarationSyntax,
+ static (ctx, _) =>
+ {
+ var classDecl = (ClassDeclarationSyntax)ctx.Node;
+ var symbol = ctx.SemanticModel.GetDeclaredSymbol(classDecl);
+ return (ClassDecl: classDecl, Symbol: symbol);
+ })
+ .Where(x => x.Symbol is not null);
// 3. 合并 Attribute Symbol 并筛选
var targets =
@@ -70,7 +70,7 @@ namespace GFramework.Generator.generator.logging
return;
}
- var source = Generate(classSymbol);
+ var source = Generate(classSymbol, spc);
spc.AddSource(
$"{classSymbol.Name}.Logger.g.cs",
SourceText.From(source, Encoding.UTF8));
@@ -81,8 +81,9 @@ namespace GFramework.Generator.generator.logging
/// 生成日志字段代码
///
/// 类符号
+ /// 源代码生成上下文
/// 生成的代码字符串
- private static string Generate(INamedTypeSymbol classSymbol)
+ private static string Generate(INamedTypeSymbol classSymbol, SourceProductionContext spc)
{
var ns = classSymbol.ContainingNamespace.IsGlobalNamespace
? null
@@ -91,24 +92,47 @@ namespace GFramework.Generator.generator.logging
var className = classSymbol.Name;
var attr = classSymbol.GetAttributes()
- .First(a => a.AttributeClass!.ToDisplayString() == AttributeMetadataName);
+ .FirstOrDefault(a =>
+ a.AttributeClass?.ToDisplayString() == AttributeMetadataName);
- string categoryExpr;
-
- if (attr.ConstructorArguments.Length > 0 &&
- attr.ConstructorArguments[0].Value is string s &&
- !string.IsNullOrWhiteSpace(s))
+ if (attr is null)
{
- // 用户显式指定字符串
- categoryExpr = $"\"{s}\"";
+ // 理论上不会发生,但防御式处理
+ spc.ReportDiagnostic(
+ Diagnostic.Create(
+ Diagnostics.LogAttributeInvalid,
+ classSymbol.Locations.FirstOrDefault(),
+ className,
+ "未找到 LogAttribute"
+ ));
+ return string.Empty;
+ }
+
+ // === 解析 category ===
+ string category;
+
+ if (attr.ConstructorArguments.Length == 0)
+ {
+ // 默认:类名
+ category = className;
+ }
+ else if (attr.ConstructorArguments[0].Value is string s &&
+ !string.IsNullOrWhiteSpace(s))
+ {
+ category = s;
}
else
{
- // 默认使用 nameof(Class)
- categoryExpr = $"nameof({className})";
+ spc.ReportDiagnostic(
+ Diagnostic.Create(
+ Diagnostics.LogAttributeInvalid,
+ classSymbol.Locations.FirstOrDefault(),
+ className,
+ "LogAttribute 的构造参数不是有效的 string"
+ ));
+ return string.Empty;
}
-
var fieldName = GetNamedArg(attr, "FieldName", "_log");
var access = GetNamedArg(attr, "AccessModifier", "private");
var isStatic = GetNamedArg(attr, "IsStatic", true);
@@ -128,8 +152,8 @@ namespace GFramework.Generator.generator.logging
sb.AppendLine($" public partial class {className}");
sb.AppendLine(" {");
sb.AppendLine(
- $" {access} {staticKeyword}readonly ILog {fieldName} =" +
- $" Log.CreateLogger(\"{categoryExpr}\");");
+ $" {access} {staticKeyword}readonly ILog {fieldName} = " +
+ $"Log.CreateLogger(\"{category}\");");
sb.AppendLine(" }");
if (ns is not null)
@@ -138,6 +162,7 @@ namespace GFramework.Generator.generator.logging
return sb.ToString();
}
+
///
/// 获取属性参数的值
///
@@ -153,7 +178,8 @@ namespace GFramework.Generator.generator.logging
if (kv.Key == name && kv.Value.Value is T v)
return v;
}
+
return defaultValue;
}
}
-}
+}
\ No newline at end of file