mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-22 10:34:30 +08:00
- 为 ValidateSymbol 方法添加 Compilation 参数以支持类型解析 - 实现基于 Compilation 的接口类型验证,替代字符串比较方式 - 添加源代码生成器跟踪诊断功能,便于调试生成过程 - 在 AttributeClassGeneratorBase 中增加详细的执行流程跟踪日志 - 更新诊断描述符配置,添加跟踪信息的诊断支持 - 优化 ContextAwareGenerator 中的接口验证逻辑
124 lines
3.9 KiB
C#
124 lines
3.9 KiB
C#
using System.Linq;
|
||
using System.Text;
|
||
using GFramework.SourceGenerators.Common.constants;
|
||
using GFramework.SourceGenerators.Common.generator;
|
||
using GFramework.SourceGenerators.diagnostics;
|
||
using Microsoft.CodeAnalysis;
|
||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||
|
||
namespace GFramework.SourceGenerators.rule;
|
||
|
||
[Generator]
|
||
public sealed class ContextAwareGenerator : MetadataAttributeClassGeneratorBase
|
||
{
|
||
/// <summary>
|
||
/// 获取属性元数据的完整名称,用于标识ContextAwareAttribute的完全限定名
|
||
/// </summary>
|
||
/// <returns>返回ContextAwareAttribute的完全限定名字符串</returns>
|
||
protected override string AttributeMetadataName =>
|
||
$"{PathContests.SourceGeneratorsAbstractionsPath}.rule.ContextAwareAttribute";
|
||
|
||
/// <summary>
|
||
/// 仅用于 Syntax 粗筛选
|
||
/// </summary>
|
||
/// <returns>返回属性的简短名称,不包含后缀</returns>
|
||
protected override string AttributeShortNameWithoutSuffix => "ContextAware";
|
||
|
||
|
||
/// <summary>
|
||
/// 额外语义校验:必须实现 IContextAware
|
||
/// </summary>
|
||
protected override bool ValidateSymbol(
|
||
SourceProductionContext context,
|
||
Compilation compilation,
|
||
ClassDeclarationSyntax syntax,
|
||
INamedTypeSymbol symbol,
|
||
AttributeData attr)
|
||
{
|
||
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>
|
||
protected override string Generate(
|
||
INamedTypeSymbol symbol,
|
||
AttributeData attr)
|
||
{
|
||
var ns = symbol.ContainingNamespace.IsGlobalNamespace
|
||
? null
|
||
: symbol.ContainingNamespace.ToDisplayString();
|
||
|
||
var sb = new StringBuilder();
|
||
sb.AppendLine("// <auto-generated/>");
|
||
sb.AppendLine("#nullable enable");
|
||
sb.AppendLine();
|
||
|
||
if (ns is not null)
|
||
{
|
||
sb.AppendLine($"namespace {ns};");
|
||
sb.AppendLine();
|
||
}
|
||
|
||
sb.AppendLine($"partial class {symbol.Name}");
|
||
sb.AppendLine("{");
|
||
|
||
// 属性
|
||
sb.AppendLine(" /// <summary>");
|
||
sb.AppendLine(" /// 自动注入的架构上下文");
|
||
sb.AppendLine(" /// </summary>");
|
||
sb.AppendLine(
|
||
$" protected {PathContests.CoreAbstractionsNamespace}.architecture.IArchitectureContext Context {{ get; private set; }} = null!;");
|
||
sb.AppendLine();
|
||
|
||
// 方法
|
||
sb.AppendLine(
|
||
$" void {PathContests.CoreAbstractionsNamespace}.rule.IContextAware.SetContext(");
|
||
sb.AppendLine(
|
||
$" {PathContests.CoreAbstractionsNamespace}.architecture.IArchitectureContext context)");
|
||
sb.AppendLine(" {");
|
||
sb.AppendLine(" Context = context;");
|
||
sb.AppendLine(" }");
|
||
|
||
sb.AppendLine("}");
|
||
|
||
return sb.ToString().TrimEnd();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 自定义生成文件名
|
||
/// </summary>
|
||
protected override string GetHintName(INamedTypeSymbol symbol)
|
||
{
|
||
// 包含命名空间和生成器类名路径
|
||
return
|
||
$"{symbol.Name}.ContextAware.g.cs";
|
||
}
|
||
} |