@@ -116,9 +116,68 @@ defmodule GrpcReflection.Service.State do
116116 end
117117 end
118118
119- def group_symbols_by_namespace ( % __MODULE__ { } = state ) do
120- # group symbols by namespace and combine
121- # IO.inspect(state)
122- state
119+ def shrink_cycles ( % __MODULE__ { } = state ) do
120+ new_state =
121+ state
122+ |> GrpcReflection.Service.Cycle . get_cycles ( )
123+ |> Enum . reduce ( state , fn filenames , acc ->
124+ files = filenames |> Enum . map ( & acc . files [ & 1 ] ) |> Enum . reject ( & is_nil / 1 )
125+
126+ if length ( files ) < 2 do
127+ acc
128+ else
129+ update_with_combined ( acc , combine_file_descriptors ( files ) , filenames )
130+ end
131+ end )
132+
133+ if new_state == state , do: state , else: shrink_cycles ( new_state )
134+ end
135+
136+ defp update_with_combined ( state , combined_file , combined_filenames ) do
137+ new_files =
138+ state . files
139+ |> Map . drop ( combined_filenames )
140+ |> Map . new ( fn { filename , descriptor } ->
141+ if Enum . any? ( descriptor . dependency , & ( & 1 in combined_filenames ) ) do
142+ updated_deps = ( descriptor . dependency -- combined_filenames ) ++ [ combined_file . name ]
143+ { filename , % { descriptor | dependency: Enum . uniq ( updated_deps ) } }
144+ else
145+ { filename , descriptor }
146+ end
147+ end )
148+ |> Map . put ( combined_file . name , combined_file )
149+
150+ new_symbols =
151+ Map . new ( state . symbols , fn { symbol , filename } ->
152+ if filename in combined_filenames do
153+ { symbol , combined_file . name }
154+ else
155+ { symbol , filename }
156+ end
157+ end )
158+
159+ % { state | files: new_files , symbols: new_symbols }
160+ end
161+
162+ defp combine_file_descriptors ( file_descriptors ) do
163+ combined_names = Enum . map ( file_descriptors , & & 1 . name )
164+ canonical_name = Enum . min ( combined_names )
165+
166+ Enum . reduce (
167+ file_descriptors ,
168+ % Google.Protobuf.FileDescriptorProto { name: canonical_name } ,
169+ fn descriptor , acc ->
170+ % {
171+ acc
172+ | syntax: acc . syntax || descriptor . syntax ,
173+ package: acc . package || descriptor . package ,
174+ message_type: Enum . uniq ( acc . message_type ++ descriptor . message_type ) ,
175+ service: Enum . uniq ( acc . service ++ descriptor . service ) ,
176+ enum_type: Enum . uniq ( acc . enum_type ++ descriptor . enum_type ) ,
177+ dependency: Enum . uniq ( acc . dependency ++ ( descriptor . dependency -- combined_names ) ) ,
178+ extension: Enum . uniq ( acc . extension ++ descriptor . extension )
179+ }
180+ end
181+ )
123182 end
124183end
0 commit comments