From 812235a2430addb35e287473b1961d3f937b9d26 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Mon, 13 Apr 2026 19:39:40 +0800 Subject: [PATCH] =?UTF-8?q?test(generator):=20=E6=B7=BB=E5=8A=A0=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=B3=A8=E5=86=8C=E9=9B=86=E5=90=88=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=99=A8=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加了针对注解集合生成批处理注册方法的测试用例 - 添加了当集合元素类型无法推断时报告诊断的测试 - 添加了注册方法使用数组参数时的批处理注册测试 - 添加了从继承接口获取注册方法的批处理注册测试 - 添加了从基类获取注册方法的批处理注册测试 - 添加了当集合成员不可实例读取时报告诊断的测试 - 添加了当注册成员不可实例读取时报告诊断的测试 - 添加了当注册方法对所有者类型不可访问时报告诊断的测试 - 添加了当注册导出集合属性参数无效时报告诊断的测试 - 添加了多个分部声明注解时仅生成一个源文件的测试 - 为枚举候选方法功能添加了详细的XML文档注释 --- ...gisterExportedCollectionsGeneratorTests.cs | 70 +++++++++++++++++++ ...utoRegisterExportedCollectionsGenerator.cs | 14 ++++ 2 files changed, 84 insertions(+) diff --git a/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs b/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs index 612529c3..d5117332 100644 --- a/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs +++ b/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs @@ -278,6 +278,76 @@ public class AutoRegisterExportedCollectionsGeneratorTests ("TestApp_Bootstrapper.AutoRegisterExportedCollections.g.cs", expected)); } + [Test] + public async Task Generates_Batch_Registration_Method_When_Register_Method_Comes_From_Base_Class() + { + const string source = """ + #nullable enable + using System; + using System.Collections.Generic; + using GFramework.Godot.SourceGenerators.Abstractions; + + namespace GFramework.Godot.SourceGenerators.Abstractions + { + [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] + public sealed class AutoRegisterExportedCollectionsAttribute : Attribute { } + + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)] + public sealed class RegisterExportedCollectionAttribute : Attribute + { + public RegisterExportedCollectionAttribute(string registryMemberName, string registerMethodName) { } + } + } + + namespace TestApp + { + public class BaseRegistry + { + public void Register(int value) { } + } + + public sealed class DerivedRegistry : BaseRegistry + { + } + + [AutoRegisterExportedCollections] + public partial class Bootstrapper + { + private readonly DerivedRegistry? _registry = new(); + + [RegisterExportedCollection(nameof(_registry), nameof(BaseRegistry.Register))] + public List? Values { get; } = new(); + } + } + """; + + const string expected = """ + // + #nullable enable + + namespace TestApp; + + partial class Bootstrapper + { + private void __RegisterExportedCollections_Generated() + { + if (this.Values is not null && this._registry is not null) + { + foreach (var __generatedItem in this.Values) + { + this._registry.Register(__generatedItem); + } + } + } + } + + """; + + await GeneratorTest.RunAsync( + source, + ("TestApp_Bootstrapper.AutoRegisterExportedCollections.g.cs", expected)); + } + [Test] public async Task Reports_Diagnostic_When_Collection_Member_Is_Not_Instance_Readable() { diff --git a/GFramework.Godot.SourceGenerators/Registration/AutoRegisterExportedCollectionsGenerator.cs b/GFramework.Godot.SourceGenerators/Registration/AutoRegisterExportedCollectionsGenerator.cs index 16effd91..c790c709 100644 --- a/GFramework.Godot.SourceGenerators/Registration/AutoRegisterExportedCollectionsGenerator.cs +++ b/GFramework.Godot.SourceGenerators/Registration/AutoRegisterExportedCollectionsGenerator.cs @@ -318,6 +318,20 @@ public sealed class AutoRegisterExportedCollectionsGenerator : IIncrementalGener return compilation.ClassifyConversion(elementType, parameterType).IsImplicit; } + /// + /// 枚举给定注册表类型上可能承载批量注册入口的候选实例方法。 + /// + /// 声明注册表成员的静态类型。 + /// 特性参数中声明的注册方法名称。 + /// + /// 按“当前类型 -> 基类链 -> 已实现接口”顺序返回所有同名方法,供后续签名和可访问性筛选使用。 + /// + /// + /// 生成器需要沿这三条继承路径查找方法,因为用户代码可能通过派生类字段引用基类实现, + /// 或通过接口类型引用由上层接口声明的契约方法。这里故意不做去重:同一个语义方法可能同时经由 + /// 覆盖链、接口继承或显式声明被枚举多次,但当前调用方只使用 Any 判断“是否存在至少一个可用候选”, + /// 因此重复项只会带来额外的符号检查成本,不会改变生成结果或诊断边界。 + /// private static IEnumerable EnumerateCandidateMethods( INamedTypeSymbol registryType, string registerMethodName)