katana-code icon indicating copy to clipboard operation
katana-code copied to clipboard

ktn_code fails since ktn_dodger cannot parse macro functions in function clauses

Open sebastiw opened this issue 5 years ago • 3 comments

Given the following module

-module(macros).
-define(MATCH_NAME(), #{name := "Per"}).
is_adult(?MATCH_NAME()) ->
    false.
1> File = "path/to/macros.erl".
"path/to/macros.erl"
2> {ok, Dev} = file:open(File, [read]).
{ok, <0.328.0>}.
3> ktn_dodger:parse_form(Dev, 1, [{scan_opts, [text]}]).
{ok,{tree,attribute,
          {attr,[{text,"module"},{location,1}],[],none},
          {attribute,{tree,atom,
                           {attr,[{text,"module"},{location,1}],[],none},
                           module},
                     [{tree,atom,
                            {attr,[{text,"module"},{location,1}],[],none},
                            macros}]}},
    2}
4> ktn_dodger:parse_form(Dev, 2, [{scan_opts, [text]}]).
{ok,{tree,attribute,
          {attr,[{text,"define"},{location,2}],[],none},
          {attribute,{atom,[{text,"define"},{location,2}],define},
                     [{tree,application,
                            {attr,[{text,"MATCH_NAME"},{location,2}],[],none},
                            {application,{var,[{text,"MATCH_NAME"},{location,2}],
                                              'MATCH_NAME'},
                                         []}},
                      {tree,map_expr,
                            {attr,[{text,"#"},{location,2}],[],none},
                            {map_expr,none,
                                      [{tree,map_field_exact,
                                             {attr,[{text,"name"},{location,2}],[],none},
                                             {map_field_exact,{atom,[{text,...},{...}],name},
                                                              {string,[{...}|...],[...]}}}]}}]}},
    3}
5> ktn_dodger:parse_form(Dev, 2, [{scan_opts, [text]}]).
{error,{3,erl_parse,["syntax error before: ","?"]},5}

Problem seems to reside in ktn_dodger:scan_form which does not send correct thing to erl_parse:parse_form.

6> file:close(Dev), f(Dev), {ok, Dev} = file:open(File, [read]).
{ok, <0.333.0>}
7> c(ktn_dodger, [export_all]).
{ok, ktn_dodger}
8> {ok, Ts1, _} = io:scan_erl_form(Dev, "", 1, [{scan_opts, [text]}]).
{ok,[{'-',1},
     {atom,1,module},
     {'(',1},
     {atom,1,macros},
     {')',1},
     {dot,1}],
    2}
9> S1 = ktn_dodger:scan_form(Ts1, {opt, false}). 
[{'-',1},
 {atom,1,module},
 {'(',1},
 {atom,1,macros},
 {')',1},
 {dot,1}]
10> erl_parse:parse_form(S1). 
{ok,{attribute,1,module,macros}}
11> {ok, Ts2, _} = io:scan_erl_form(Dev, "", 2, [{scan_opts, [text]}]).
{ok,[{'-',2},
     {atom,2,define},
     {'(',2},
     {var,2,'MATCH_NAME'},
     {'(',2},
     {')',2},
     {',',2},
     {'#',2},
     {'{',2},
     {atom,2,name},
     {':=',2},
     {string,2,"Per"},
     {'}',2},
     {')',2},
     {dot,2}],
    3}
12> S2 = ktn_dodger:scan_form(Ts2, {opt, false}).
[{atom,2,'?preprocessor declaration?'},
 {'(',2},
 {')',2},
 {'->',2},
 {atom,2,define},
 {'(',2},
 {var,2,'MATCH_NAME'},
 {'(',2},
 {')',2},
 {',',2},
 {'#',2},
 {'{',2},
 {atom,2,name},
 {':=',2},
 {string,2,"Per"},
 {'}',2}, 
 {')',2},
 {dot,2}]
13> erl_parse:parse_form(S2).
{ok,{function,2,'?preprocessor declaration?',0,
              [{clause,2,[],[],
                       [{call,2,
                              {atom,2,define},
                              [{call,2,{var,2,'MATCH_NAME'},[]},
                               {map,2,
                                    [{map_field_exact,2,{atom,2,...},{string,...}}]}]}]}]}}
14> {ok, Ts3, _} = io:scan_erl_form(Dev, "", 3, [{scan_opts, [text]}]).
{ok,[{atom,3,is_adult},
     {'(',3},
     {'?',3},
     {var,3,'MATCH_NAME'},
     {'(',3},
     {')',3},
     {')',3},
     {'->',3},
     {atom,4,false},
     {dot,4}],
    5}
15> S3 = ktn_dodger:scan_form(Ts3, {opt, false}).                      
[{atom,3,is_adult},
 {'(',3},
 {'(',0},
 {atom,3,'? <macro> ('},
 {'(',3},
 {var,3,'MATCH_NAME'},
 {')',3},
 {')',0},
 {')',3},
 {'->',3},
 {atom,4,false},
 {dot,4}]
16> erl_parse:parse_form(S3).                                          
{error,{3,erl_parse,["syntax error before: ","'('"]}}

sebastiw avatar Apr 22 '20 11:04 sebastiw

You should try with ktn_dodger:parse_form(Dev, 1, [{scan_opts, [text]}, no_fail]).

elbrujohalcon avatar Nov 11 '20 12:11 elbrujohalcon

haven't been able to look at it yet, but you suggest opening a PR changing this row?

https://github.com/inaka/katana-code/blob/9ae6f99ac8709f576bdf3f4a1ff638e307765f48/src/ktn_code.erl#L96

    {ok, Forms}     = ktn_dodger:parse( IoString
-                                     , {1, 1}
+                                     , 1
                                      , [{scan_opts, [text]}]
+                                     , no_fail
                                      ),

sebastiw avatar Nov 18 '20 09:11 sebastiw

Yeah, exactly. Sorry I closed the issue, I thought the usage of ktn_dodger was from another library not this one.

elbrujohalcon avatar Nov 18 '20 09:11 elbrujohalcon