From 1b9128438358155a215c465b5a3d1deb9c4d9965 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 11 Sep 2018 09:44:51 +0200 Subject: syntax_tools: Correct erl_syntax:revert/1 revert/1 did not handle the types tuple() and map() correctly. --- lib/syntax_tools/src/erl_syntax.erl | 15 ++++-- lib/syntax_tools/test/syntax_tools_SUITE.erl | 79 +++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 5 deletions(-) diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 758aff32fd..55cc5b792b 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -5455,8 +5455,12 @@ map_type(Fields) -> revert_map_type(Node) -> Pos = get_pos(Node), - {type, Pos, map, map_type_fields(Node)}. - + case map_type_fields(Node) of + any_size -> + {type, Pos, map, any}; + Fields -> + {type, Pos, map, Fields} + end. %% ===================================================================== %% @doc Returns the list of field subtrees of a `map_type' node. @@ -5714,7 +5718,12 @@ tuple_type(Elements) -> revert_tuple_type(Node) -> Pos = get_pos(Node), - {type, Pos, tuple, tuple_type_elements(Node)}. + case tuple_type_elements(Node) of + any_size -> + {type, Pos, tuple, any}; + TypeElements -> + {type, Pos, tuple, TypeElements} + end. %% ===================================================================== diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl index 4cddf8f0c3..9dbd0e302a 100644 --- a/lib/syntax_tools/test/syntax_tools_SUITE.erl +++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl @@ -25,14 +25,14 @@ %% Test cases -export([app_test/1,appup_test/1,smoke_test/1,revert/1,revert_map/1, revert_map_type/1, - t_abstract_type/1,t_erl_parse_type/1,t_epp_dodger/1, + t_abstract_type/1,t_erl_parse_type/1,t_type/1, t_epp_dodger/1, t_comment_scan/1,t_igor/1,t_erl_tidy/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [app_test,appup_test,smoke_test,revert,revert_map,revert_map_type, - t_abstract_type,t_erl_parse_type,t_epp_dodger, + t_abstract_type,t_erl_parse_type,t_type,t_epp_dodger, t_comment_scan,t_igor,t_erl_tidy]. groups() -> @@ -145,6 +145,74 @@ revert_map_type(Config) when is_list(Config) -> %% api tests +t_type(Config) when is_list(Config) -> + F0 = fun validate_basic_type/1, + Appl0 = fun(Name) -> + Atom = erl_syntax:atom(Name), + erl_syntax:type_application(none, Atom, []) + end, + User0 = fun(Name) -> + Atom = erl_syntax:atom(Name), + erl_syntax:user_type_application(Atom, []) + end, + ok = validate(F0,[{"tuple()", erl_syntax:tuple_type()} + ,{"{}", erl_syntax:tuple_type([])} + ,{"integer()", Appl0(integer)} + ,{"foo()", User0(foo)} + ,{"map()", erl_syntax:map_type()} + ,{"#{}", erl_syntax:map_type([])} + ,{"1..2", erl_syntax:integer_range_type + (erl_syntax:integer(1), erl_syntax:integer(2))} + ,{"<<_:1,_:_*2>>", erl_syntax:bitstring_type + (erl_syntax:integer(1), erl_syntax:integer(2))} + ,{"fun()", erl_syntax:fun_type()} + ]), + + F = fun validate_type/1, + ok = validate(F,[{"{}", tuple_type, false} + ,{"tuple()", tuple_type, true} + ,{"{atom()}", tuple_type, false} + ,{"{atom(),integer()}", tuple_type, false} + ,{"integer()", type_application, false} + ,{"foo()", user_type_application, false} + ,{"foo(integer())", user_type_application, false} + ,{"module:function()", type_application, false} + ,{"map()", map_type, true} + ,{"#{}", map_type, false} + ,{"#{atom() => integer()}", map_type, false} + ,{"#{atom() := integer()}", map_type, false} + ,{"#r{}", record_type, false} + ,{"#r{a :: integer()}", record_type, false} + ,{"[]", type_application, false} + ,{"nil()", type_application, false} + ,{"[atom()]", type_application, false} + ,{"1..2", integer_range_type, false} + ,{"<<_:1,_:_*2>>", bitstring_type, false} + ,{"fun()", fun_type, true} + ,{"integer() | atom()", type_union, false} + ,{"A :: fun()", annotated_type, false} + ,{"fun((...) -> atom())", function_type, false} + ,{"fun((integer()) -> atom())", function_type, false} + ,{"V", variable, true} + ]), + ok. + +validate_basic_type({String, Tree}) -> + ErlT = string_to_type(String), + ErlT = erl_syntax:revert(Tree), + ok. + +validate_type({String, Type, Leaf}) -> + ErlT = string_to_type(String), + Type = erl_syntax:type(ErlT), + Leaf = erl_syntax:is_leaf(ErlT), + Tree = erl_syntax_lib:map(fun(Node) -> Node end, ErlT), + Type = erl_syntax:type(Tree), + _ = erl_syntax:meta(Tree), + RevT = erl_syntax:revert(Tree), + Type = erl_syntax:type(RevT), + ok. + t_abstract_type(Config) when is_list(Config) -> F = fun validate_abstract_type/1, ok = validate(F,[{hi,atom}, @@ -451,6 +519,13 @@ string_to_expr(String) -> {ok,[Expr]} = erl_parse:parse_exprs(Ts), Expr. +string_to_type(String) -> + io:format("Str: ~p~n", [String]), + {ok,Ts,_} = erl_scan:string("-type foo() :: "++String++".", 0), + {ok,Form} = erl_parse:parse_form(Ts), + {attribute,_,type,{foo,Type,_NoParms=[]}} = Form, + Type. + p_run(Test, List) -> N = erlang:system_info(schedulers), -- cgit v1.2.3 From 8856bfa8d104b700d67180c15eff98003d28e075 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Tue, 11 Sep 2018 10:09:30 +0200 Subject: erts: Add comment about [] and nil() to The Abstract Format --- erts/doc/src/absform.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index f29bb7b8f9..d77d989057 100644 --- a/erts/doc/src/absform.xml +++ b/erts/doc/src/absform.xml @@ -811,7 +811,9 @@

If T is the empty list type [], then Rep(T) = - {type,Line,nil,[]}.

+ {type,Line,nil,[]}, that is, the empty list type + [] cannot be distinguished from the predefined type + nil().

If T is a fun type fun(), then Rep(T) = -- cgit v1.2.3