From 1da3959c1ffdaa8172069b6dc5b8bb545e9872fb Mon Sep 17 00:00:00 2001 From: Jonathan Baker Date: Tue, 7 Jul 2026 15:45:34 -0400 Subject: [PATCH] Add FileDescriptor#imports and #public_imports Resolve a file's dependency filenames to their FileDescriptors so generators can follow imports (e.g. to emit require/import statements). #public_imports returns the subset declared with 'import public'. Imports not included in the request are omitted. Mark article.proto's comment.proto import as public in the fixtures (and regenerate) to cover public imports. --- lib/proto_plugin/file_descriptor.rb | 28 ++++++++++++++++++++++ test/fixtures/blog.cgr | Bin 18159 -> 18185 bytes test/fixtures/blog.fds | Bin 2706 -> 2708 bytes test/fixtures/blog/article.proto | 2 +- test/proto_plugin/file_descriptor_test.rb | 27 +++++++++++++++++++++ 5 files changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/proto_plugin/file_descriptor.rb b/lib/proto_plugin/file_descriptor.rb index 74d3eab..de4f2b9 100644 --- a/lib/proto_plugin/file_descriptor.rb +++ b/lib/proto_plugin/file_descriptor.rb @@ -108,6 +108,34 @@ def services end end + # The files imported by this file, resolved to their descriptors. + # + # Imports that were not included in the request are omitted. + # + # @return [Array] + # + # @see https://github.com/protocolbuffers/protobuf/blob/v28.2/src/google/protobuf/descriptor.proto#L100 + # Google::Protobuf::FileDescriptorProto#dependency + def imports + @imports ||= @descriptor.dependency.filter_map do |name| + @context.file_by_filename(name) + end + end + + # The subset of {#imports} that were declared with `import public`, resolved + # to their descriptors. + # + # @return [Array] + # + # @see https://github.com/protocolbuffers/protobuf/blob/v28.2/src/google/protobuf/descriptor.proto#L103 + # Google::Protobuf::FileDescriptorProto#public_dependency + def public_imports + @public_imports ||= @descriptor.public_dependency.filter_map do |i| + name = @descriptor.dependency[i] + @context.file_by_filename(name) if name + end + end + private # Field numbers of the relevant repeated fields within their parent diff --git a/test/fixtures/blog.cgr b/test/fixtures/blog.cgr index fea96d63834240a4f270a1cb68ed5a9b567249cd..19065c64c220b097a026902bfc676b7a8da19020 100644 GIT binary patch delta 87 zcmaFg%h=h+xIsdR@%m;-rQeK<7bmZ?GUAcr;^boDVi00xW9Qxc&`N}bDS&Zvj7F#c L5z4;W{bC0IPvRH* delta 59 wcmeC|V|?GsxIsdR@zm!17QY!8k4@ffWyC1H`KOf#%jQgtPywtG{Pw@t0nU9FI{*Lx diff --git a/test/fixtures/blog.fds b/test/fixtures/blog.fds index 5598f216b0f0c9cfcd23f53bb1bce49ea68c9d37..3a4741af0145b059d21d21967f810c77fb97a891 100644 GIT binary patch delta 22 ecmbOvIz@ED5f;Yg%|}^&F){@(Zr;y!nHd0M9|&at delta 19 bcmbOtI!ScH5f;YA%|}^&F>XG{c9|IfPlE^& diff --git a/test/fixtures/blog/article.proto b/test/fixtures/blog/article.proto index d936a63..7d31789 100644 --- a/test/fixtures/blog/article.proto +++ b/test/fixtures/blog/article.proto @@ -4,7 +4,7 @@ package proto_plugin.fixtures; import "google/protobuf/timestamp.proto"; -import "comment.proto"; +import public "comment.proto"; // An article published on the blog. message Article { diff --git a/test/proto_plugin/file_descriptor_test.rb b/test/proto_plugin/file_descriptor_test.rb index 45c9150..3fdbbf5 100644 --- a/test/proto_plugin/file_descriptor_test.rb +++ b/test/proto_plugin/file_descriptor_test.rb @@ -47,6 +47,33 @@ def test_services assert_instance_of(ServiceDescriptor, service_one) end + def test_imports + file = @context.file_by_filename("article.proto") + + assert_equal( + ["google/protobuf/timestamp.proto", "comment.proto"], + file.imports.map(&:name), + ) + + file.imports.each do |i| + assert_instance_of(FileDescriptor, i) + end + end + + def test_public_imports + file = @context.file_by_filename("article.proto") + + assert_equal(["comment.proto"], file.public_imports.map(&:name)) + assert_instance_of(FileDescriptor, file.public_imports.first) + end + + def test_imports_empty_without_dependencies + file = @context.file_by_filename("category.proto") + + assert_empty(file.imports) + assert_empty(file.public_imports) + end + def test_namespace_without_package file = FileDescriptor.new(@context, Google::Protobuf::FileDescriptorProto.new( name: "sample.proto",