From 1798238086d0a482f97452c47467c4f095edd7b2 Mon Sep 17 00:00:00 2001
From: elbrujohalcon
Date: Wed, 16 Oct 2024 16:20:58 +0200
Subject: [PATCH] brujo-update Update with OTP25 improvements
---
src/ktn_dodger.erl | 284 +++++++++++++++++++++++--------------------
test/files/otp27.erl | 9 +-
2 files changed, 151 insertions(+), 142 deletions(-)
diff --git a/src/ktn_dodger.erl b/src/ktn_dodger.erl
index f4e69e2..0bfbee0 100644
--- a/src/ktn_dodger.erl
+++ b/src/ktn_dodger.erl
@@ -21,6 +21,7 @@
%%
%% @copyright 2001-2006 Richard Carlsson
%% @author Richard Carlsson
+%% @end
%% =====================================================================
%% @doc `epp_dodger' - bypasses the Erlang preprocessor.
@@ -29,9 +30,9 @@
%% expanding preprocessor directives and macro applications, as long as
%% these are syntactically "well-behaved". Because the normal parse
%% trees of the `erl_parse' module cannot represent these things
-%% (normally, they are expanded by the Erlang preprocessor (`epp')
-%% before the parser sees them), an extended syntax tree
-%% is created, using the `erl_syntax' module.
+%% (normally, they are expanded by the Erlang preprocessor {@link
+%% //stdlib/epp} before the parser sees them), an extended syntax tree
+%% is created, using the {@link erl_syntax} module.
%% NOTES:
@@ -93,7 +94,7 @@
%% This is a so-called Erlang I/O ErrorInfo structure; see the {@link
%% //stdlib/io} module for details.
--type errorinfo() :: {integer(), atom(), term()}.
+-type errorinfo() :: erl_scan:error_info().
-type option() :: atom() | {atom(), term()}.
@@ -121,8 +122,8 @@ parse_file(File) ->
%%
%% - {@type {no_fail, boolean()@}}
%% - If `true', this makes `epp_dodger' replace any program forms
-%% that could not be parsed with nodes of type `text' (see
-%% `erl_syntax:text/1'), representing the raw token sequence of the
+%% that could not be parsed with nodes of type `text' (see {@link
+%% erl_syntax:text/1}), representing the raw token sequence of the
%% form, instead of reporting a parse error. The default value is
%% `false'.
%% - {@type {clever, boolean()@}}
@@ -157,7 +158,7 @@ quick_parse_file(File) ->
%% can usually handle more strange cases than the normal, more exact
%% parsing.
%%
-%% Options: see `parse_file/2'. Note however that for
+%% Options: see {@link parse_file/2}. Note however that for
%% `quick_parse_file/2', the option `no_fail' is `true' by default.
%%
%% @see quick_parse/2
@@ -201,7 +202,7 @@ do_parse_file(DefEncoding, File, Parser, Options) ->
find_invalid_unicode([H | T]) ->
case H of
- {error, {_Line, file_io_server, invalid_unicode}} ->
+ {error, {_Location, file_io_server, invalid_unicode}} ->
invalid_unicode;
_Other ->
find_invalid_unicode(T)
@@ -216,17 +217,17 @@ find_invalid_unicode([]) ->
parse(Dev) ->
parse(Dev, 1).
-%% @equiv parse(IODevice, StartLine, [])
+%% @equiv parse(IODevice, StartLocation, [])
%% @see parse/1
--spec parse(file:io_device(), integer()) -> {ok, erl_syntax:forms()}.
+-spec parse(file:io_device(), erl_anno:location()) -> {ok, erl_syntax:forms()}.
parse(Dev, L) ->
parse(Dev, L, []).
%% @doc Reads and parses program text from an I/O stream. Characters are
%% read from `IODevice' until end-of-file; apart from this, the
-%% behaviour is the same as for `parse_file/2'. `StartLine' is the
-%% initial line number, which should be a positive integer.
+%% behaviour is the same as for {@link parse_file/2}. `StartLocation' is the
+%% initial location.
%%
%% @see parse/2
%% @see parse_file/2
@@ -244,10 +245,10 @@ parse(Dev, L0, Options) ->
quick_parse(Dev) ->
quick_parse(Dev, 1).
-%% @equiv quick_parse(IODevice, StartLine, [])
+%% @equiv quick_parse(IODevice, StartLocation, [])
%% @see quick_parse/1
--spec quick_parse(file:io_device(), integer()) -> {ok, erl_syntax:forms()}.
+-spec quick_parse(file:io_device(), erl_anno:location()) -> {ok, erl_syntax:forms()}.
quick_parse(Dev, L) ->
quick_parse(Dev, L, []).
@@ -259,7 +260,7 @@ quick_parse(Dev, L) ->
%% @see quick_parse_form/2
%% @see parse/3
--spec quick_parse(file:io_device(), integer(), [option()]) -> {ok, erl_syntax:forms()}.
+-spec quick_parse(file:io_device(), erl_anno:location(), [option()]) -> {ok, erl_syntax:forms()}.
quick_parse(Dev, L0, Options) ->
parse(Dev, L0, fun quick_parse_form/3, Options).
@@ -280,14 +281,14 @@ parse(Dev, L0, Fs, Parser, Options) ->
%% =====================================================================
-%% @equiv parse_form(IODevice, StartLine, [])
+%% @equiv parse_form(IODevice, StartLocation, [])
%%
%% @see quick_parse_form/2
--spec parse_form(file:io_device(), non_neg_integer()) ->
- {ok, erl_syntax:forms(), non_neg_integer()} |
- {eof, non_neg_integer()} |
- {error, errorinfo(), non_neg_integer()}.
+-spec parse_form(file:io_device(), erl_anno:location()) ->
+ {ok, erl_syntax:forms(), erl_anno:location()} |
+ {eof, erl_anno:location()} |
+ {error, errorinfo(), erl_anno:location()}.
parse_form(Dev, L0) ->
parse_form(Dev, L0, []).
@@ -296,28 +297,28 @@ parse_form(Dev, L0) ->
%% marker is found (a period character followed by whitespace), or until
%% end-of-file; apart from this, the behaviour is similar to that of
%% `parse/3', except that the return values also contain the
-%% final line number given that `StartLine' is the initial
-%% line number, and that `{eof, LineNo}' may be returned.
+%% final location given that `StartLocation' is the initial
+%% location, and that `{eof, Location}' may be returned.
%%
%% @see parse/3
%% @see parse_form/2
%% @see quick_parse_form/3
--spec parse_form(file:io_device(), integer(), [option()]) ->
- {ok, erl_syntax:forms(), integer()} |
- {eof, integer()} |
- {error, errorinfo(), integer()}.
+-spec parse_form(file:io_device(), erl_anno:location(), [option()]) ->
+ {ok, erl_syntax:forms(), erl_anno:location()} |
+ {eof, erl_anno:location()} |
+ {error, errorinfo(), erl_anno:location()}.
parse_form(Dev, L0, Options) ->
parse_form(Dev, L0, fun normal_parser/2, Options).
-%% @equiv quick_parse_form(IODevice, StartLine, [])
+%% @equiv quick_parse_form(IODevice, StartLocation, [])
%%
%% @see parse_form/2
--spec quick_parse_form(file:io_device(), non_neg_integer()) ->
- {ok, erl_syntax:forms(), non_neg_integer()} |
- {eof, non_neg_integer()} |
- {error, errorinfo(), non_neg_integer()}.
+-spec quick_parse_form(file:io_device(), erl_anno:location()) ->
+ {ok, erl_syntax:forms(), erl_anno:location()} |
+ {eof, erl_anno:location()} |
+ {error, errorinfo(), erl_anno:location()}.
quick_parse_form(Dev, L0) ->
quick_parse_form(Dev, L0, []).
@@ -328,10 +329,10 @@ quick_parse_form(Dev, L0) ->
%% @see quick_parse_form/2
%% @see parse_form/3
--spec quick_parse_form(file:io_device(), integer(), [option()]) ->
- {ok, erl_syntax:forms(), integer()} |
- {eof, integer()} |
- {error, errorinfo(), integer()}.
+-spec quick_parse_form(file:io_device(), erl_anno:location(), [option()]) ->
+ {ok, erl_syntax:forms(), erl_anno:location()} |
+ {eof, erl_anno:location()} |
+ {error, errorinfo(), erl_anno:location()}.
quick_parse_form(Dev, L0, Options) ->
parse_form(Dev, L0, fun quick_parser/2, Options).
@@ -353,7 +354,12 @@ parse_form(Dev, L0, Parser, Options) ->
compact_strings = proplists:get_bool(compact_strings, Options),
pre_fixer = proplists:get_value(pre_fixer, Options, fun no_fix/1),
post_fixer = proplists:get_value(post_fixer, Options, fun no_fix/1)},
- ScanOpts = proplists:get_value(scan_opts, Options, []),
+
+ %% This has the *potential* to read options for enabling/disabling
+ %% (i.e. `{feature, TheFeature, enable}') when parsing the file.
+ {ok, {_Ftrs, ResWordFun}} = erl_features:keyword_fun(Options, fun erl_scan:f_reserved_word/1),
+
+ ScanOpts = [{reserved_word_fun, ResWordFun} | proplists:get_value(scan_opts, Options, [])],
case io:scan_erl_form(Dev, "", L0, ScanOpts) of
{ok, Ts, L1} ->
case extract_escript_header(Ts) of
@@ -394,9 +400,9 @@ parse_form(Parser, Ts, L1, NoFail, Opt) ->
IoErr = io_error(L1, Term),
{error, IoErr, L1};
{parse_error, _IoErr} when NoFail ->
- {ok,
- erl_syntax:set_pos(
- erl_syntax:text(tokens_to_string(Ts)), start_pos(Ts, L1)),
+ {ok, erl_syntax:set_pos(
+ erl_syntax:text(tokens_to_string(Ts)),
+ erl_anno:new(start_pos(Ts, L1))),
L1};
{parse_error, IoErr} ->
{error, IoErr, L1};
@@ -408,7 +414,7 @@ io_error(L, Desc) ->
{L, ?MODULE, Desc}.
start_pos([T | _Ts], _L) ->
- erl_anno:line(element(2, T));
+ erl_anno:location(element(2, T));
start_pos([], L) ->
L.
@@ -484,32 +490,34 @@ expression_dot() ->
quick_parser(Ts, _Opt) ->
filter_form(parse_tokens(quickscan_form(Ts))).
-quickscan_form([{'-', _L}, {atom, La, define} | _Ts]) ->
- kill_form(La);
-quickscan_form([{'-', _L}, {atom, La, undef} | _Ts]) ->
- kill_form(La);
-quickscan_form([{'-', _L}, {atom, La, include} | _Ts]) ->
- kill_form(La);
-quickscan_form([{'-', _L}, {atom, La, include_lib} | _Ts]) ->
- kill_form(La);
-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]) ->
- kill_form(La);
-quickscan_form([{'-', L}, {'?', _}, {Type, _, _} = N | [{'(', _} | _] = Ts])
+quickscan_form([{'-', _Anno}, {atom, AnnoA, define} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, undef} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, include} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, include_lib} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, ifdef} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, ifndef} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {'if', AnnoA} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, elif} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, 'else'} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {'else', AnnoA} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', _Anno}, {atom, AnnoA, endif} | _Ts]) ->
+ kill_form(AnnoA);
+quickscan_form([{'-', Anno}, {'?', _}, {Type, _, _} = N | [{'(', _} | _] = Ts])
when Type =:= atom; Type =:= var ->
%% minus, macro and open parenthesis at start of form - assume that
%% the macro takes no arguments; e.g. `-?foo(...).'
- do_quickscan_macros(N, Ts, [{'-', L}]);
-quickscan_form([{'?', _L}, {Type, _, _} = N | [{'(', _} | _] = Ts])
+ do_quickscan_macros(N, Ts, [{'-', Anno}]);
+quickscan_form([{'?', _Anno}, {Type, _, _} = N | [{'(', _} | _] = Ts])
when Type =:= atom; Type =:= var ->
%% macro and open parenthesis at start of form - assume that the
%% macro takes no arguments (see scan_macros for details)
@@ -517,18 +525,18 @@ quickscan_form([{'?', _L}, {Type, _, _} = N | [{'(', _} | _] = Ts])
quickscan_form(Ts) ->
quickscan_macros(Ts).
-kill_form(L) ->
- [{atom, L, ?pp_form}, {'(', L}, {')', L}, {'->', L}, {atom, L, kill}, {dot, L}].
+kill_form(A) ->
+ [{atom, A, ?pp_form}, {'(', A}, {')', A}, {'->', A}, {atom, A, kill}, {dot, A}].
quickscan_macros(Ts) ->
quickscan_macros(Ts, []).
-quickscan_macros([{'?', _}, {Type, _, A} | Ts], [{string, L, S} | As])
+quickscan_macros([{'?', _}, {Type, _, A} | Ts], [{string, AnnoS, S} | As])
when Type =:= atom; Type =:= var ->
%% macro after a string literal: change to a single string
{_, Ts1} = skip_macro_args(Ts),
S1 = S ++ quick_macro_string(A),
- quickscan_macros(Ts1, [{string, L, S1} | As]);
+ quickscan_macros(Ts1, [{string, AnnoS, S1} | As]);
quickscan_macros([{'?', _}, {Type, _, _} = N | [{'(', _} | _] = Ts], [{':', _} | _] = As)
when Type =:= atom; Type =:= var ->
%% macro and open parenthesis after colon - check the token
@@ -553,13 +561,13 @@ quickscan_macros([], As) ->
lists:reverse(As).
%% (after a macro has been found and the arglist skipped, if any)
-do_quickscan_macros({_Type, _, A}, [{string, L, S} | Ts], As) ->
+do_quickscan_macros({_Type, _, A}, [{string, AnnoS, S} | Ts], As) ->
%% string literal following macro: change to single string
S1 = quick_macro_string(A) ++ S,
- quickscan_macros(Ts, [{string, L, S1} | As]);
-do_quickscan_macros({_Type, L, A}, Ts, As) ->
+ quickscan_macros(Ts, [{string, AnnoS, S1} | As]);
+do_quickscan_macros({_Type, AnnoA, A}, Ts, As) ->
%% normal case - just replace the macro with an atom
- quickscan_macros(Ts, [{atom, L, quick_macro_atom(A)} | As]).
+ quickscan_macros(Ts, [{atom, AnnoA, quick_macro_atom(A)} | As]).
quick_macro_atom(A) ->
list_to_atom("?" ++ atom_to_list(A)).
@@ -592,15 +600,9 @@ skip_macro_args([{'receive', _} = T | Ts], Es, As) ->
skip_macro_args(Ts, ['end' | Es], [T | As]);
skip_macro_args([{'try', _} = T | Ts], Es, As) ->
skip_macro_args(Ts, ['end' | Es], [T | As]);
-skip_macro_args([{'cond', _} = T | Ts], Es, As) ->
- skip_macro_args(Ts, ['end' | Es], [T | As]);
-skip_macro_args([{E, _} = T | Ts],
- [E],
- As) -> %final close
+skip_macro_args([{E, _} = T | Ts], [E], As) -> %final close
{lists:reverse([T | As]), Ts};
-skip_macro_args([{E, _} = T | Ts],
- [E | Es],
- As) -> %matching close
+skip_macro_args([{E, _} = T | Ts], [E | Es], As) -> %matching close
skip_macro_args(Ts, Es, [T | As]);
skip_macro_args([T | Ts], Es, As) ->
skip_macro_args(Ts, Es, [T | As]);
@@ -664,58 +666,67 @@ default_prefix(#opt{parse_macro_definitions = false, compact_strings = true}) ->
end
end.
-scan_form([{'-', _L}, {atom, La, define} | Ts], #opt{parse_macro_definitions = false}) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, define} | Ts];
-scan_form([{'-', _L}, {atom, La, define} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, define}
+scan_form([{'-', _Anno}, {atom, AnnoA, define} | Ts], #opt{parse_macro_definitions = false}) ->
+ [
+ {atom, AnnoA, ?pp_form},
+ {'(', AnnoA},
+ {')', AnnoA},
+ {'->', AnnoA},
+ {atom, AnnoA, define}
+ | Ts];
+scan_form([{'-', _Anno}, {atom, AnnoA, define} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, define}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, undef} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, undef}
+scan_form([{'-', _Anno}, {atom, AnnoA, undef} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, undef}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, include} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, include}
+scan_form([{'-', _Anno}, {atom, AnnoA, include} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, include}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, include_lib} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, include_lib}
+scan_form([{'-', _Anno}, {atom, AnnoA, include_lib} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, include_lib}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, ifdef} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, ifdef}
+scan_form([{'-', _Anno}, {atom, AnnoA, ifdef} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, ifdef}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, ifndef} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, ifndef}
+scan_form([{'-', _Anno}, {atom, AnnoA, ifndef} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, ifndef}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {'if', La} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, 'if'}
+scan_form([{'-', _Anno}, {'if', AnnoA} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, 'if'}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, elif} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, elif}
+scan_form([{'-', _Anno}, {atom, AnnoA, elif} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, elif}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, 'else'} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, 'else'}
+scan_form([{'-', _Anno}, {atom, AnnoA, 'else'} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, 'else'}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, endif} | Ts], Opt) ->
- [{atom, La, ?pp_form}, {'(', La}, {')', La}, {'->', La}, {atom, La, endif}
+scan_form([{'-', Anno}, {'else', AnnoA} | Ts], Opt) ->
+ %% See previous clause
+ scan_form([{'-', Anno}, {atom, AnnoA, 'else'} | Ts], Opt);
+scan_form([{'-', _Anno}, {atom, AnnoA, endif} | Ts], Opt) ->
+ [{atom, AnnoA, ?pp_form}, {'(', AnnoA}, {')', AnnoA}, {'->', AnnoA}, {atom, AnnoA, endif}
| scan_macros(Ts, Opt)];
-scan_form([{'-', _L}, {atom, La, error} | Ts], _Opt) ->
+scan_form([{'-', _Anno}, {atom, AnnoA, error} | Ts], _Opt) ->
Desc = build_info_string("-error", Ts),
- ErrorInfo = {La, ?MODULE, {error, Desc}},
+ ErrorInfo = {erl_anno:location(AnnoA), ?MODULE, {error, Desc}},
erl_syntax:error_marker(ErrorInfo);
-scan_form([{'-', _L}, {atom, La, warning} | Ts], _Opt) ->
+scan_form([{'-', _Anno}, {atom, AnnoA, warning} | Ts], _Opt) ->
Desc = build_info_string("-warning", Ts),
- ErrorInfo = {La, ?MODULE, {warning, Desc}},
+ ErrorInfo = {erl_anno:location(AnnoA), ?MODULE, {warning, Desc}},
erl_syntax:error_marker(ErrorInfo);
-scan_form([{'-', L}, {'?', L1}, {Type, _, _} = N | [{'(', _} | _] = Ts], Opt)
+scan_form([{'-', A}, {'?', A1}, {Type, _, _} = N | [{'(', _} | _] = Ts], Opt)
when Type =:= atom; Type =:= var ->
%% minus, macro and open parenthesis at start of form - assume that
%% the macro takes no arguments; e.g. `-?foo(...).'
- macro(L1, N, Ts, [{'-', L}], Opt);
-scan_form([{'?', L}, {Type, _, _} = N | [{'(', _} | _] = Ts], Opt)
+ macro(A1, N, Ts, [{'-', A}], Opt);
+scan_form([{'?', A}, {Type, _, _} = N | [{'(', _} | _] = Ts], Opt)
when Type =:= atom; Type =:= var ->
%% macro and open parenthesis at start of form - assume that the
%% macro takes no arguments; probably a function declaration on the
%% form `?m(...) -> ...', which will not parse if it is rewritten as
%% `(?m(...)) -> ...', so it must be handled as `(?m)(...) -> ...'
- macro(L, N, Ts, [], Opt);
+ macro(A, N, Ts, [], Opt);
scan_form(Ts, Opt) ->
scan_macros(Ts, Opt).
@@ -728,12 +739,12 @@ scan_macros(Ts, Opt) ->
scan_macros(Ts, [], Opt).
scan_macros([{'?', _} = M, {Type, _, _} = N | Ts],
- [{string, L, _} = S | As],
+ [{string, AnnoS, _} = S | As],
#opt{clever = true} = Opt)
when Type =:= atom; Type =:= var ->
%% macro after a string literal: be clever and insert ++
- scan_macros([M, N | Ts], [{'++', L}, S | As], Opt);
-scan_macros([{'?', L}, {Type, _, _} = N | [{'(', _} | _] = Ts], [{':', _} | _] = As, Opt)
+ scan_macros([M, N | Ts], [{'++', AnnoS}, S | As], Opt);
+scan_macros([{'?', Anno}, {Type, _, _} = N | [{'(', _} | _] = Ts], [{':', _} | _] = As, Opt)
when Type =:= atom; Type =:= var ->
%% macro and open parentheses after colon - probably a call
%% `m:?F(...)' so the argument list might belong to the call, not
@@ -743,21 +754,21 @@ scan_macros([{'?', L}, {Type, _, _} = N | [{'(', _} | _] = Ts], [{':', _} | _] =
{Args, Rest} = skip_macro_args(Ts),
case Rest of
[{'->', _} | _] ->
- macro_call(Args, L, N, Rest, As, Opt);
+ macro_call(Args, Anno, N, Rest, As, Opt);
[{'when', _} | _] ->
- macro_call(Args, L, N, Rest, As, Opt);
+ macro_call(Args, Anno, N, Rest, As, Opt);
_ ->
- macro(L, N, Ts, As, Opt)
+ macro(Anno, N, Ts, As, Opt)
end;
-scan_macros([{'?', L}, {Type, _, _} = N | [{'(', _} | _] = Ts], As, Opt)
+scan_macros([{'?', Anno}, {Type, _, _} = N | [{'(', _} | _] = Ts], As, Opt)
when Type =:= atom; Type =:= var ->
%% macro with arguments
{Args, Rest} = skip_macro_args(Ts),
- macro_call(Args, L, N, Rest, As, Opt);
-scan_macros([{'?', L}, {Type, _, _} = N | Ts], As, Opt)
+ macro_call(Args, Anno, N, Rest, As, Opt);
+scan_macros([{'?', Anno}, {Type, _, _} = N | Ts], As, Opt)
when Type =:= atom; Type =:= var ->
%% macro without arguments
- macro(L, N, Ts, As, Opt);
+ macro(Anno, N, Ts, As, Opt);
scan_macros([T | Ts], As, Opt) ->
scan_macros(Ts, [T | As], Opt);
scan_macros([], As, _Opt) ->
@@ -766,15 +777,18 @@ scan_macros([], As, _Opt) ->
%% Rewriting to a call which will be recognized by the post-parse pass
%% (we insert parentheses to preserve the precedences when parsing).
-macro(L, {Type, _, A}, Rest, As, Opt) ->
- do_scan_macros([], Rest, [{atom, L, macro_atom(Type, A)} | As], Opt).
+macro(Anno, {Type, _, A}, Rest, As, Opt) ->
+ do_scan_macros([], Rest, [{atom, Anno, macro_atom(Type, A)} | As], Opt).
-macro_call([{'(', _}, {')', _}], L, {_, Ln, _} = N, Rest, As, Opt) ->
+macro_call([{'(', _}, {')', _}], Anno, {_, AnnoN, _} = N, Rest, As, Opt) ->
{Open, Close} = parentheses(As),
do_scan_macros([],
Rest,
- lists:reverse(Open ++ [{atom, L, ?macro_call}, {'(', L}, N, {')', Ln}] ++ Close,
- As),
+ lists:reverse(
+ Open ++
+ [{atom, Anno, ?macro_call}, {'(', Anno}, N, {')', AnnoN}] ++
+ Close,
+ As),
Opt);
macro_call([{'(', _} | Args], L, {_, Ln, _} = N, Rest, As, Opt) ->
{Open, Close} = parentheses(As),
@@ -798,19 +812,19 @@ parentheses(_) ->
{[{'(', 0}], [{')', 0}]}.
%% (after a macro has been found and the arglist skipped, if any)
-do_scan_macros(Args, [{string, L, _} | _] = Rest, As, #opt{clever = true} = Opt) ->
+do_scan_macros(Args, [{string, AnnoS, _} | _] = Rest, As, #opt{clever = true} = Opt) ->
%% string literal following macro: be clever and insert ++
- scan_macros(Args ++ [{'++', L} | Rest], As, Opt);
+ scan_macros(Args ++ [{'++', AnnoS} | Rest], As, Opt);
do_scan_macros(Args, Rest, As, Opt) ->
%% normal case - continue scanning
scan_macros(Args ++ Rest, As, Opt).
-rewrite_form({function, L, ?pp_form, _, [{clause, _, [], [], [{call, _, A, As}]}]}) ->
+rewrite_form({function, Anno, ?pp_form, _, [{clause, _, [], [], [{call, _, A, As}]}]}) ->
erl_syntax:set_pos(
- erl_syntax:attribute(A, rewrite_list(As)), L);
-rewrite_form({function, L, ?pp_form, _, [{clause, _, [], [], [A]}]}) ->
+ erl_syntax:attribute(A, rewrite_list(As)), Anno);
+rewrite_form({function, Anno, ?pp_form, _, [{clause, _, [], [], [A]}]}) ->
erl_syntax:set_pos(
- erl_syntax:attribute(A), L);
+ erl_syntax:attribute(A), Anno);
rewrite_form(T) ->
rewrite(T).
@@ -904,11 +918,11 @@ fix_stringyfied_macros([{'?', Pos}, {atom, Pos, MacroName} | Rest], Ts) ->
fix_stringyfied_macros([Other | Rest], Ts) ->
fix_stringyfied_macros(Rest, [Other | Ts]).
-fix_define([{atom, L, ?pp_form},
+fix_define([{atom, Anno, ?pp_form},
{'(', _},
{')', _},
{'->', _},
- {atom, La, define},
+ {atom, AnnoA, define},
{'(', _},
N,
{',', _}
@@ -916,12 +930,12 @@ fix_define([{atom, L, ?pp_form},
[{dot, _}, {')', _} | Ts1] = lists:reverse(Ts),
S = tokens_to_string(lists:reverse(Ts1)),
A = erl_syntax:set_pos(
- erl_syntax:atom(define), La),
+ erl_syntax:atom(define), AnnoA),
Txt = erl_syntax:set_pos(
- erl_syntax:text(S), La),
+ erl_syntax:text(S), AnnoA),
{form,
erl_syntax:set_pos(
- erl_syntax:attribute(A, [N, Txt]), L)};
+ erl_syntax:attribute(A, [N, Txt]), Anno)};
fix_define(_Ts) ->
no_fix.
diff --git a/test/files/otp27.erl b/test/files/otp27.erl
index 2e09d09..e7b0083 100644
--- a/test/files/otp27.erl
+++ b/test/files/otp27.erl
@@ -6,13 +6,8 @@
-export([break/0]).
-break() ->
- _ = scan:string(~"""
+break( ) -> _ = scan : string( ~ "" "
This is valid code.
- """),
-
- Fun = fun () -> ok end,
- ?assertMatch({ok, _}
- when is_function(Fun, 0), {ok, 'no'}).
+ " "" ) , Fun = fun ( ) -> ok end , ?assertMatch( { ok , _ } when is_function( Fun , 0 ) , { ok , 'no' } ) .
-endif.