aboutsummaryrefslogtreecommitdiffstats
path: root/lib/syntax_tools/src/erl_syntax_lib.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/syntax_tools/src/erl_syntax_lib.erl')
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl150
1 files changed, 130 insertions, 20 deletions
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index ccbf864c2a..5c4e074488 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -46,6 +46,9 @@
new_variable_names/2, new_variable_names/3, strip_comments/1,
to_comment/1, to_comment/2, to_comment/3, variables/1]).
+%% =====================================================================
+
+-type ordset(X) :: [X]. % XXX: TAKE ME OUT
%% =====================================================================
%% @spec map(Function, Tree::syntaxTree()) -> syntaxTree()
@@ -58,6 +61,9 @@
%%
%% @see map_subtrees/2
+-spec map(fun((erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()),
+ erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
+
map(F, Tree) ->
case erl_syntax:subtrees(Tree) of
[] ->
@@ -81,6 +87,9 @@ map(F, Tree) ->
%%
%% @see map/2
+-spec map_subtrees(fun((erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()),
+ erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
+
map_subtrees(F, Tree) ->
case erl_syntax:subtrees(Tree) of
[] ->
@@ -105,6 +114,9 @@ map_subtrees(F, Tree) ->
%% @see fold_subtrees/3
%% @see foldl_listlist/3
+-spec fold(fun((erl_syntax:syntaxTree(), term()) -> term()),
+ term(), erl_syntax:syntaxTree()) -> term().
+
fold(F, S, Tree) ->
case erl_syntax:subtrees(Tree) of
[] ->
@@ -137,6 +149,9 @@ fold_2(_, S, []) ->
%%
%% @see fold/3
+-spec fold_subtrees(fun((erl_syntax:syntaxTree(), term()) -> term()),
+ term(), erl_syntax:syntaxTree()) -> term().
+
fold_subtrees(F, S, Tree) ->
foldl_listlist(F, S, erl_syntax:subtrees(Tree)).
@@ -151,6 +166,9 @@ fold_subtrees(F, S, Tree) ->
%% @see fold/3
%% @see //stdlib/lists:foldl/3
+-spec foldl_listlist(fun((term(), term()) -> term()),
+ term(), [[term()]]) -> term().
+
foldl_listlist(F, S, [L | Ls]) ->
foldl_listlist(F, foldl(F, S, L), Ls);
foldl_listlist(_, S, []) ->
@@ -178,6 +196,9 @@ foldl(_, S, []) ->
%% @see map/2
%% @see fold/3
+-spec mapfold(fun((erl_syntax:syntaxTree(), term()) -> {erl_syntax:syntaxTree(), term()}),
+ term(), erl_syntax:syntaxTree()) -> {erl_syntax:syntaxTree(), term()}.
+
mapfold(F, S, Tree) ->
case erl_syntax:subtrees(Tree) of
[] ->
@@ -216,6 +237,11 @@ mapfold_2(_, S, []) ->
%%
%% @see mapfold/3
+-spec mapfold_subtrees(fun((erl_syntax:syntaxTree(), term()) ->
+ {erl_syntax:syntaxTree(), term()}),
+ term(), erl_syntax:syntaxTree()) ->
+ {erl_syntax:syntaxTree(), term()}.
+
mapfold_subtrees(F, S, Tree) ->
case erl_syntax:subtrees(Tree) of
[] ->
@@ -237,6 +263,9 @@ mapfold_subtrees(F, S, Tree) ->
%% The list of lists in the result has the same structure as the given
%% list of lists.
+-spec mapfoldl_listlist(fun((term(), term()) -> {term(), term()}),
+ term(), [[term()]]) -> {[[term()]], term()}.
+
mapfoldl_listlist(F, S, [L | Ls]) ->
{L1, S1} = mapfoldl(F, S, L),
{Ls1, S2} = mapfoldl_listlist(F, S1, Ls),
@@ -263,6 +292,8 @@ mapfoldl(_, S, []) ->
%%
%% @see //stdlib/sets
+-spec variables(erl_syntax:syntaxTree()) -> set().
+
variables(Tree) ->
variables(Tree, sets:new()).
@@ -316,6 +347,8 @@ default_variable_name(N) ->
%%
%% @see new_variable_name/2
+-spec new_variable_name(set()) -> atom().
+
new_variable_name(S) ->
new_variable_name(fun default_variable_name/1, S).
@@ -340,6 +373,8 @@ new_variable_name(S) ->
%% @see //stdlib/sets
%% @see //stdlib/random
+-spec new_variable_name(fun((integer()) -> atom()), set()) -> atom().
+
new_variable_name(F, S) ->
R = start_range(S),
new_variable_name(R, F, S).
@@ -388,6 +423,8 @@ generate(_Key, Range) ->
%%
%% @see new_variable_name/1
+-spec new_variable_names(integer(), set()) -> [atom()].
+
new_variable_names(N, S) ->
new_variable_names(N, fun default_variable_name/1, S).
@@ -402,6 +439,9 @@ new_variable_names(N, S) ->
%%
%% @see new_variable_name/2
+-spec new_variable_names(integer(), fun((integer()) -> atom()), set()) ->
+ [atom()].
+
new_variable_names(N, F, S) when is_integer(N) ->
R = start_range(S),
new_variable_names(N, [], R, F, S).
@@ -441,6 +481,9 @@ new_variable_names(0, Names, _, _, _) ->
%% @see annotate_bindings/1
%% @see //stdlib/ordsets
+-spec annotate_bindings(erl_syntax:syntaxTree(), ordset(atom())) ->
+ erl_syntax:syntaxTree().
+
annotate_bindings(Tree, Env) ->
{Tree1, _, _} = vann(Tree, Env),
Tree1.
@@ -457,6 +500,8 @@ annotate_bindings(Tree, Env) ->
%%
%% @see annotate_bindings/2
+-spec annotate_bindings(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
+
annotate_bindings(Tree) ->
As = erl_syntax:get_ann(Tree),
case lists:keyfind(env, 1, As) of
@@ -856,7 +901,7 @@ delete_binding_anns([]) ->
%% =====================================================================
-%% @spec is_fail_expr(Tree::syntaxTree()) -> bool()
+%% @spec is_fail_expr(Tree::syntaxTree()) -> boolean()
%%
%% @doc Returns `true' if `Tree' represents an
%% expression which never terminates normally. Note that the reverse
@@ -869,6 +914,8 @@ delete_binding_anns([]) ->
%% @see //erts/erlang:error/1
%% @see //erts/erlang:error/2
+-spec is_fail_expr(erl_syntax:syntaxTree()) -> boolean().
+
is_fail_expr(E) ->
case erl_syntax:type(E) of
application ->
@@ -1038,6 +1085,12 @@ is_fail_expr(E) ->
%% @see erl_syntax:error_marker_info/1
%% @see erl_syntax:warning_marker_info/1
+-type key() :: 'attributes' | 'errors' | 'exports' | 'functions' | 'imports'
+ | 'module' | 'records' | 'rules' | 'warnings'.
+-type info_pair() :: {key(), term()}.
+
+-spec analyze_forms(erl_syntax:forms()) -> [info_pair()].
+
analyze_forms(Forms) when is_list(Forms) ->
finfo_to_list(lists:foldl(fun collect_form/2, new_finfo(), Forms));
analyze_forms(Forms) ->
@@ -1204,6 +1257,8 @@ list_value(List) ->
%% @see erl_syntax:error_marker_info/1
%% @see erl_syntax:warning_marker_info/1
+-spec analyze_form(erl_syntax:syntaxTree()) -> {atom(), term()} | atom().
+
analyze_form(Node) ->
case erl_syntax:type(Node) of
attribute ->
@@ -1276,6 +1331,9 @@ analyze_form(Node) ->
%% @see analyze_record_attribute/1
%% @see analyze_wild_attribute/1
+-spec analyze_attribute(erl_syntax:syntaxTree()) ->
+ 'preprocessor' | {atom(), term()}. % XXX: underspecified
+
analyze_attribute(Node) ->
Name = erl_syntax:attribute_name(Node),
case erl_syntax:type(Name) of
@@ -1326,12 +1384,14 @@ analyze_attribute(_, Node) ->
%% containing the module name and a list of the parameter variable
%% names.
%%
-%% The evaluation throws `syntax_error' if
-%% `Node' does not represent a well-formed module
-%% attribute.
+%% The evaluation throws `syntax_error' if `Node' does not represent a
+%% well-formed module attribute.
%%
%% @see analyze_attribute/1
+-spec analyze_module_attribute(erl_syntax:syntaxTree()) ->
+ atom() | {atom(), [atom()]}.
+
analyze_module_attribute(Node) ->
case erl_syntax:type(Node) of
attribute ->
@@ -1370,12 +1430,16 @@ analyze_variable_list(Node) ->
%% attribute. We do not guarantee that each name occurs at most once in
%% the list. The order of listing is not defined.
%%
-%% The evaluation throws `syntax_error' if
-%% `Node' does not represent a well-formed export
-%% attribute.
+%% The evaluation throws `syntax_error' if `Node' does not represent a
+%% well-formed export attribute.
%%
%% @see analyze_attribute/1
+-type functionN() :: atom() | {atom(), arity()}.
+-type functionName() :: functionN() | {atom(), functionN()}.
+
+-spec analyze_export_attribute(erl_syntax:syntaxTree()) -> [functionName()].
+
analyze_export_attribute(Node) ->
case erl_syntax:type(Node) of
attribute ->
@@ -1416,6 +1480,8 @@ analyze_function_name_list(Node) ->
%% The evaluation throws `syntax_error' if
%% `Node' does not represent a well-formed function name.
+-spec analyze_function_name(erl_syntax:syntaxTree()) -> functionName().
+
analyze_function_name(Node) ->
case erl_syntax:type(Node) of
atom ->
@@ -1470,12 +1536,14 @@ append_arity(_A, Name) ->
%% that each name occurs at most once in `Names'. The order
%% of listing is not defined.
%%
-%% The evaluation throws `syntax_error' if
-%% `Node' does not represent a well-formed import
-%% attribute.
+%% The evaluation throws `syntax_error' if `Node' does not represent a
+%% well-formed import attribute.
%%
%% @see analyze_attribute/1
+-spec analyze_import_attribute(erl_syntax:syntaxTree()) ->
+ {atom(), [functionName()]} | atom().
+
analyze_import_attribute(Node) ->
case erl_syntax:type(Node) of
attribute ->
@@ -1498,19 +1566,19 @@ analyze_import_attribute(Node) ->
%% @spec analyze_wild_attribute(Node::syntaxTree()) -> {atom(), term()}
%%
%% @doc Returns the name and value of a "wild" attribute. The result is
-%% the pair `{Name, Value}', if `Node' represents
-%% "`-Name(Value)'".
+%% the pair `{Name, Value}', if `Node' represents "`-Name(Value)'".
%%
%% Note that no checking is done whether `Name' is a
%% reserved attribute name such as `module' or
%% `export': it is assumed that the attribute is "wild".
%%
-%% The evaluation throws `syntax_error' if
-%% `Node' does not represent a well-formed wild
-%% attribute.
+%% The evaluation throws `syntax_error' if `Node' does not represent a
+%% well-formed wild attribute.
%%
%% @see analyze_attribute/1
+-spec analyze_wild_attribute(erl_syntax:syntaxTree()) -> {atom(), term()}.
+
analyze_wild_attribute(Node) ->
case erl_syntax:type(Node) of
attribute ->
@@ -1559,6 +1627,10 @@ analyze_wild_attribute(Node) ->
%% @see analyze_attribute/1
%% @see analyze_record_field/1
+-type fields() :: [{atom(), 'none' | erl_syntax:syntaxTree()}].
+
+-spec analyze_record_attribute(erl_syntax:syntaxTree()) -> {atom(), fields()}.
+
analyze_record_attribute(Node) ->
case erl_syntax:type(Node) of
attribute ->
@@ -1629,6 +1701,11 @@ analyze_record_attribute_tuple(Node) ->
%% @see analyze_record_attribute/1
%% @see analyze_record_field/1
+-type info() :: {atom(), [{atom(), 'none' | erl_syntax:syntaxTree()}]}
+ | {atom(), atom()} | atom().
+
+-spec analyze_record_expr(erl_syntax:syntaxTree()) -> {atom(), info()} | atom().
+
analyze_record_expr(Node) ->
case erl_syntax:type(Node) of
record_expr ->
@@ -1700,6 +1777,9 @@ analyze_record_expr(Node) ->
%% @see analyze_record_attribute/1
%% @see analyze_record_expr/1
+-spec analyze_record_field(erl_syntax:syntaxTree()) ->
+ {atom(), 'none' | erl_syntax:syntaxTree()}.
+
analyze_record_field(Node) ->
case erl_syntax:type(Node) of
record_field ->
@@ -1730,6 +1810,8 @@ analyze_record_field(Node) ->
%%
%% @see analyze_attribute/1
+-spec analyze_file_attribute(erl_syntax:syntaxTree()) -> {string(), integer()}.
+
analyze_file_attribute(Node) ->
case erl_syntax:type(Node) of
attribute ->
@@ -1765,6 +1847,8 @@ analyze_file_attribute(Node) ->
%%
%% @see analyze_rule/1
+-spec analyze_function(erl_syntax:syntaxTree()) -> {atom(), arity()}.
+
analyze_function(Node) ->
case erl_syntax:type(Node) of
function ->
@@ -1794,6 +1878,8 @@ analyze_function(Node) ->
%%
%% @see analyze_function/1
+-spec analyze_rule(erl_syntax:syntaxTree()) -> {atom(), arity()}.
+
analyze_rule(Node) ->
case erl_syntax:type(Node) of
rule ->
@@ -1826,11 +1912,12 @@ analyze_rule(Node) ->
%%
%% @see analyze_function_name/1
+-spec analyze_implicit_fun(erl_syntax:syntaxTree()) -> functionName().
+
analyze_implicit_fun(Node) ->
case erl_syntax:type(Node) of
implicit_fun ->
- analyze_function_name(
- erl_syntax:implicit_fun_name(Node));
+ analyze_function_name(erl_syntax:implicit_fun_name(Node));
_ ->
throw(syntax_error)
end.
@@ -1851,12 +1938,15 @@ analyze_implicit_fun(Node) ->
%% function is not explicitly named (i.e., `F' is given by
%% some expression), only the arity `A' is returned.
%%
-%% The evaluation throws `syntax_error' if
-%% `Node' does not represent a well-formed application
-%% expression.
+%% The evaluation throws `syntax_error' if `Node' does not represent a
+%% well-formed application expression.
%%
%% @see analyze_function_name/1
+-type appFunName() :: {atom(), arity()} | {atom(), {atom(), arity()}}.
+
+-spec analyze_application(erl_syntax:syntaxTree()) -> appFunName() | arity().
+
analyze_application(Node) ->
case erl_syntax:type(Node) of
application ->
@@ -1897,6 +1987,11 @@ analyze_application(Node) ->
%%
%% @see analyze_function_name/1
+-type shortname() :: atom() | {atom(), arity()}.
+-type name() :: shortname() | {atom(), shortname()}.
+
+-spec function_name_expansions([name()]) -> [{shortname(), name()}].
+
function_name_expansions(Fs) ->
function_name_expansions(Fs, []).
@@ -1922,6 +2017,8 @@ function_name_expansions(A, Name, Ack) ->
%% Standalone comments in form lists are removed; any other standalone
%% comments are changed into null-comments (no text, no indentation).
+-spec strip_comments(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
+
strip_comments(Tree) ->
map(fun strip_comments_1/1, Tree).
@@ -1942,6 +2039,8 @@ strip_comments_1(T) ->
%% @spec to_comment(Tree) -> syntaxTree()
%% @equiv to_comment(Tree, "% ")
+-spec to_comment(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
+
to_comment(Tree) ->
to_comment(Tree, "% ").
@@ -1956,6 +2055,8 @@ to_comment(Tree) ->
%% @see to_comment/3
%% @see erl_prettypr:format/1
+-spec to_comment(erl_syntax:syntaxTree(), string()) -> erl_syntax:syntaxTree().
+
to_comment(Tree, Prefix) ->
F = fun (T) -> erl_prettypr:format(T) end,
to_comment(Tree, Prefix, F).
@@ -1985,6 +2086,10 @@ to_comment(Tree, Prefix) ->
%% @see to_comment/1
%% @see to_comment/2
+-spec to_comment(erl_syntax:syntaxTree(), string(),
+ fun((erl_syntax:syntaxTree()) -> string())) ->
+ erl_syntax:syntaxTree().
+
to_comment(Tree, Prefix, F) ->
erl_syntax:comment(split_lines(F(Tree), Prefix)).
@@ -1998,6 +2103,8 @@ to_comment(Tree, Prefix, F) ->
%% @see limit/3
%% @see erl_syntax:text/1
+-spec limit(erl_syntax:syntaxTree(), integer()) -> erl_syntax:syntaxTree().
+
limit(Tree, Depth) ->
limit(Tree, Depth, erl_syntax:text("...")).
@@ -2026,6 +2133,9 @@ limit(Tree, Depth) ->
%%
%% @see limit/2
+-spec limit(erl_syntax:syntaxTree(), integer(), erl_syntax:syntaxTree()) ->
+ erl_syntax:syntaxTree().
+
limit(_Tree, Depth, Node) when Depth < 0 ->
Node;
limit(Tree, Depth, Node) ->