diff options
Diffstat (limited to 'lib/syntax_tools')
-rw-r--r-- | lib/syntax_tools/doc/src/Makefile | 15 | ||||
-rw-r--r-- | lib/syntax_tools/src/Makefile | 2 | ||||
-rw-r--r-- | lib/syntax_tools/src/epp_dodger.erl | 36 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_comment_scan.erl | 2 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_prettypr.erl | 20 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_syntax.erl | 58 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_syntax_lib.erl | 2 | ||||
-rw-r--r-- | lib/syntax_tools/src/merl_transform.erl | 2 | ||||
-rw-r--r-- | lib/syntax_tools/test/syntax_tools_SUITE.erl | 24 |
9 files changed, 134 insertions, 27 deletions
diff --git a/lib/syntax_tools/doc/src/Makefile b/lib/syntax_tools/doc/src/Makefile index 1ce620b3d6..a346b9a0bd 100644 --- a/lib/syntax_tools/doc/src/Makefile +++ b/lib/syntax_tools/doc/src/Makefile @@ -63,10 +63,11 @@ BOOK_FILES = book.xml XML_FILES=\ - $(BOOK_FILES) $(XML_CHAPTER_FILES) \ - $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_APPLICATION_FILES) \ + $(BOOK_FILES) $(XML_PART_FILES) $(XML_APPLICATION_FILES) \ $(XML_NOTES_FILES) +XML_GEN_FILES = $(XML_REF3_FILES:%=$(XMLDIR)/%) $(XML_CHAPTER_FILES:%=$(XMLDIR)/%) + # ---------------------------------------------------- INFO_FILE = ../../info @@ -108,11 +109,13 @@ html: gifs $(HTML_REF_MAN_FILE) man: $(MAN3_FILES) -$(XML_REF3_FILES): - escript $(DOCGEN)/priv/bin/xml_from_edoc.escript $(SRC_DIR)/$(@:%.xml=%.erl) +$(XML_REF3_FILES:%=$(XMLDIR)/%): + $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript \ + -dir $(XMLDIR) $(SRC_DIR)/$(@:$(XMLDIR)/%.xml=%.erl) -$(XML_CHAPTER_FILES): - escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) -chapter ../overview.edoc +$(XML_CHAPTER_FILES:%=$(XMLDIR)/%): + $(gen_verbose)escript $(DOCGEN)/priv/bin/xml_from_edoc.escript -def vsn $(VSN) \ + -chapter -dir $(XMLDIR) ../overview.edoc gifs: $(GIF_FILES:%=$(HTMLDIR)/%) diff --git a/lib/syntax_tools/src/Makefile b/lib/syntax_tools/src/Makefile index 8325db45a8..c21d2f49c8 100644 --- a/lib/syntax_tools/src/Makefile +++ b/lib/syntax_tools/src/Makefile @@ -75,7 +75,7 @@ $(EBIN)/%.$(EMULATOR):%.erl # special rules and dependencies to apply the transform to itself $(EBIN)/merl_transform.beam: $(EBIN)/merl.beam ./merl_transform.beam \ - ../include/merl.hrl \ + ../include/merl.hrl $(EBIN)/erl_comment_scan.beam \ $(EBIN)/erl_syntax.beam $(EBIN)/erl_syntax_lib.beam ./merl_transform.beam: ./merl_transform.erl $(EBIN)/merl.beam \ ../include/merl.hrl diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl index 0a12e8fd8b..7e741cc649 100644 --- a/lib/syntax_tools/src/epp_dodger.erl +++ b/lib/syntax_tools/src/epp_dodger.erl @@ -502,6 +502,10 @@ quickscan_form([{'-', _L}, {atom, La, ifdef} | _Ts]) -> kill_form(La); quickscan_form([{'-', _L}, {atom, La, ifndef} | _Ts]) -> kill_form(La); +quickscan_form([{'-', _L}, {'if', La} | _Ts]) -> + kill_form(La); +quickscan_form([{'-', _L}, {atom, La, elif} | _Ts]) -> + kill_form(La); quickscan_form([{'-', _L}, {atom, La, else} | _Ts]) -> kill_form(La); quickscan_form([{'-', _L}, {atom, La, endif} | _Ts]) -> @@ -615,8 +619,13 @@ filter_form(T) -> %% --------------------------------------------------------------------- %% Normal parsing - try to preserve all information -normal_parser(Ts, Opt) -> - rewrite_form(parse_tokens(scan_form(Ts, Opt))). +normal_parser(Ts0, Opt) -> + case scan_form(Ts0, Opt) of + Ts when is_list(Ts) -> + rewrite_form(parse_tokens(Ts)); + Node -> + Node + end. scan_form([{'-', _L}, {atom, La, define} | Ts], Opt) -> [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, @@ -636,12 +645,26 @@ scan_form([{'-', _L}, {atom, La, ifdef} | Ts], Opt) -> scan_form([{'-', _L}, {atom, La, ifndef} | Ts], Opt) -> [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, ifndef} | scan_macros(Ts, Opt)]; +scan_form([{'-', _L}, {'if', La} | Ts], Opt) -> + [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, + {atom, La, 'if'} | scan_macros(Ts, Opt)]; +scan_form([{'-', _L}, {atom, La, elif} | Ts], Opt) -> + [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, + {atom, La, 'elif'} | scan_macros(Ts, Opt)]; scan_form([{'-', _L}, {atom, La, else} | Ts], Opt) -> [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, else} | scan_macros(Ts, Opt)]; scan_form([{'-', _L}, {atom, La, endif} | Ts], Opt) -> [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, endif} | scan_macros(Ts, Opt)]; +scan_form([{'-', _L}, {atom, La, error} | Ts], _Opt) -> + Desc = build_info_string("-error", Ts), + ErrorInfo = {La, ?MODULE, {error, Desc}}, + erl_syntax:error_marker(ErrorInfo); +scan_form([{'-', _L}, {atom, La, warning} | Ts], _Opt) -> + Desc = build_info_string("-warning", Ts), + ErrorInfo = {La, ?MODULE, {warning, Desc}}, + erl_syntax:error_marker(ErrorInfo); scan_form([{'-', L}, {'?', L1}, {Type, _, _}=N | [{'(', _} | _]=Ts], Opt) when Type =:= atom; Type =:= var -> %% minus, macro and open parenthesis at start of form - assume that @@ -657,6 +680,11 @@ scan_form([{'?', L}, {Type, _, _}=N | [{'(', _} | _]=Ts], Opt) scan_form(Ts, Opt) -> scan_macros(Ts, Opt). +build_info_string(Prefix, Ts0) -> + Ts = lists:droplast(Ts0), + String = lists:droplast(tokens_to_string(Ts)), + Prefix ++ " " ++ String ++ ".". + scan_macros(Ts, Opt) -> scan_macros(Ts, [], Opt). @@ -865,6 +893,10 @@ tokens_to_string([]) -> format_error(macro_args) -> errormsg("macro call missing end parenthesis"); +format_error({error, Error}) -> + Error; +format_error({warning, Error}) -> + Error; format_error({unknown, Reason}) -> errormsg(io_lib:format("unknown error: ~tP", [Reason, 15])). diff --git a/lib/syntax_tools/src/erl_comment_scan.erl b/lib/syntax_tools/src/erl_comment_scan.erl index 07e501e553..e3eb95b819 100644 --- a/lib/syntax_tools/src/erl_comment_scan.erl +++ b/lib/syntax_tools/src/erl_comment_scan.erl @@ -208,7 +208,7 @@ scan_comment([], Cs1, L, Col, M, Ack) -> seen_comment(Cs, Cs1, L, Col, M, Ack) -> %% Compute indentation and strip trailing spaces N = Col - M, - Text = lists:reverse(string:strip(Cs1, left)), + Text = lists:reverse(string:trim(Cs1, leading)), Ack1 = [{L, Col + 1, N, Text} | Ack], scan_lines(Cs, L + 1, 0, 0, Ack1). diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl index 40ddd2b22a..6906ef1553 100644 --- a/lib/syntax_tools/src/erl_prettypr.erl +++ b/lib/syntax_tools/src/erl_prettypr.erl @@ -675,7 +675,12 @@ lay_2(Node, Ctxt) -> %% attribute name, without following parentheses. Ctxt1 = reset_prec(Ctxt), Args = erl_syntax:attribute_arguments(Node), - N = erl_syntax:attribute_name(Node), + N = case erl_syntax:attribute_name(Node) of + {atom, _, 'if'} -> + erl_syntax:variable('if'); + N0 -> + N0 + end, D = case attribute_type(Node) of spec -> [SpecTuple] = Args, @@ -774,9 +779,16 @@ lay_2(Node, Ctxt) -> class_qualifier -> Ctxt1 = set_prec(Ctxt, max_prec()), D1 = lay(erl_syntax:class_qualifier_argument(Node), Ctxt1), - D2 = lay(erl_syntax:class_qualifier_body(Node), Ctxt1), - beside(D1, beside(text(":"), D2)); - + D2 = lay(erl_syntax:class_qualifier_body(Node), Ctxt1), + Stacktrace = erl_syntax:class_qualifier_stacktrace(Node), + case erl_syntax:variable_name(Stacktrace) of + '_' -> + beside(D1, beside(text(":"), D2)); + _ -> + D3 = lay(Stacktrace, Ctxt1), + beside(D1, beside(beside(text(":"), D2), + beside(text(":"), D3))) + end; comment -> D = stack_comment_lines( erl_syntax:comment_text(Node)), diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 9b2b503762..029f1e88ac 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -342,8 +342,10 @@ typed_record_field_body/1, typed_record_field_type/1, class_qualifier/2, + class_qualifier/3, class_qualifier_argument/1, class_qualifier_body/1, + class_qualifier_stacktrace/1, tuple/1, tuple_elements/1, tuple_size/1, @@ -3884,7 +3886,7 @@ fold_try_clause({clause, Pos, [P], Guard, Body}) -> class_qualifier -> {tuple, Pos, [class_qualifier_argument(P), class_qualifier_body(P), - {var, Pos, '_'}]}; + class_qualifier_stacktrace(P)]}; _ -> {tuple, Pos, [{atom, Pos, throw}, P, {var, Pos, '_'}]} end, @@ -3893,12 +3895,14 @@ fold_try_clause({clause, Pos, [P], Guard, Body}) -> unfold_try_clauses(Cs) -> [unfold_try_clause(C) || C <- Cs]. -unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw}, V, _]}], +unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw}, + V, + [{var, _, '_'}]]}], Guard, Body}) -> {clause, Pos, [V], Guard, Body}; -unfold_try_clause({clause, Pos, [{tuple, _, [C, V, _]}], +unfold_try_clause({clause, Pos, [{tuple, _, [C, V, Stacktrace]}], Guard, Body}) -> - {clause, Pos, [class_qualifier(C, V)], Guard, Body}. + {clause, Pos, [class_qualifier(C, V, Stacktrace)], Guard, Body}. %% ===================================================================== @@ -5324,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]}. %% ===================================================================== @@ -5382,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]}. %% ===================================================================== @@ -6725,9 +6729,12 @@ try_expr_after(Node) -> %% %% @see class_qualifier_argument/1 %% @see class_qualifier_body/1 +%% @see class_qualifier_stacktrace/1 %% @see try_expr/4 --record(class_qualifier, {class :: syntaxTree(), body :: syntaxTree()}). +-record(class_qualifier, {class :: syntaxTree(), + body :: syntaxTree(), + stacktrace :: syntaxTree()}). %% type(Node) = class_qualifier %% data(Node) = #class_qualifier{class :: Class, body :: Body} @@ -6737,8 +6744,27 @@ try_expr_after(Node) -> -spec class_qualifier(syntaxTree(), syntaxTree()) -> syntaxTree(). class_qualifier(Class, Body) -> + Underscore = {var, get_pos(Body), '_'}, tree(class_qualifier, - #class_qualifier{class = Class, body = Body}). + #class_qualifier{class = Class, body = Body, + stacktrace = Underscore}). + +%% ===================================================================== +%% @doc Creates an abstract class qualifier. The result represents +%% "<code><em>Class</em>:<em>Body</em>:<em>Stacktrace</em></code>". +%% +%% @see class_qualifier_argument/1 +%% @see class_qualifier_body/1 +%% @see try_expr/4 + +-spec class_qualifier(syntaxTree(), syntaxTree(), syntaxTree()) -> + syntaxTree(). + +class_qualifier(Class, Body, Stacktrace) -> + tree(class_qualifier, + #class_qualifier{class = Class, + body = Body, + stacktrace = Stacktrace}). %% ===================================================================== @@ -6763,6 +6789,16 @@ class_qualifier_argument(Node) -> class_qualifier_body(Node) -> (data(Node))#class_qualifier.body. +%% ===================================================================== +%% @doc Returns the stacktrace subtree of a `class_qualifier' node. +%% +%% @see class_qualifier/2 + +-spec class_qualifier_stacktrace(syntaxTree()) -> syntaxTree(). + +class_qualifier_stacktrace(Node) -> + (data(Node))#class_qualifier.stacktrace. + %% ===================================================================== %% @doc Creates an abstract "implicit fun" expression. If @@ -7727,8 +7763,9 @@ subtrees(T) -> catch_expr -> [[catch_expr_body(T)]]; class_qualifier -> - [[class_qualifier_argument(T)], - [class_qualifier_body(T)]]; + [[class_qualifier_argument(T)], + [class_qualifier_body(T)], + [class_qualifier_stacktrace(T)]]; clause -> case clause_guard(T) of none -> @@ -7949,6 +7986,7 @@ make_tree(block_expr, [B]) -> block_expr(B); make_tree(case_expr, [[A], C]) -> case_expr(A, C); make_tree(catch_expr, [[B]]) -> catch_expr(B); make_tree(class_qualifier, [[A], [B]]) -> class_qualifier(A, B); +make_tree(class_qualifier, [[A], [B], [C]]) -> class_qualifier(A, B, C); make_tree(clause, [P, B]) -> clause(P, none, B); make_tree(clause, [P, [G], B]) -> clause(P, G, B); make_tree(cond_expr, [C]) -> cond_expr(C); diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl index c7f477c4d2..ced0dba3e2 100644 --- a/lib/syntax_tools/src/erl_syntax_lib.erl +++ b/lib/syntax_tools/src/erl_syntax_lib.erl @@ -1317,6 +1317,8 @@ analyze_attribute(Node) -> include_lib -> preprocessor; ifdef -> preprocessor; ifndef -> preprocessor; + 'if' -> preprocessor; + elif -> preprocessor; else -> preprocessor; endif -> preprocessor; A -> diff --git a/lib/syntax_tools/src/merl_transform.erl b/lib/syntax_tools/src/merl_transform.erl index b298bc407f..571d7e4d86 100644 --- a/lib/syntax_tools/src/merl_transform.erl +++ b/lib/syntax_tools/src/merl_transform.erl @@ -196,7 +196,7 @@ var_name(V) -> V. var_to_tag(V) when is_integer(V) -> V; var_to_tag(V) -> - list_to_atom(string:to_lower(atom_to_list(V))). + list_to_atom(string:lowercase(atom_to_list(V))). pre_expand_case(Expr, Clauses, Line) -> merl:qquote(Line, "merl:switch(_@expr, _@clauses)", diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl index ae2c67c03e..c8e6448d37 100644 --- a/lib/syntax_tools/test/syntax_tools_SUITE.erl +++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl @@ -24,13 +24,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_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, + [app_test,appup_test,smoke_test,revert,revert_map,revert_map_type, t_abstract_type,t_erl_parse_type,t_epp_dodger, t_comment_scan,t_igor,t_erl_tidy]. @@ -121,7 +122,26 @@ 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 |