refactor(generator): 重构源代码生成器基础类和诊断功能

- 为 ValidateSymbol 方法添加 Compilation 参数以支持类型解析
- 实现基于 Compilation 的接口类型验证,替代字符串比较方式
- 添加源代码生成器跟踪诊断功能,便于调试生成过程
- 在 AttributeClassGeneratorBase 中增加详细的执行流程跟踪日志
- 更新诊断描述符配置,添加跟踪信息的诊断支持
- 优化 ContextAwareGenerator 中的接口验证逻辑
This commit is contained in:
GwWuYou 2025-12-28 16:17:08 +08:00
parent 414e49c413
commit 3262e111f4
6 changed files with 100 additions and 16 deletions

View File

@ -5,4 +5,5 @@
Rule ID | Category | Severity | Notes
---------------------|-------------------|----------|-------------------
GF_Common_Class_001 | GFramework.Common | Error | CommonDiagnostics
GF_Common_Class_001 | GFramework.Common | Error | CommonDiagnostics
GF_Common_Trace_001 | GFramework.Trace | Info | CommonDiagnostics

View File

@ -24,6 +24,37 @@ public static class CommonDiagnostics
"Class '{0}' must be declared partial for code generation",
"GFramework.Common",
DiagnosticSeverity.Error,
true
isEnabledByDefault: true
);
/// <summary>
/// 定义源代码生成器跟踪信息的诊断描述符
/// </summary>
/// <remarks>
/// 诊断ID: GF_Common_Trace_001
/// 诊断消息: "{0}"
/// 分类: GFramework.Trace
/// 严重性: Info
/// 是否启用: true
/// </remarks>
public static readonly DiagnosticDescriptor GeneratorTrace =
new(
"GF_Common_Trace_001",
"Source generator trace",
"{0}",
"GFramework.Trace",
DiagnosticSeverity.Info,
isEnabledByDefault: true
);
/// <summary>
/// 源代码生成器跟踪信息
/// </summary>
public static void Trace(SourceProductionContext context, string message)
{
context.ReportDiagnostic(Diagnostic.Create(
GeneratorTrace,
Location.None,
message));
}
}

View File

@ -70,22 +70,49 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
ClassDeclarationSyntax classDecl,
INamedTypeSymbol symbol)
{
var attr = ResolveAttribute(compilation, symbol);
if (attr is null)
return;
// ① 进入 Execute
CommonDiagnostics.Trace(context, $"[GEN] Enter Execute: {symbol.ToDisplayString()}");
var attr = ResolveAttribute(compilation, symbol);
// ② 属性是否解析到
if (attr is null)
{
CommonDiagnostics.Trace(context,
$"[GEN] Attribute NOT resolved on {symbol.ToDisplayString()}");
return;
}
CommonDiagnostics.Trace(context,
$"[GEN] Attribute resolved: {attr.AttributeClass?.ToDisplayString()}");
// ③ partial 校验
if (!classDecl.Modifiers.Any(SyntaxKind.PartialKeyword))
{
CommonDiagnostics.Trace(context,
$"[GEN] Class is NOT partial: {symbol.Name}");
ReportClassMustBePartial(context, classDecl, symbol);
return;
}
if (!ValidateSymbol(context, classDecl, symbol, attr))
// ④ ValidateSymbol
if (!ValidateSymbol(context, compilation, classDecl, symbol, attr))
{
CommonDiagnostics.Trace(context,
$"[GEN] ValidateSymbol FAILED: {symbol.ToDisplayString()}");
return;
}
context.AddSource(GetHintName(symbol), Generate(symbol, attr));
// ⑤ Generate
var hintName = GetHintName(symbol);
CommonDiagnostics.Trace(context,
$"[GEN] Generating source: {hintName}");
context.AddSource(hintName, Generate(symbol, attr));
}
/// <summary>
/// 验证符号的有效性
/// </summary>
@ -96,9 +123,11 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
/// <returns>验证是否通过</returns>
protected virtual bool ValidateSymbol(
SourceProductionContext context,
Compilation compilation,
ClassDeclarationSyntax syntax,
INamedTypeSymbol symbol,
AttributeData attr) => true;
AttributeData attr)
=> true;
/// <summary>
/// 生成源代码

View File

@ -26,12 +26,14 @@ public sealed class EnumExtensionsGenerator : MetadataAttributeClassGeneratorBas
/// 验证符号是否为有效的枚举类型
/// </summary>
/// <param name="context">源生产上下文</param>
/// <param name="compilation">编译对象</param>
/// <param name="syntax">类声明语法节点</param>
/// <param name="symbol">命名类型符号</param>
/// <param name="attr">属性数据</param>
/// <returns>验证是否通过</returns>
protected override bool ValidateSymbol(
SourceProductionContext context,
Compilation compilation,
ClassDeclarationSyntax syntax,
INamedTypeSymbol symbol,
AttributeData attr)

View File

@ -31,6 +31,7 @@ public sealed class LoggerGenerator : TypeAttributeClassGeneratorBase
/// </summary>
protected override bool ValidateSymbol(
SourceProductionContext context,
Compilation compilation,
ClassDeclarationSyntax syntax,
INamedTypeSymbol symbol,
AttributeData attr)

View File

@ -1,6 +1,5 @@
using System.Linq;
using System.Text;
using GFramework.Core.Abstractions.rule;
using GFramework.SourceGenerators.Common.constants;
using GFramework.SourceGenerators.Common.generator;
using GFramework.SourceGenerators.diagnostics;
@ -31,19 +30,40 @@ public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
/// </summary>
protected override bool ValidateSymbol(
SourceProductionContext context,
Compilation compilation,
ClassDeclarationSyntax syntax,
INamedTypeSymbol symbol,
AttributeData attr)
{
if (symbol.AllInterfaces.Any(i =>
i.ToDisplayString() == typeof(IContextAware).FullName)) return true;
context.ReportDiagnostic(Diagnostic.Create(
ContextAwareDiagnostic.ClassMustImplementIContextAware,
syntax.Identifier.GetLocation(),
symbol.Name));
return false;
var iContextAware = compilation
.GetTypeByMetadataName(
$"{PathContests.CoreAbstractionsNamespace}.rule.IContextAware");
if (iContextAware is null)
{
context.ReportDiagnostic(Diagnostic.Create(
ContextAwareDiagnostic.ClassMustImplementIContextAware,
syntax.Identifier.GetLocation(),
symbol.Name));
return false;
}
if (!symbol.AllInterfaces.Any(i =>
SymbolEqualityComparer.Default.Equals(i, iContextAware)))
{
context.ReportDiagnostic(Diagnostic.Create(
ContextAwareDiagnostic.ClassMustImplementIContextAware,
syntax.Identifier.GetLocation(),
symbol.Name));
return false;
}
return true;
}
/// <summary>
/// 生成源码
/// </summary>