style(generator): 格式化源代码生成器相关文件

- 修复 ILogger.cs 中多余的逗号
- 统一 ContextAwareDiagnostic.cs 中的注释缩进格式
- 统一 ContextAwareGenerator.cs 中的注释缩进格式
- 统一 ContextAwareAttribute.cs 中的注释缩进格式
- 统一 CommonDiagnostics.cs 中的注释缩进格式
- 简化 AttributeClassGeneratorBase.cs 中的 isEnabledByDefault 参数
- 统一 GeneratorTest.cs 中的注释缩进格式
- 优化 ContextAwareGeneratorTests.cs 中的代码结构
- 调整 AnalyzerReleases.Unshipped.md 中的表格格式
This commit is contained in:
GwWuYou 2025-12-28 10:50:41 +08:00
parent 3e1531d7eb
commit e4a317b743
9 changed files with 58 additions and 52 deletions

View File

@ -72,7 +72,7 @@ public interface ILogger
LogLevel.Warning => IsWarnEnabled(), LogLevel.Warning => IsWarnEnabled(),
LogLevel.Error => IsErrorEnabled(), LogLevel.Error => IsErrorEnabled(),
LogLevel.Fatal => IsFatalEnabled(), LogLevel.Fatal => IsFatalEnabled(),
_ => throw new ArgumentException($"Level [{level}] not recognized.", nameof(level)), _ => throw new ArgumentException($"Level [{level}] not recognized.", nameof(level))
}; };
} }

View File

