aboutsummaryrefslogtreecommitdiffstats
path: root/lib/syntax_tools
diff options
context:
space:
mode:
Diffstat (limited to 'lib/syntax_tools')
-rw-r--r--lib/syntax_tools/doc/src/Makefile3
-rw-r--r--lib/syntax_tools/doc/src/notes.xml79
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl62
-rw-r--r--lib/syntax_tools/src/erl_syntax_lib.erl2
-rw-r--r--lib/syntax_tools/src/igor.erl2
-rw-r--r--lib/syntax_tools/test/merl_SUITE.erl14
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE.erl104
-rw-r--r--lib/syntax_tools/vsn.mk2
8 files changed, 240 insertions, 28 deletions
diff --git a/lib/syntax_tools/doc/src/Makefile b/lib/syntax_tools/doc/src/Makefile
index a346b9a0bd..d953287bad 100644
--- a/lib/syntax_tools/doc/src/Makefile
+++ b/lib/syntax_tools/doc/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2006-2017. All Rights Reserved.
+# Copyright Ericsson AB 2006-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -125,6 +125,7 @@ debug opt:
clean clean_docs:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN3DIR)/*
rm -f $(XML_REF3_FILES) $(XML_CHAPTER_FILES) *.html
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/lib/syntax_tools/doc/src/notes.xml b/lib/syntax_tools/doc/src/notes.xml
index bd2bcde2c2..dc13fe474b 100644
--- a/lib/syntax_tools/doc/src/notes.xml
+++ b/lib/syntax_tools/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2007</year><year>2017</year>
+ <year>2007</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,69 @@
<p>This document describes the changes made to the Syntax_Tools
application.</p>
+<section><title>Syntax_Tools 2.1.6</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fix the <c>TypeName</c> type in erl_syntax_lib.</p>
+ <p>
+ Own Id: OTP-15207 Aux Id: PR-1888 </p>
+ </item>
+ <item>
+ <p> Correct unfolding of the stacktrace variable. </p>
+ <p>
+ Own Id: OTP-15291 Aux Id: ERL-719 </p>
+ </item>
+ <item>
+ <p> Correct <c>erl_syntax:revert/1</c> bug regarding the
+ types <c>map()</c> and <c>tuple()</c>. </p>
+ <p>
+ Own Id: OTP-15294</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p> Support bitstrings as literals in module
+ <c>erl_syntax</c>. </p>
+ <p>
+ Own Id: OTP-15165 Aux Id: PR-1842 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Syntax_Tools 2.1.5</title>
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>
+ Update to use the new string api instead of the old.</p>
+ <p>
+ Own Id: OTP-15036</p>
+ </item>
+ </list>
+ </section>
+</section>
+
+<section><title>Syntax_Tools 2.1.4.1</title>
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding reverting map types. </p>
+ <p>
+ Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ </item>
+ </list>
+ </section>
+</section>
+
<section><title>Syntax_Tools 2.1.4</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -83,6 +146,20 @@
</section>
+<section><title>Syntax_Tools 2.1.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p> Fix a bug regarding reverting map types. </p>
+ <p>
+ Own Id: OTP-15098 Aux Id: ERIERL-177 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Syntax_Tools 2.1.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index b816c0699c..1be644c620 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -3897,7 +3897,7 @@ unfold_try_clauses(Cs) ->
unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw},
V,
- [{var, _, '_'}]]}],
+ {var, _, '_'}]}],
Guard, Body}) ->
{clause, Pos, [V], Guard, Body};
unfold_try_clause({clause, Pos, [{tuple, _, [C, V, Stacktrace]}],
@@ -5328,7 +5328,7 @@ revert_map_type_assoc(Node) ->
Pos = get_pos(Node),
Name = map_type_assoc_name(Node),
Value = map_type_assoc_value(Node),
- {type, Pos, map_type_assoc, [Name, Value]}.
+ {type, Pos, map_field_assoc, [Name, Value]}.
%% =====================================================================
@@ -5386,7 +5386,7 @@ revert_map_type_exact(Node) ->
Pos = get_pos(Node),
Name = map_type_exact_name(Node),
Value = map_type_exact_value(Node),
- {type, Pos, map_type_exact, [Name, Value]}.
+ {type, Pos, map_field_exact, [Name, Value]}.
%% =====================================================================
@@ -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.
%% =====================================================================
@@ -7223,7 +7232,7 @@ macro_arguments(Node) ->
%% @doc Returns the syntax tree corresponding to an Erlang term.
%% `Term' must be a literal term, i.e., one that can be
%% represented as a source code literal. Thus, it may not contain a
-%% process identifier, port, reference, binary or function value as a
+%% process identifier, port, reference or function value as a
%% subterm. The function recognises printable strings, in order to get a
%% compact and readable representation. Evaluation fails with reason
%% `badarg' if `Term' is not a literal term.
@@ -7257,6 +7266,13 @@ abstract(T) when is_map(T) ->
|| {Key,Value} <- maps:to_list(T)]);
abstract(T) when is_binary(T) ->
binary([binary_field(integer(B)) || B <- binary_to_list(T)]);
+abstract(T) when is_bitstring(T) ->
+ S = bit_size(T),
+ ByteS = S div 8,
+ BitS = S rem 8,
+ <<Bin:ByteS/binary, I:BitS>> = T,
+ binary([binary_field(integer(B)) || B <- binary_to_list(Bin)]
+ ++ [binary_field(integer(I), integer(BitS), [])]);
abstract(T) ->
erlang:error({badarg, T}).
@@ -7332,15 +7348,20 @@ concrete(Node) ->
Node0 -> maps:merge(concrete(Node0),M0)
end;
binary ->
- Fs = [revert_binary_field(
- binary_field(binary_field_body(F),
- case binary_field_size(F) of
- none -> none;
- S ->
- revert(S)
- end,
- binary_field_types(F)))
- || F <- binary_fields(Node)],
+ Fs = [begin
+ B = binary_field_body(F),
+ {Body, Size} =
+ case type(B) of
+ size_qualifier ->
+ {size_qualifier_body(B),
+ size_qualifier_argument(B)};
+ _ ->
+ {B, none}
+ end,
+ revert_binary_field(
+ binary_field(Body, Size, binary_field_types(F)))
+ end
+ || F <- binary_fields(Node)],
{value, B, _} =
eval_bits:expr_grp(Fs, [],
fun(F, _) ->
@@ -7413,7 +7434,14 @@ is_literal(T) ->
is_literal_binary_field(F) ->
case binary_field_types(F) of
- [] -> is_literal(binary_field_body(F));
+ [] -> B = binary_field_body(F),
+ case type(B) of
+ size_qualifier ->
+ is_literal(size_qualifier_body(B)) andalso
+ is_literal(size_qualifier_argument(B));
+ _ ->
+ is_literal(B)
+ end;
_ -> false
end.
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index ced0dba3e2..352165893f 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -1981,7 +1981,7 @@ analyze_application(Node) ->
%%
%% @see analyze_type_name/1
--type typeName() :: atom() | {module(), atom(), arity()} | {atom(), arity()}.
+-type typeName() :: atom() | {module(), {atom(), arity()}} | {atom(), arity()}.
-spec analyze_type_application(erl_syntax:syntaxTree()) -> typeName().
diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl
index 16e3511734..b712b77e9f 100644
--- a/lib/syntax_tools/src/igor.erl
+++ b/lib/syntax_tools/src/igor.erl
@@ -660,7 +660,7 @@ merge_files1(Files, Opts) ->
%% transitions), code replacement is expected to be detected. Then, if
%% we in the merged code do not check at these points if the
%% <em>target</em> module (the result of the merge) has been replaced,
-%% we can not be sure in general that we will be able to do code
+%% we cannot be sure in general that we will be able to do code
%% replacement of the merged state machine - it could run forever
%% without detecting the code change. Therefore, all such calls must
%% remain remote-calls (detecting code changes), but may call the target
diff --git a/lib/syntax_tools/test/merl_SUITE.erl b/lib/syntax_tools/test/merl_SUITE.erl
index 52bbd9b3b8..6389ad7738 100644
--- a/lib/syntax_tools/test/merl_SUITE.erl
+++ b/lib/syntax_tools/test/merl_SUITE.erl
@@ -30,13 +30,14 @@
%% Test cases
-export([merl_smoke_test/1,
- transform_parse_error_test/1]).
+ transform_parse_error_test/1, otp_15291/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[merl_smoke_test,
- transform_parse_error_test].
+ transform_parse_error_test,
+ otp_15291].
groups() ->
[].
@@ -101,6 +102,15 @@ transform_parse_error_test(_Config) ->
[?Q("merl:qquote(2, \"{\", [{var, V}])")], []))),
ok.
+otp_15291(_Config) ->
+ C0 = merl:quote("() -> ok"),
+ {clause,1,[],[],[{atom,1,ok}]} = C0,
+ C2 = merl:quote("(_,_) -> ok"),
+ {clause,1,[{var,1,'_'},{var,1,'_'}],[],[{atom,1,ok}]} = C2,
+ C1 = merl:quote("(_) -> ok"),
+ {clause,1,[{var,1,'_'}],[],[{atom,1,ok}]} = C1,
+ ok.
+
%% utilities
f(Ts) when is_list(Ts) ->
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl
index ae2c67c03e..9dbd0e302a 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl
@@ -24,14 +24,15 @@
%% Test cases
-export([app_test/1,appup_test/1,smoke_test/1,revert/1,revert_map/1,
- t_abstract_type/1,t_erl_parse_type/1,t_epp_dodger/1,
+ revert_map_type/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,
- t_abstract_type,t_erl_parse_type,t_epp_dodger,
+ [app_test,appup_test,smoke_test,revert,revert_map,revert_map_type,
+ t_abstract_type,t_erl_parse_type,t_type,t_epp_dodger,
t_comment_scan,t_igor,t_erl_tidy].
groups() ->
@@ -121,10 +122,97 @@ revert_map(Config) when is_list(Config) ->
{map_field_assoc,{atom,17,name},{var,18,'Value'}}}]),
?t:timetrap_cancel(Dog).
-
+%% Testing bug fix for reverting map_field_assoc in types
+revert_map_type(Config) when is_list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(1)),
+ Form1 = {attribute,4,record,
+ {state,
+ [{typed_record_field,
+ {record_field,5,{atom,5,x}},
+ {type,5,map,
+ [{type,5,map_field_exact,[{atom,5,y},{atom,5,z}]}]}}]}},
+ Mapped1 = erl_syntax_lib:map(fun(X) -> X end, Form1),
+ Form1 = erl_syntax:revert(Mapped1),
+ Form2 = {attribute,4,record,
+ {state,
+ [{typed_record_field,
+ {record_field,5,{atom,5,x}},
+ {type,5,map,
+ [{type,5,map_field_assoc,[{atom,5,y},{atom,5,z}]}]}}]}},
+ Mapped2 = erl_syntax_lib:map(fun(X) -> X end, Form2),
+ Form2 = erl_syntax:revert(Mapped2),
+ ?t:timetrap_cancel(Dog).
%% 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},
@@ -137,6 +225,7 @@ t_abstract_type(Config) when is_list(Config) ->
{[$a,$b,$c],string},
{"hello world",string},
{<<1,2,3>>,binary},
+ {<<1,2,3:4>>,binary},
{#{a=>1,"b"=>2},map_expr},
{#{#{i=>1}=>1,"b"=>#{v=>2}},map_expr},
{{a,b,c},tuple}]),
@@ -430,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),
diff --git a/lib/syntax_tools/vsn.mk b/lib/syntax_tools/vsn.mk
index 8d37c40742..8959ebbd04 100644
--- a/lib/syntax_tools/vsn.mk
+++ b/lib/syntax_tools/vsn.mk
@@ -1 +1 @@
-SYNTAX_TOOLS_VSN = 2.1.4
+SYNTAX_TOOLS_VSN = 2.1.6