From 3e3531026b2f8ebd89d354850820d1fbd302eeeb Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Fri, 8 Jan 2021 14:31:52 +0100 Subject: [PATCH 1/2] Handle annotations and locations better This PR is one of several affecting repositories on Github. It aims at fixing bad use of annotations (see erl_anno(3)). The following remarks are common to all PR:s. Typically the second element of abstract code tuples is assumed to be an integer, which is no longer always true. For instance, the parse transform implementing QLC tables (see qlc(3)) returns code where some annotations are marked as `generated'. Such an annotation is a list, not an integer (it used to be a negative integer). As of Erlang/OTP 24.0, the location can be a tuple {Line, Column}, which is another reason to handle annotations properly. --- src/partial.erl | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/partial.erl b/src/partial.erl index 89449e4..afa9814 100644 --- a/src/partial.erl +++ b/src/partial.erl @@ -216,7 +216,8 @@ transform_forms(Forms, Options) -> end || Form <- Forms])). transform(Form, Errors, Options) -> - Line = erl_syntax:get_pos(Form), + Pos = erl_syntax:get_pos(Form), + Line = get_line(Pos), Transformed = case Form of ?Q("partial:cut(_@@Args)") -> cut_function(Line, Args); @@ -289,8 +290,9 @@ split_name(Name) -> [Name] end. -match(Line, Type, Form) -> - Pattern = variable(Line, Type), +match(Pos, Type, Form) -> + Pattern = variable(Pos, Type), + Line = get_line(Pos), Match = merl:qquote(Line, "_@pattern = _@form", [{pattern, Pattern}, {form, Form}]), @@ -358,9 +360,10 @@ cut_function(MarkerLine, [MarkerArgument])-> ?IF_DEBUG(ok = io:format( "partial:cut_function/2 Original:~n~p~n", [MarkerArgument])), - Line = erl_syntax:get_pos(MarkerArgument), - NameCut = name_cuts(Line, Name), - Cut = cuts(Line, cut, Args), + Pos = erl_syntax:get_pos(MarkerArgument), + Line = get_line(Pos), + NameCut = name_cuts(Pos, Name), + Cut = cuts(Pos, cut, Args), CutFun = merl:qquote(Line, "fun (_@@variables) ->" " _@name(_@@arguments)" @@ -407,9 +410,10 @@ cute_function(MarkerLine, [MarkerArgument])-> ?IF_DEBUG(ok = io:format( "partial:cute_function/2 Original:~n~p~n", [MarkerArgument])), - Line = erl_syntax:get_pos(MarkerArgument), - NameCute = name_cutes(Line, Name), - Cute = cutes(Line, cute, Args), + Pos = erl_syntax:get_pos(MarkerArgument), + Line = get_line(Pos), + NameCute = name_cutes(Pos, Name), + Cute = cutes(Pos, cute, Args), CuteFun = merl:qquote(Line, "(fun () ->" " _@@matches," @@ -434,3 +438,11 @@ cute_function(MarkerLine, MarkerArguments)-> io_lib:format( "partial:cute/1 requires a single argument, got ~b", [length(MarkerArguments)])). + +get_line(Pos) -> + case erl_anno:is_anno(Pos) of + true -> + erl_anno:line(Pos); + false -> + Pos + end. From 9ea303a6266474a1dd4d790ebcc6030a536bf8f1 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Mon, 11 Jan 2021 09:58:22 +0100 Subject: [PATCH 2/2] Substitute Pos for Line Just to clearify that Pos is not necessarily an integer line number. --- src/partial.erl | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/partial.erl b/src/partial.erl index afa9814..d9d162c 100644 --- a/src/partial.erl +++ b/src/partial.erl @@ -274,8 +274,8 @@ variable_name(Type) -> Name = io_lib:format("PartialArgument_~s_~w", [Type, make_ref()]), erlang:list_to_atom(lists:flatten(Name)). -variable(Line, Type) -> - erl_syntax:set_pos(erl_syntax:variable(variable_name(Type)), Line). +variable(Pos, Type) -> + erl_syntax:set_pos(erl_syntax:variable(variable_name(Type)), Pos). name([Name]) -> [Name]; @@ -298,12 +298,12 @@ match(Pos, Type, Form) -> [{pattern, Pattern}, {form, Form}]), {Pattern, Match}. -cuts(Line, Type, Forms) -> +cuts(Pos, Type, Forms) -> reverse(lists:foldl( fun (Form, #cut{} = Acc) -> case is_cut_variable(Form) of true -> - Variable = variable(Line, Type), + Variable = variable(Pos, Type), Acc#cut{variables=[Variable | Acc#cut.variables], arguments=[Variable | Acc#cut.arguments]}; false -> @@ -313,23 +313,23 @@ cuts(Line, Type, Forms) -> #cut{}, Forms)). -name_cuts(Line, Name) -> +name_cuts(Pos, Name) -> Parts = split_name(Name), - Cut = cuts(Line, name, Parts), + Cut = cuts(Pos, name, Parts), Cut#cut{arguments=name(Cut#cut.arguments)}. -cutes(Line, Type, Forms) -> +cutes(Pos, Type, Forms) -> reverse(lists:foldl( fun (Form, #cute{} = Acc) -> case {is_cut_variable(Form), erl_syntax:is_literal(Form)} of {true, false} -> - Variable = variable(Line, Type), + Variable = variable(Pos, Type), Acc#cute{variables=[Variable | Acc#cute.variables], arguments=[Variable | Acc#cute.arguments]}; {false, true} -> Acc#cute{arguments=[Form | Acc#cute.arguments]}; {false, false} -> - {Variable, Match} = match(Line, Type, Form), + {Variable, Match} = match(Pos, Type, Form), Acc#cute{matches=[Match | Acc#cute.matches], arguments=[Variable | Acc#cute.arguments]} end @@ -337,9 +337,9 @@ cutes(Line, Type, Forms) -> #cute{}, Forms)). -name_cutes(Line, Name) -> +name_cutes(Pos, Name) -> Parts = split_name(Name), - Cute = cutes(Line, name, Parts), + Cute = cutes(Pos, name, Parts), Cute#cute{arguments=name(Cute#cute.arguments)}. %% @private