@ -3,7 +3,7 @@
namespace GFramework.SourceGenerators.Abstractions.rule; namespace GFramework.SourceGenerators.Abstractions.rule;
/// <summary> /// <summary>
/// 标记该类需要自动实现 IContextAware /// 标记该类需要自动实现 IContextAware
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false)] [AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class ContextAwareAttribute : Attribute public sealed class ContextAwareAttribute : Attribute

View File

@ -3,19 +3,19 @@
namespace GFramework.SourceGenerators.Common.diagnostics; namespace GFramework.SourceGenerators.Common.diagnostics;
/// <summary> /// <summary>
/// 提供通用诊断描述符的静态类 /// 提供通用诊断描述符的静态类
/// </summary> /// </summary>
public static class CommonDiagnostics public static class CommonDiagnostics
{ {
/// <summary> /// <summary>
/// 定义类必须为partial的诊断描述符 /// 定义类必须为partial的诊断描述符
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// 诊断ID: GF001 /// 诊断ID: GF001
/// 诊断消息: "Class '{0}' must be declared partial for code generation" /// 诊断消息: "Class '{0}' must be declared partial for code generation"
/// 分类: GFramework.Common /// 分类: GFramework.Common
/// 严重性: Error /// 严重性: Error
/// 是否启用: true /// 是否启用: true
/// </remarks> /// </remarks>
public static readonly DiagnosticDescriptor ClassMustBePartial = public static readonly DiagnosticDescriptor ClassMustBePartial =
new( new(
@ -24,6 +24,6 @@ public static class CommonDiagnostics
"Class '{0}' must be declared partial for code generation", "Class '{0}' must be declared partial for code generation",
"GFramework.Common", "GFramework.Common",
DiagnosticSeverity.Error, DiagnosticSeverity.Error,
isEnabledByDefault: true true
); );
} }

View File

@ -8,38 +8,38 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace GFramework.SourceGenerators.Common.generator; namespace GFramework.SourceGenerators.Common.generator;
/// <summary> /// <summary>
/// 属性类生成器基类,用于处理带有特定属性的类并生成相应的源代码 /// 属性类生成器基类,用于处理带有特定属性的类并生成相应的源代码
/// </summary> /// </summary>
public abstract class AttributeClassGeneratorBase : IIncrementalGenerator public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
{ {
/// <summary> /// <summary>
/// 获取属性的元数据名称 /// 获取属性的元数据名称
/// </summary> /// </summary>
protected abstract Type AttributeType { get; } protected abstract Type AttributeType { get; }
/// <summary> /// <summary>
/// Attribute 的短名称(不含 Attribute 后缀) /// Attribute 的短名称(不含 Attribute 后缀)
/// 仅用于 Syntax 层宽松匹配 /// 仅用于 Syntax 层宽松匹配
/// </summary> /// </summary>
protected abstract string AttributeShortNameWithoutSuffix { get; } protected abstract string AttributeShortNameWithoutSuffix { get; }
/// <summary> /// <summary>
/// 初始化增量生成器 /// 初始化增量生成器
/// </summary> /// </summary>
/// <param name="context">增量生成器初始化上下文</param> /// <param name="context">增量生成器初始化上下文</param>
public void Initialize(IncrementalGeneratorInitializationContext context) public void Initialize(IncrementalGeneratorInitializationContext context)
{ {
var targets = context.SyntaxProvider.CreateSyntaxProvider( var targets = context.SyntaxProvider.CreateSyntaxProvider(
predicate: (node, _) => (node, _) =>
node is ClassDeclarationSyntax cls && node is ClassDeclarationSyntax cls &&
cls.AttributeLists cls.AttributeLists
.SelectMany(a => a.Attributes) .SelectMany(a => a.Attributes)
.Any(a => a.Name.ToString() .Any(a => a.Name.ToString()
.Contains(AttributeShortNameWithoutSuffix)), .Contains(AttributeShortNameWithoutSuffix)),
transform: static (ctx, t) => static (ctx, t) =>
{ {
var cls = (ClassDeclarationSyntax)ctx.Node; var cls = (ClassDeclarationSyntax)ctx.Node;
var symbol = ctx.SemanticModel.GetDeclaredSymbol(cls, cancellationToken: t); var symbol = ctx.SemanticModel.GetDeclaredSymbol(cls, t);
return (ClassDecl: cls, Symbol: symbol); return (ClassDecl: cls, Symbol: symbol);
} }
) )
@ -59,7 +59,7 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
} }
/// <summary> /// <summary>
/// 执行源代码生成的主要逻辑 /// 执行源代码生成的主要逻辑
/// </summary> /// </summary>
/// <param name="context">源生产上下文</param> /// <param name="context">源生产上下文</param>
/// <param name="classDecl">类声明语法节点</param> /// <param name="classDecl">类声明语法节点</param>
@ -90,7 +90,7 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
#region #region
/// <summary> /// <summary>
/// 验证符号的有效性 /// 验证符号的有效性
/// </summary> /// </summary>
/// <param name="context">源生产上下文</param> /// <param name="context">源生产上下文</param>
/// <param name="syntax">类声明语法节点</param> /// <param name="syntax">类声明语法节点</param>
@ -102,10 +102,12 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
ClassDeclarationSyntax syntax, ClassDeclarationSyntax syntax,
INamedTypeSymbol symbol, INamedTypeSymbol symbol,
AttributeData attr) AttributeData attr)
=> true; {
return true;
}
/// <summary> /// <summary>
/// 生成源代码 /// 生成源代码
/// </summary> /// </summary>
/// <param name="symbol">命名类型符号</param> /// <param name="symbol">命名类型符号</param>
/// <param name="attr">属性数据</param> /// <param name="attr">属性数据</param>
@ -115,28 +117,32 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
AttributeData attr); AttributeData attr);
/// <summary> /// <summary>
/// 获取生成文件的提示名称 /// 获取生成文件的提示名称
/// </summary> /// </summary>
/// <param name="symbol">命名类型符号</param> /// <param name="symbol">命名类型符号</param>
/// <returns>生成文件的提示名称</returns> /// <returns>生成文件的提示名称</returns>
protected virtual string GetHintName(INamedTypeSymbol symbol) protected virtual string GetHintName(INamedTypeSymbol symbol)
=> $"{symbol.Name}.g.cs"; {
return $"{symbol.Name}.g.cs";
}
#endregion #endregion
#region Attribute / Diagnostic #region Attribute / Diagnostic
/// <summary> /// <summary>
/// 获取指定符号的属性数据 /// 获取指定符号的属性数据
/// </summary> /// </summary>
/// <param name="symbol">命名类型符号</param> /// <param name="symbol">命名类型符号</param>
/// <returns>属性数据如果未找到则返回null</returns> /// <returns>属性数据如果未找到则返回null</returns>
protected virtual AttributeData? GetAttribute(INamedTypeSymbol symbol) protected virtual AttributeData? GetAttribute(INamedTypeSymbol symbol)
=> symbol.GetAttributes().FirstOrDefault(a => {
return symbol.GetAttributes().FirstOrDefault(a =>
string.Equals(a.AttributeClass?.ToDisplayString(), AttributeType.FullName, StringComparison.Ordinal)); string.Equals(a.AttributeClass?.ToDisplayString(), AttributeType.FullName, StringComparison.Ordinal));
}
/// <summary> /// <summary>
/// 报告类必须是partial的诊断信息 /// 报告类必须是partial的诊断信息
/// </summary> /// </summary>
/// <param name="context">源生产上下文</param> /// <param name="context">源生产上下文</param>
/// <param name="syntax">类声明语法节点</param> /// <param name="syntax">类声明语法节点</param>
@ -153,7 +159,7 @@ public abstract class AttributeClassGeneratorBase : IIncrementalGenerator
} }
/// <summary> /// <summary>
/// 发出错误信息 /// 发出错误信息
/// </summary> /// </summary>
/// <param name="context">源生产上下文</param> /// <param name="context">源生产上下文</param>
/// <param name="symbol">命名类型符号</param> /// <param name="symbol">命名类型符号</param>

