From 5e1e16f86e005b51fbfb22148bcf4dcdf04b21d2 Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Mon, 13 Apr 2026 19:17:06 +0800 Subject: [PATCH] =?UTF-8?q?feat(generator):=20=E6=B7=BB=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?=E7=BB=A7=E6=89=BF=E5=B1=82=E6=AC=A1=E7=BB=93=E6=9E=84=E4=B8=AD?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E6=96=B9=E6=B3=95=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现 EnumerateCandidateMethods 方法以搜索基类和接口中的注册方法 - 修改 AutoRegisterExportedCollectionsGenerator 以支持从继承链中查找兼容的注册方法 - 添加完整的单元测试覆盖继承、接口实现和泛型场景 - 修复静态成员和不可访问方法的诊断报告功能 - 增强源代码生成器对复杂继承结构的支持能力 --- ...gisterExportedCollectionsGeneratorTests.cs | 78 +++++++++++++++++++ ...utoRegisterExportedCollectionsGenerator.cs | 23 +++++- 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs b/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs index 1c4927a4..612529c3 100644 --- a/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs +++ b/GFramework.Godot.SourceGenerators.Tests/Registration/AutoRegisterExportedCollectionsGeneratorTests.cs @@ -200,6 +200,84 @@ public class AutoRegisterExportedCollectionsGeneratorTests ("TestApp_Bootstrapper.AutoRegisterExportedCollections.g.cs", expected)); } + [Test] + public async Task Generates_Batch_Registration_Method_When_Register_Method_Comes_From_Inherited_Interface() + { + 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 interface IKeyValue + { + } + + public interface IRegistry + { + void Registry(IKeyValue mapping); + } + + public interface IAssetRegistry : IRegistry + { + } + + public sealed class IntConfig : IKeyValue + { + } + + [AutoRegisterExportedCollections] + public partial class Bootstrapper + { + private readonly IAssetRegistry? _registry = null; + + [RegisterExportedCollection(nameof(_registry), "Registry")] + 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.Registry(__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 df0c433b..16effd91 100644 --- a/GFramework.Godot.SourceGenerators/Registration/AutoRegisterExportedCollectionsGenerator.cs +++ b/GFramework.Godot.SourceGenerators/Registration/AutoRegisterExportedCollectionsGenerator.cs @@ -268,8 +268,7 @@ public sealed class AutoRegisterExportedCollectionsGenerator : IIncrementalGener return false; } - var hasCompatibleMethod = registryType.GetMembers(registerMethodName) - .OfType() + var hasCompatibleMethod = EnumerateCandidateMethods(registryType, registerMethodName) .Any(method => !method.IsStatic && method.Parameters.Length == 1 && @@ -319,6 +318,26 @@ public sealed class AutoRegisterExportedCollectionsGenerator : IIncrementalGener return compilation.ClassifyConversion(elementType, parameterType).IsImplicit; } + private static IEnumerable EnumerateCandidateMethods( + INamedTypeSymbol registryType, + string registerMethodName) + { + foreach (var method in registryType.GetMembers(registerMethodName).OfType()) + yield return method; + + for (var baseType = registryType.BaseType; baseType is not null; baseType = baseType.BaseType) + { + foreach (var method in baseType.GetMembers(registerMethodName).OfType()) + yield return method; + } + + foreach (var interfaceType in registryType.AllInterfaces) + { + foreach (var method in interfaceType.GetMembers(registerMethodName).OfType()) + yield return method; + } + } + private static bool TryGetRegistrationAttributeArguments( SourceProductionContext context, ISymbol collectionMember,