@@ -158,14 +158,56 @@ defmodule Protobuf.Protoc.CLI do
158158 Context . t ( )
159159 def find_types ( % Context { } = ctx , descs , files_to_generate )
160160 when is_list ( descs ) and is_list ( files_to_generate ) do
161- global_type_mapping =
161+ base_mapping =
162162 Map . new ( descs , fn % Google.Protobuf.FileDescriptorProto { name: filename } = desc ->
163163 { filename , find_types_in_proto ( ctx , desc , files_to_generate ) }
164164 end )
165165
166+ # `import public` re-exports types from the imported file. A file that
167+ # depends on `shared.proto` should see types from anything `shared.proto`
168+ # publicly imports (transitively). We fold those types into each file's
169+ # mapping here so `get_dep_type_mapping/3` keeps working unchanged.
170+ public_deps_by_file =
171+ Map . new ( descs , fn % Google.Protobuf.FileDescriptorProto { } = desc ->
172+ deps = desc . dependency
173+ public_deps = Enum . map ( desc . public_dependency , & Enum . at ( deps , & 1 ) )
174+ { desc . name , public_deps }
175+ end )
176+
177+ global_type_mapping =
178+ Map . new ( base_mapping , fn { filename , mapping } ->
179+ transitive =
180+ collect_public_deps ( [ filename ] , public_deps_by_file , MapSet . new ( [ filename ] ) )
181+ |> MapSet . delete ( filename )
182+
183+ merged =
184+ Enum . reduce ( transitive , mapping , fn other , acc ->
185+ Map . merge ( acc , Map . get ( base_mapping , other , % { } ) )
186+ end )
187+
188+ { filename , merged }
189+ end )
190+
166191 % { ctx | global_type_mapping: global_type_mapping }
167192 end
168193
194+ defp collect_public_deps ( [ ] , _public_deps_by_file , visited ) , do: visited
195+
196+ defp collect_public_deps ( [ filename | rest ] , public_deps_by_file , visited ) do
197+ deps = Map . get ( public_deps_by_file , filename , [ ] )
198+
199+ { new_deps , visited } =
200+ Enum . reduce ( deps , { [ ] , visited } , fn dep , { to_visit , visited } ->
201+ if MapSet . member? ( visited , dep ) do
202+ { to_visit , visited }
203+ else
204+ { [ dep | to_visit ] , MapSet . put ( visited , dep ) }
205+ end
206+ end )
207+
208+ collect_public_deps ( new_deps ++ rest , public_deps_by_file , visited )
209+ end
210+
169211 defp find_types_in_proto (
170212 % Context { } = ctx ,
171213 % Google.Protobuf.FileDescriptorProto { } = desc ,
0 commit comments