View File

@ -4,14 +4,14 @@ using Microsoft.CodeAnalysis.Testing;
namespace GFramework.SourceGenerators.Tests.core; namespace GFramework.SourceGenerators.Tests.core;
/// <summary> /// <summary>
/// 提供源代码生成器测试的通用功能 /// 提供源代码生成器测试的通用功能
/// </summary> /// </summary>
/// <typeparam name="TGenerator">要测试的源代码生成器类型,必须具有无参构造函数</typeparam> /// <typeparam name="TGenerator">要测试的源代码生成器类型,必须具有无参构造函数</typeparam>
public static class GeneratorTest<TGenerator> public static class GeneratorTest<TGenerator>
where TGenerator : new() where TGenerator : new()
{ {
/// <summary> /// <summary>
/// 运行源代码生成器测试 /// 运行源代码生成器测试
/// </summary> /// </summary>
/// <param name="source">输入的源代码</param> /// <param name="source">输入的源代码</param>
/// <param name="generatedSources">期望生成的源文件集合,包含文件名和内容的元组</param> /// <param name="generatedSources">期望生成的源文件集合,包含文件名和内容的元组</param>
@ -30,10 +30,8 @@ public static class GeneratorTest<TGenerator>
// 添加期望的生成源文件到测试状态中 // 添加期望的生成源文件到测试状态中
foreach (var (filename, content) in generatedSources) foreach (var (filename, content) in generatedSources)
{
test.TestState.GeneratedSources.Add( test.TestState.GeneratedSources.Add(
(typeof(TGenerator), filename, content)); (typeof(TGenerator), filename, content));
}
await test.RunAsync(); await test.RunAsync();
} }

View File

