Skip to content
Permalink
Browse files
Fix bugs in maps and records printing
- improper lists are now handled
- can handle printing filtered maps when not in an imported record but
  still in a tuple
- clean up function exports and docs
  • Loading branch information
ferd committed May 16, 2019
1 parent e51bc3c commit 6e175b35a6c317346e41fe5d17f3b4712a660a92
Showing 3 changed files with 53 additions and 14 deletions.
@@ -13,12 +13,8 @@
-author("bartlomiej.gorny@erlang-solutions.com").
%% API

-export([limit/3]).
-export([list/0]).
-export([limit/3, list/0, is_active/0, clear/0, remove/1, rename/2]).
-export([process_map/1]).
-export([is_active/0]).
-export([clear/0]).
-export([remove/1, rename/2]).

-type map_label() :: atom().
-type pattern() :: map() | function().
@@ -52,34 +48,46 @@ limit(Label, #{} = Pattern, Limit) when is_atom(Label) ->
limit(Label, Pattern, Limit) when is_atom(Label), is_function(Pattern) ->
store_pattern(Label, Pattern, Limit).

%% @doc prints out all "known" map definitions and their limit settings.
%% Printout tells a map's name, the matching fields required, and the limit options.
%% @end
list() ->
ensure_table_exists(),
io:format("~nmap definitions and limits:~n"),
list(lists:sort(ets:tab2list(patterns_table_name()))).
list(ets:tab2list(patterns_table_name())).

%% @doc remove a given map entry
-spec remove(map_label()) -> true.
remove(Label) ->
ensure_table_exists(),
ets:delete(patterns_table_name(), Label).

%% @doc rename a given map entry, which allows to to change priorities for
%% matching. The first argument is the current name, and the second
%% argument is the new name.
-spec rename(map_label(), map_label()) -> renamed | missing.
rename(Name, NewName) ->
ensure_table_exists(),
case ets:lookup(patterns_table_name(), Name) of
[{Name, Pattern, Limit}] ->
ets:delete(patterns_table_name(), Name),
ets:insert(patterns_table_name(), {NewName, Pattern, Limit}),
ets:delete(patterns_table_name(), Name),
renamed;
[] ->
missing
end.

%% @doc prints out all "known" map filter definitions and their settings.
%% Printout tells the map's label, the matching patterns, and the limit options
%% @end
list([]) ->
io:format("~n"),
ok;
list([{Label, Pattern, Limit} | Rest]) ->
io:format("~p: ~p -> ~p~n", [Label, Pattern, Limit]),
list(Rest).

%% @doc given a map, scans saved patterns for one that matches; if found, returns a label
%% @private given a map, scans saved patterns for one that matches; if found, returns a label
%% and a map with limits applied; otherwise returns 'none' and original map.
%% Pattern can be:
%% <ul>
@@ -15,8 +15,8 @@
%% API

-export([is_active/0]).
-export([import/1, format_tuple/1, clear/1, clear/0, list/0, get_list/0, limit/3]).
-export([ensure_table_exists/0]).
-export([import/1, clear/1, clear/0, list/0, get_list/0, limit/3]).
-export([format_tuple/1]).

-ifdef(TEST).
-export([lookup_record/2]).
@@ -63,7 +63,7 @@ clear() ->
ok.

%% @doc prints out all "known" (imported) record definitions and their limit settings.
%% Print out tells module a record originates from, its name and a list of field names,
%% Printout tells module a record originates from, its name and a list of field names,
%% plus the record's arity (may be handy if handling big records) and a list of field it
%% limits its output to, if set.
%% @end
@@ -151,6 +151,7 @@ lookup_record(RecName, FieldCount) ->
ensure_table_exists(),
ets:lookup(records_table_name(), {RecName, FieldCount}).

%% @private
ensure_table_exists() ->
case ets:info(records_table_name()) of
undefined ->
@@ -234,6 +235,7 @@ format_record(Rec, {{Name, Arity}, Fields, _, Limits}) ->
end.

format_kv(Key, Val) ->
%% Some messy mutually recursive calls we can't avoid
[recon_trace:format_trace_output(true, Key), "=", recon_trace:format_trace_output(true, Val)].

apply_limits(List, none) -> List;
@@ -621,13 +621,14 @@ format_trace_output(Recs, Args) ->

format_trace_output(true, _, Args) when is_tuple(Args) ->
recon_rec:format_tuple(Args);
format_trace_output(true, Maps, Args) when is_list(Args) ->
format_trace_output(false, true, Args) when is_tuple(Args) ->
format_tuple(false, true, Args);
format_trace_output(Recs, Maps, Args) when is_list(Args), Recs orelse Maps ->
case io_lib:printable_list(Args) of
true ->
io_lib:format("~p", [Args]);
false ->
L = lists:map(fun(A) -> format_trace_output(true, Maps, A) end, Args),
[$[, join(", ", L), $]]
format_maybe_improper_list(Recs, Maps, Args)
end;
format_trace_output(Recs, true, Args) when is_map(Args) ->
{Label, Map} = case recon_map:process_map(Args) of
@@ -650,6 +651,33 @@ format_trace_output(_, _, Args) ->
format_kv(Recs, Maps, Key, Val) ->
[format_trace_output(Recs, Maps, Key), "=>", format_trace_output(Recs, Maps, Val)].


format_tuple(Recs, Maps, Tup) ->
[${ | format_tuple_(Recs, Maps, tuple_to_list(Tup))].

format_tuple_(_Recs, _Maps, []) ->
"}";
format_tuple_(Recs, Maps, [H|T]) ->
[format_trace_output(Recs, Maps, H), $,,
format_tuple_(Recs, Maps, T)].


format_maybe_improper_list(Recs, Maps, List) ->
[$[ | format_maybe_improper_list_(Recs, Maps, List)].

format_maybe_improper_list_(_, _, []) ->
"]";
format_maybe_improper_list_(Recs, Maps, [H|[]]) ->
[format_trace_output(Recs, Maps, H), $]];
format_maybe_improper_list_(Recs, Maps, [H|T]) when is_list(T) ->
[format_trace_output(Recs, Maps, H), $,,
format_maybe_improper_list_(Recs, Maps, T)];
format_maybe_improper_list_(Recs, Maps, [H|T]) when not is_list(T) ->
%% Handling improper lists
[format_trace_output(Recs, Maps, H), $|,
format_trace_output(Recs, Maps, T), $]].


%%%%%%%%%%%%%%%
%%% HELPERS %%%
%%%%%%%%%%%%%%%
@@ -690,6 +718,7 @@ fun_to_ms(ShellFun) when is_function(ShellFun) ->
exit(shell_funs_only)
end.


-ifdef(OTP_RELEASE).
-spec join(term(), [term()]) -> [term()].
join(Sep, List) ->

0 comments on commit 6e175b3

Please sign in to comment.