GFramework/GFramework.Godot.SourceGenerators/Diagnostics/AutoRegisterExportedCollectionsDiagnostics.cs
GeWuYou be928718e3 feat: 增强 AutoSceneGenerator 与 AutoRegisterExportedCollectionsGenerator 的验证与安全机制
### AutoSceneGenerator
- 引入保留成员名称集合(GeneratedMemberNames),包含:
  - SceneKeyStr
  - __autoSceneBehavior_Generated
- 实现 ReportGeneratedMemberConflicts 方法:
  - 检测用户定义成员与生成成员冲突
  - 提供清晰的诊断信息
- 在生成流程中集成冲突检测,避免重复成员导致的编译错误

### AutoRegisterExportedCollectionsGenerator
- 增强集合注册生成器的验证逻辑:
  - 新增诊断 GF_AutoExport_006:导出集合成员必须为实例可读成员
  - 新增诊断 GF_AutoExport_007:注册表成员必须为实例可读成员
- 实现 IsInstanceReadableMember 方法:
  - 校验成员为非静态字段或可读属性
- 修复符号访问性检查:
  - 确保注册方法对所有者类型可访问
- 优化生成逻辑:
  - 过滤重复的部分类声明,仅生成一次源码

### Tests
- AutoSceneGenerator
  - 覆盖保留成员冲突场景:
    - SceneKeyStr 冲突
    - __autoSceneBehavior_Generated 冲突

- AutoRegisterExportedCollectionsGenerator
  - 覆盖完整验证逻辑:
    - 不可读成员 → GF_AutoExport_006 / 007
    - 方法不可访问 → GF_AutoExport_003
    - 多个 partial class → 仅生成一个源文件
2026-04-13 13:04:00 +08:00

93 lines
3.9 KiB
C#

using GFramework.SourceGenerators.Common.Constants;
namespace GFramework.Godot.SourceGenerators.Diagnostics;
/// <summary>
/// 定义导出集合自动注册生成器使用的诊断描述符。
/// </summary>
/// <remarks>
/// 这些规则用于在源生成阶段验证集合成员、注册目标以及元素类型推导,
/// 避免把配置错误延后到生成代码编译或运行时才暴露。
/// </remarks>
internal static class AutoRegisterExportedCollectionsDiagnostics
{
private const string Category = $"{PathContests.GodotNamespace}.SourceGenerators.Registration";
/// <summary>
/// 报告自动注册生成器不支持嵌套类型。
/// </summary>
public static readonly DiagnosticDescriptor NestedClassNotSupported = new(
"GF_AutoExport_001",
"AutoRegisterExportedCollections does not support nested classes",
"AutoRegisterExportedCollections does not support nested class '{0}'",
Category,
DiagnosticSeverity.Error,
true);
/// <summary>
/// 报告特性引用的注册表成员在宿主类型上不存在。
/// </summary>
public static readonly DiagnosticDescriptor RegistryMemberNotFound = new(
"GF_AutoExport_002",
"Registry member was not found",
"Member '{0}' referenced by exported collection '{1}' was not found on '{2}'",
Category,
DiagnosticSeverity.Error,
true);
/// <summary>
/// 报告注册表上未找到与集合元素类型兼容的注册方法。
/// </summary>
public static readonly DiagnosticDescriptor RegisterMethodNotFound = new(
"GF_AutoExport_003",
"Register method was not found",
"Method '{0}' was not found on registry member '{1}' for exported collection '{2}'",
Category,
DiagnosticSeverity.Error,
true);
/// <summary>
/// 报告被标记成员不是可枚举集合,因此无法执行批量注册。
/// </summary>
public static readonly DiagnosticDescriptor CollectionTypeMustBeEnumerable = new(
"GF_AutoExport_004",
"Exported collection must be enumerable",
"Member '{0}' must be enumerable to use RegisterExportedCollection",
Category,
DiagnosticSeverity.Error,
true);
/// <summary>
/// 报告集合元素类型无法在编译期推导,因此无法安全匹配注册方法。
/// </summary>
public static readonly DiagnosticDescriptor CollectionElementTypeCouldNotBeInferred = new(
"GF_AutoExport_005",
"Exported collection element type could not be inferred",
"Member '{0}' must expose a generic enumerable element type to use RegisterExportedCollection safely",
Category,
DiagnosticSeverity.Error,
true);
/// <summary>
/// 报告被标记为导出集合的成员不是实例可读成员,因此无法生成 <c>this.&lt;member&gt;</c> 访问代码。
/// </summary>
public static readonly DiagnosticDescriptor CollectionMemberMustBeInstanceReadable = new(
"GF_AutoExport_006",
"Exported collection member must be an instance readable member",
"Member '{0}' must be an instance field or readable non-indexer instance property to use RegisterExportedCollection",
Category,
DiagnosticSeverity.Error,
true);
/// <summary>
/// 报告注册表成员不是实例可读成员,因此生成器无法安全读取并调用注册方法。
/// </summary>
public static readonly DiagnosticDescriptor RegistryMemberMustBeInstanceReadable = new(
"GF_AutoExport_007",
"Registry member must be an instance readable member",
"Registry member '{0}' referenced by exported collection '{1}' must be an instance field or readable non-indexer instance property",
Category,
DiagnosticSeverity.Error,
true);
}