@ -5,14 +5,14 @@ using NUnit.Framework;
namespace GFramework.SourceGenerators.Tests.rule; namespace GFramework.SourceGenerators.Tests.rule;
/// <summary> /// <summary>
/// 测试ContextAwareGenerator源代码生成器的功能 /// 测试ContextAwareGenerator源代码生成器的功能
/// </summary> /// </summary>
[TestFixture] [TestFixture]
public class ContextAwareGeneratorTests public class ContextAwareGeneratorTests
{ {
/// <summary> /// <summary>
/// 测试ContextAware代码生成功能 /// 测试ContextAware代码生成功能
/// 验证当使用[ContextAware]特性标记的类能够正确生成上下文感知的相关代码 /// 验证当使用[ContextAware]特性标记的类能够正确生成上下文感知的相关代码
/// </summary> /// </summary>
/// <returns>异步任务</returns> /// <returns>异步任务</returns>
[Test] [Test]

View File

@ -3,7 +3,7 @@
### New Rules ### New Rules
Rule ID | Category | Severity | Notes Rule ID | Category | Severity | Notes
---------------------|----------------------------------|----------|------------------------ ----------------|----------------------------------|----------|------------------------
GF_Logging_001 | GFramework.Godot.Logging | Warning | LoggerDiagnostics GF_Logging_001 | GFramework.Godot.Logging | Warning | LoggerDiagnostics
GF_Rule_001 | GFramework.SourceGenerators.rule | Error | ContextAwareDiagnostic GF_Rule_001 | GFramework.SourceGenerators.rule | Error | ContextAwareDiagnostic

View File

@ -3,19 +3,19 @@
namespace GFramework.SourceGenerators.diagnostics; namespace GFramework.SourceGenerators.diagnostics;
/// <summary> /// <summary>
/// 提供与上下文感知相关的诊断规则定义 /// 提供与上下文感知相关的诊断规则定义
/// </summary> /// </summary>
public static class ContextAwareDiagnostic public static class ContextAwareDiagnostic
{ {
/// <summary> /// <summary>
/// 定义类必须实现IContextAware接口的诊断规则 /// 定义类必须实现IContextAware接口的诊断规则
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// 诊断ID: GF_Rule_001 /// 诊断ID: GF_Rule_001
/// 诊断类别: GFramework.SourceGenerators.rule /// 诊断类别: GFramework.SourceGenerators.rule
/// 严重级别: 错误 /// 严重级别: 错误
/// 启用状态: true /// 启用状态: true
/// 消息格式: "Class '{0}' must implement IContextAware" /// 消息格式: "Class '{0}' must implement IContextAware"
/// </remarks> /// </remarks>
public static readonly DiagnosticDescriptor ClassMustImplementIContextAware = new( public static readonly DiagnosticDescriptor ClassMustImplementIContextAware = new(
"GF_Rule_001", "GF_Rule_001",

View File

@ -14,17 +14,17 @@ namespace GFramework.SourceGenerators.rule;
public sealed class ContextAwareGenerator : AttributeClassGeneratorBase public sealed class ContextAwareGenerator : AttributeClassGeneratorBase
{ {
/// <summary> /// <summary>
/// 使用强类型 Attribute替代字符串 /// 使用强类型 Attribute替代字符串
/// </summary> /// </summary>
protected override Type AttributeType => typeof(ContextAwareAttribute); protected override Type AttributeType => typeof(ContextAwareAttribute);
/// <summary> /// <summary>
/// 仅用于 Syntax 粗筛选 /// 仅用于 Syntax 粗筛选
/// </summary> /// </summary>
protected override string AttributeShortNameWithoutSuffix => "ContextAware"; protected override string AttributeShortNameWithoutSuffix => "ContextAware";
/// <summary> /// <summary>
/// 额外语义校验:必须实现 IContextAware /// 额外语义校验:必须实现 IContextAware
/// </summary> /// </summary>
protected override bool ValidateSymbol( protected override bool ValidateSymbol(
SourceProductionContext context, SourceProductionContext context,
@ -46,7 +46,7 @@ public sealed class ContextAwareGenerator : AttributeClassGeneratorBase
} }
/// <summary> /// <summary>
/// 生成源码 /// 生成源码
/// </summary> /// </summary>
protected override string Generate( protected override string Generate(
INamedTypeSymbol symbol, INamedTypeSymbol symbol,
@ -81,8 +81,10 @@ public sealed class ContextAwareGenerator : AttributeClassGeneratorBase
} }
/// <summary> /// <summary>
/// 自定义生成文件名 /// 自定义生成文件名
/// </summary> /// </summary>
protected override string GetHintName(INamedTypeSymbol symbol) protected override string GetHintName(INamedTypeSymbol symbol)
=> $"{symbol.Name}.ContextAware.g.cs"; {
return $"{symbol.Name}.ContextAware.g.cs";
}
} }