Skip to content

Commit ca6444e

Browse files
Don't emit unnecessary functions with no_gen_decoders/encoders
The automatically generated translators for map<_,_> type fields got unnecessarily included when options {gen_decoders,false} or {gen_encoders,false} (-no_gen_decoders or -no_gen_encoders) were set, causing compilation warnings about unused functions. Fix this.
1 parent 587e73e commit ca6444e

3 files changed

Lines changed: 246 additions & 129 deletions

File tree

src/gpb_analyzer.erl

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@
3535
%% -- analysis -----------------------------------------------------
3636

3737
analyze_defs(Defs, Sources, Renamings, Opts) ->
38+
DoEncoders = gpb_lib:get_gen_encoders(Opts),
39+
DoDecoders = gpb_lib:get_gen_decoders(Opts),
3840
ProtoDefsVsnElem = find_or_make_proto_defs_version_elem(Defs),
3941
MapTypes = find_map_types(Defs),
40-
MapsAsMsgs = map_types_to_msgs(MapTypes),
42+
MapsAsMsgs = if DoEncoders; DoDecoders -> map_types_to_msgs(MapTypes);
43+
true -> []
44+
end,
4145
DMapsAsMsgs = map_types_to_msgs_for_decoding(MapTypes),
4246
MapMsgEnums = enums_for_maps_as_msgs(MapTypes, Defs),
4347
Translations = compute_translations(Defs, Opts),
@@ -471,6 +475,9 @@ remove_empty_translations(D) ->
471475
dict:filter(fun(_Key, Ops) -> Ops /= [] end, D).
472476

473477
compute_map_translations(Defs, Opts) ->
478+
DoMergers = gpb_lib:get_gen_mergers(Opts),
479+
DoEncoders = gpb_lib:get_gen_encoders(Opts),
480+
DoDecoders = gpb_lib:get_gen_decoders(Opts),
474481
MapInfos =
475482
gpb_lib:fold_msg_fields(
476483
fun(MsgName, #?gpb_field{name=FName, type={map,KType,VType}}, Acc) ->
@@ -483,7 +490,9 @@ compute_map_translations(Defs, Opts) ->
483490
MapFieldFmt = gpb_lib:get_2tuples_or_maps_for_maptype_fields_by_opts(Opts),
484491
dict_from_translation_list(
485492
lists:append(
486-
[mk_map_transls(MsgName, FName, KeyType, ValueType, MapFieldFmt)
493+
[maybe_prune_translations(
494+
mk_map_transls(MsgName, FName, KeyType, ValueType, MapFieldFmt),
495+
DoEncoders, DoDecoders, DoMergers)
487496
|| {{MsgName, FName}, {KeyType, ValueType}} <- MapInfos])).
488497

489498
mk_map_transls(MsgName, FName, KeyType, ValueType, '2tuples')->
@@ -513,6 +522,35 @@ mk_map_transls(MsgName, FName, _KeyType, ValueType, maps)->
513522
{decode_repeated_finalize, {id, ['$1', '$user_data']}},
514523
{merge, {mt_merge_maps_m, ['$1', '$2']}}]}].
515524

