@@ -132,7 +132,7 @@ defmodule Protox.Parse do
132
132
_ ->
133
133
# If FileOptions and other related message have been found, we also need
134
134
# to compile their associated enums.
135
- { file_options_optimize_enum , other_enums } =
135
+ { file_options_enums , other_enums } =
136
136
Map . split ( definition . enums_schemas , [
137
137
Google.Protobuf.FeatureSet.EnumType ,
138
138
Google.Protobuf.FeatureSet.FieldPresence ,
@@ -143,10 +143,19 @@ defmodule Protox.Parse do
143
143
Google.Protobuf.FileOptions.OptimizeMode
144
144
] )
145
145
146
+ # FileOptions can also contain nested messages and enums, which we need to compile as well.
147
+ nested_in_file_options = find_enums_and_messages ( definition . messages_schemas , Google.Protobuf.FileOptions )
148
+ messages_used_in_file_options = Map . take ( definition . messages_schemas , nested_in_file_options . messages )
149
+ enums_used_in_file_options = Map . take ( definition . enums_schemas , nested_in_file_options . enums )
150
+
151
+ # Remove those messages and enums from the returned definition to avoid compiling them twice.
152
+ other_messages = Map . drop ( other_messages , nested_in_file_options . messages )
153
+ other_enums = Map . drop ( other_enums , nested_in_file_options . enums )
154
+
146
155
# Compile the needed modules.
147
156
% Definition {
148
- messages_schemas: file_options_messages ,
149
- enums_schemas: file_options_optimize_enum
157
+ messages_schemas: Map . merge ( file_options_messages , messages_used_in_file_options ) ,
158
+ enums_schemas: Map . merge ( file_options_enums , enums_used_in_file_options )
150
159
}
151
160
|> Protox.Define . define ( )
152
161
|> Code . eval_quoted ( )
@@ -155,7 +164,7 @@ defmodule Protox.Parse do
155
164
# Also, we transform this FileOptions into a bare map so as to not depend
156
165
# on the FileOptions type which is not necessary for the end user.
157
166
other_messages =
158
- for { msg_name , msg } <- other_messages , into: % { } do
167
+ for { msg_name , msg } when msg . file_options != nil <- other_messages , into: % { } do
159
168
file_options =
160
169
msg . file_options
161
170
|> Protox.Google.Protobuf.FileOptions . encode! ( )
@@ -189,6 +198,23 @@ defmodule Protox.Parse do
189
198
end
190
199
end
191
200
201
+ defp find_enums_and_messages ( messages_schemas , msg_name , acc \\ % { enums: [ ] , messages: [ ] } ) do
202
+ Enum . reduce ( messages_schemas [ msg_name ] . fields , acc , fn
203
+ { _field_name , % Protox.Field { type: { :message , sub_msg_name } } } , acc ->
204
+ find_enums_and_messages (
205
+ messages_schemas ,
206
+ sub_msg_name ,
207
+ _new_acc = Map . update! ( acc , :messages , & [ sub_msg_name | & 1 ] )
208
+ )
209
+
210
+ { _field_name , % Protox.Field { type: { :enum , sub_enum_name } } } , acc ->
211
+ Map . update! ( acc , :enums , & [ sub_enum_name | & 1 ] )
212
+
213
+ _field , acc ->
214
+ acc
215
+ end )
216
+ end
217
+
192
218
defp resolve_types ( % Field { type: { :type_to_resolve , tname } } = field , enums ) do
193
219
if Map . has_key? ( enums , tname ) do
194
220
% { field | type: { :enum , tname } }
0 commit comments