525+
maybe_prune_translations(Transls, true, true, true) -> % common case fast path
526+
Transls;
527+
maybe_prune_translations(Transls, DoEncoders, DoDecoders, DoMergers) ->
528+
lists:filtermap(
529+
fun({Path, Transls0}) ->
530+
Transls1 =
531+
if DoEncoders -> Transls0;
532+
true -> delete_transl_ops([encode], Transls0)
533+
end,
534+
Transls2 =
535+
if DoDecoders -> Transls1;
536+
true -> delete_transl_ops([decode_init_default,
537+
decode_repeated_add_elem,
538+
decode_repeated_finalize],
539+
Transls1)
540+
end,
541+
Transls3 =
542+
if DoMergers -> Transls2;
543+
true -> delete_transl_ops([merge], Transls2)
544+
end,
545+
if Transls3 == [] -> false;
546+
Transls3 /= [] -> {true, {Path, Transls3}}
547+
end
548+
end,
549+
Transls).
550+
551+
delete_transl_ops(Ops, Transls) ->
552+
lists:foldl(fun(Op, Acc) -> lists:keydelete(Op, 1, Acc) end, Transls, Ops).
553+
516554
compute_type_translations(Defs, Opts) ->
517555
TypeTranslations =
518556
lists:foldl(fun({translate_type, {Type, Transls}}, Acc) ->

src/gpb_gen_translators.erl

Lines changed: 141 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -382,136 +382,150 @@ format_default_translators(AnRes, Opts) ->
382382

383383
format_default_map_translators(#anres{map_types=MapTypes,
384384
map_value_types=MVT}=AnRes, Opts) ->
385+
DoMergers = gpb_lib:get_gen_mergers(Opts),
386+
DoEncoders = gpb_lib:get_gen_encoders(Opts),
387+
DoDecoders = gpb_lib:get_gen_decoders(Opts),
385388
HaveMaps = sets:size(MapTypes) > 0,
386389
{HaveMapSubmsgs, HaveMapNonSubmsgs} = MVT,
390+
{M,K,V} = {?expr(M), ?expr(K), ?expr(V)},
387391
[%% Auxiliary helpers in case of fields of type map<_,_>
388-
[case gpb_lib:get_2tuples_or_maps_for_maptype_fields_by_opts(Opts) of
389-
'2tuples' ->
390-
[inline_attr(mt_maptuple_to_pseudomsg_r,2),
391-
gpb_codegen:format_fn(
392-
mt_maptuple_to_pseudomsg_r,
393-
fun({K,V},RName) -> {RName,K,V} end),
394-
"\n",
395-
inline_attr(mt_empty_map_r,0),
396-
gpb_codegen:format_fn(
397-
mt_empty_map_r,
398-
fun() -> [] end),
399-
[[inline_attr(mt_add_item_r,2),
400-
gpb_codegen:format_fn(
401-
mt_add_item_r,
402-
fun({_RName,K,V}, Acc) -> [{K,V} | Acc] end),
403-
"\n"]
404-
|| HaveMapNonSubmsgs],
405-
[[inline_attr(mt_add_item_r_verify_value,2),
406-
gpb_codegen:format_fn(
407-
mt_add_item_r_verify_value,
408-
fun({_,_,undefined}, _) -> error({gpb_error, missing_value});
409-
({_RName,K,V}, Acc) -> [{K,V} | Acc]
410-
end),
411-
"\n"]
412-
|| HaveMapSubmsgs],
413-
inline_attr(mt_finalize_items_r,1),
414-
gpb_codegen:format_fn(
415-
mt_finalize_items_r,
416-
fun(Acc) ->
417-
%% Reverse to store the items in the dict
418-
%% in the same order they were decoded,
419-
%% in case a key occurs more than once.
420-
mt_finalize_items_r_aux(lists:reverse(Acc),
421-
dict:new())
422-
end),
423-
gpb_codegen:format_fn(
424-
mt_finalize_items_r_aux,
425-
fun([{K,V} | Tl], D) -> call_self(Tl, dict:store(K, V, D));
426-
([], D) -> dict:to_list(D)
427-
end),
428-
"\n"];
429-
maps ->
430-
{M,K,V} = {?expr(M), ?expr(K), ?expr(V)},
431-
[inline_attr(mt_maptuple_to_pseudomsg_m,1),
432-
gpb_codegen:format_fn(
433-
mt_maptuple_to_pseudomsg_m,
434-
fun({K,V}) -> '#{key => K, value => V}' end,
435-
[replace_tree('#{key => K, value => V}',
436-
gpb_lib:map_create([{key,K}, {value,V}],
437-
Opts))]),
438-
"\n",
439-
inline_attr(mt_map_to_list_m,1),
440-
gpb_codegen:format_fn(
441-
mt_map_to_list_m,
442-
fun(M) -> maps:to_list(M) end),
443-
"\n",
444-
inline_attr(mt_empty_map_m,0),
445-
gpb_codegen:format_fn(
446-
mt_empty_map_m,
447-
fun() -> '#{}' end,
448-
[replace_tree('#{}', gpb_lib:map_create([], []))]),
449-
"\n",
450-
[[inline_attr(mt_add_item_m,2),
451-
case gpb_lib:target_has_variable_key_map_update(Opts) of
452-
true ->
453-
gpb_codegen:format_fn(
454-
mt_add_item_m,
455-
fun('#{key := K,value := V}', M) -> 'M#{K => V}' end,
456-
[replace_tree(
457-
'#{key := K,value := V}',
458-
gpb_lib:map_match([{key,K}, {value,V}], Opts)),
459-
replace_tree(
460-
'M#{K => V}',
461-
gpb_lib:map_set(M, [{K,V}], []))]);
462-
false ->
463-
gpb_codegen:format_fn(
464-
mt_add_item_m,
465-
fun('#{key := K,value := V}', M) ->
466-
maps:put('K', 'V', 'M')
467-
end,
468-
[replace_tree(
469-
'#{key := K,value := V}',
470-
gpb_lib:map_match([{key,K}, {value,V}], Opts)),
471-
replace_tree('K', K),
472-
replace_tree('V', V),
473-
replace_tree('M', M)])
474-
end]
475-
|| HaveMapNonSubmsgs],
476-
[[inline_attr(mt_add_item_m_verify_value,2),
477-
case gpb_lib:target_has_variable_key_map_update(Opts) of
478-
true ->
479-
gpb_codegen:format_fn(
480-
mt_add_item_m_verify_value,
481-
fun('#{key := K,value := V}', M) ->
482-
if V =:= '$undef' ->
483-
error({gpb_error, missing_value});
484-
true ->
485-
'M#{K => V}'
486-
end
487-
end,
488-
[replace_tree(
489-
'#{key := K,value := V}',
490-
gpb_lib:map_match([{key,K}, {value,V}], Opts)),
491-
replace_tree(
492-
'M#{K => V}',
493-
gpb_lib:map_set(M, [{K,V}], []))]);
494-
false ->
495-
gpb_codegen:format_fn(
496-
mt_add_item_m_verify_value,
497-
fun('#{key := K,value := V}', M) ->
498-
if V =:= '$undef' ->
499-
error({gpb_error, missing_value});
500-
true ->
501-
maps:put('K', 'V', 'M')
502-
end
503-
end,
504-
[replace_tree(
505-
'#{key := K,value := V}',
506-
gpb_lib:map_match([{key,K}, {value,V}], Opts)),
507-
replace_tree('K', K),
508-
replace_tree('V', V),
509-
replace_tree('M', M)])
510-
end]
511-
|| HaveMapSubmsgs],
512-
"\n"]
513-
end,
514-
format_default_merge_translators(AnRes, Opts)]
392+
[[%% If encoders:
393+
case gpb_lib:get_2tuples_or_maps_for_maptype_fields_by_opts(Opts) of
394+
'2tuples' ->
395+
[inline_attr(mt_maptuple_to_pseudomsg_r,2),
396+
gpb_codegen:format_fn(
397+
mt_maptuple_to_pseudomsg_r,
398+
fun({K,V},RName) -> {RName,K,V} end)];
399+
maps ->
400+
[inline_attr(mt_maptuple_to_pseudomsg_m,1),
401+
gpb_codegen:format_fn(
402+
mt_maptuple_to_pseudomsg_m,
403+
fun({K,V}) -> '#{key => K, value => V}' end,
404+
[replace_tree('#{key => K, value => V}',
405+
gpb_lib:map_create([{key,K}, {value,V}],
406+
Opts))]),
407+
"\n",
408+
inline_attr(mt_map_to_list_m,1),
409+
gpb_codegen:format_fn(
410+
mt_map_to_list_m,
411+
fun(M) -> maps:to_list(M) end)]
412+
end
413+
|| DoEncoders],
414+
"\n",
415+
[%% If decoders:
416+
case gpb_lib:get_2tuples_or_maps_for_maptype_fields_by_opts(Opts) of
417+
'2tuples' ->
418+
[inline_attr(mt_empty_map_r,0),
419+
gpb_codegen:format_fn(
420+
mt_empty_map_r,
421+
fun() -> [] end),
422+
[[inline_attr(mt_add_item_r,2),
423+
gpb_codegen:format_fn(
424+
mt_add_item_r,
425+
fun({_RName,K,V}, Acc) -> [{K,V} | Acc] end),
426+
"\n"]
427+
|| HaveMapNonSubmsgs],
428+
[[inline_attr(mt_add_item_r_verify_value,2),
429+
gpb_codegen:format_fn(
430+
mt_add_item_r_verify_value,
431+
fun({_,_,undefined}, _) ->
432+
error({gpb_error, missing_value});
433+
({_RName,K,V}, Acc) ->
434+
[{K,V} | Acc]
435+
end),
436+
"\n"]
437+
|| HaveMapSubmsgs],
438+
inline_attr(mt_finalize_items_r,1),
439+
gpb_codegen:format_fn(
440+
mt_finalize_items_r,
441+
fun(Acc) ->
442+
%% Reverse to store the items in the dict
443+
%% in the same order they were decoded,
444+
%% in case a key occurs more than once.
445+
mt_finalize_items_r_aux(lists:reverse(Acc),
446+
dict:new())
447+
end),
448+
gpb_codegen:format_fn(
449+
mt_finalize_items_r_aux,
450+
fun([{K,V} | Tl], D) -> call_self(Tl, dict:store(K, V, D));
451+
([], D) -> dict:to_list(D)
452+
end)];
453+
maps ->
454+
[inline_attr(mt_empty_map_m,0),
455+
gpb_codegen:format_fn(
456+
mt_empty_map_m,
457+
fun() -> '#{}' end,
458+
[replace_tree('#{}', gpb_lib:map_create([], []))]),
459+
"\n",
460+
[[inline_attr(mt_add_item_m,2),
461+
case gpb_lib:target_has_variable_key_map_update(Opts) of
462+
true ->
463+
gpb_codegen:format_fn(
464+
mt_add_item_m,
465+
fun('#{key := K,value := V}', M) ->
466+
'M#{K => V}'
467+
end,
468+
[replace_tree(
469+
'#{key := K,value := V}',
470+
gpb_lib:map_match([{key,K}, {value,V}], Opts)),
471+
replace_tree(
472+
'M#{K => V}',
473+
gpb_lib:map_set(M, [{K,V}], []))]);
474+
false ->
475+
gpb_codegen:format_fn(
476+
mt_add_item_m,
477+
fun('#{key := K,value := V}', M) ->
478+
maps:put('K', 'V', 'M')
479+
end,
480+
[replace_tree(
481+
'#{key := K,value := V}',
482+
gpb_lib:map_match([{key,K}, {value,V}], Opts)),
483+
replace_tree('K', K),
484+
replace_tree('V', V),
485+
replace_tree('M', M)])
486+
end]
487+
|| HaveMapNonSubmsgs],
488+
[[inline_attr(mt_add_item_m_verify_value,2),
489+
case gpb_lib:target_has_variable_key_map_update(Opts) of
490+
true ->
491+
gpb_codegen:format_fn(
492+
mt_add_item_m_verify_value,
493+
fun('#{key := K,value := V}', M) ->
494+
if V =:= '$undef' ->
495+
error({gpb_error, missing_value});
496+
true ->
497+
'M#{K => V}'
498+
end
499+
end,
500+
[replace_tree(
501+
'#{key := K,value := V}',
502+
gpb_lib:map_match([{key,K}, {value,V}], Opts)),
503+
replace_tree(
504+
'M#{K => V}',
505+
gpb_lib:map_set(M, [{K,V}], []))]);
506+
false ->
507+
gpb_codegen:format_fn(
508+
mt_add_item_m_verify_value,
509+
fun('#{key := K,value := V}', M) ->
510+
if V =:= '$undef' ->
511+
error({gpb_error, missing_value});
512+
true ->
513+
maps:put('K', 'V', 'M')
514+
end
515+
end,
516+
[replace_tree(
517+
'#{key := K,value := V}',
518+
gpb_lib:map_match([{key,K}, {value,V}], Opts)),
519+
replace_tree('K', K),
520+
replace_tree('V', V),
521+
replace_tree('M', M)])
522+
end]
523+
|| HaveMapSubmsgs]]
524+
end
525+
|| DoDecoders],
526+
"\n",
527+
[format_default_merge_translators(AnRes, Opts)
528+
|| DoMergers]]
515529
|| HaveMaps].
516530

517531
format_default_merge_translators(#anres{map_types=MapTypes}, Opts) ->

0 commit comments

Comments
 (0)