Skip to content

Commit e6dce2a

Browse files
committed
Support Elixir 1.13
In version >= 1.13 some expressions previously without a line now have a line propagated from a parent. This line does not always match the location of the expression in the code. So we still need to look at the tokens to correct these locations. This location presence required small changes in the AstSpecifier code because now we can't be sure when the expression has a line then this line is correct. Changes: - Adapt debug.ex to new elixir api - Add specifying a line in nil. - Propagate a generated flag from clauses to conditions. - Consume the beginning token of list or tuple. - Stop predicting the last line of the form from :bin or :cons expressions.
1 parent 4c4ac7e commit e6dce2a

File tree

2 files changed

+40
-16
lines changed

2 files changed

+40
-16
lines changed

lib/gradient/ast_specifier.ex

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ defmodule Gradient.AstSpecifier do
203203
if not :erl_anno.generated(anno) do
204204
context_mapper_fold(args, tokens, opts)
205205
else
206+
opts = Keyword.put(opts, :generated, :erl_anno.generated(anno))
207+
{args, []} = context_mapper_fold(args, [], opts)
206208
{args, tokens}
207209
end
208210

@@ -211,6 +213,8 @@ defmodule Gradient.AstSpecifier do
211213
{:clause, anno, args, guards, children}
212214
|> pass_tokens(tokens)
213215
else
216+
arg_opts = Keyword.put(opts, :generated, :erl_anno.generated(anno))
217+
{args, []} = context_mapper_fold(args, [], arg_opts)
214218
{children, tokens} = children |> context_mapper_fold(tokens, opts)
215219

216220
{:clause, anno, args, guards, children}
@@ -263,7 +267,6 @@ defmodule Gradient.AstSpecifier do
263267
def mapper({:cons, anno, value, more} = cons, tokens, opts) do
264268
# anno could be 0
265269
{:ok, line, anno, opts, _} = get_line(anno, opts)
266-
267270
tokens = drop_tokens_to_line(tokens, line)
268271

269272
case get_list(tokens, opts) do
@@ -286,14 +289,16 @@ defmodule Gradient.AstSpecifier do
286289

287290
def mapper({:tuple, anno, elements}, tokens, opts) do
288291
# anno could be 0
289-
{:ok, line, anno, opts, has_line?} = get_line(anno, opts)
292+
{:ok, line, anno, opts, _} = get_line(anno, opts)
290293

291294
tokens
292295
|> drop_tokens_to_line(line)
293296
|> get_tuple(opts)
294297
|> case do
295298
{:tuple, tokens} ->
296-
{anno, opts} = update_line_from_tokens(tokens, anno, opts, has_line?)
299+
{anno, opts} = update_line_from_tokens(tokens, anno, opts)
300+
# drop a token that begins tuple
301+
tokens = drop_tokens_while(tokens, fn t -> elem(t, 0) in [:"{"] end)
297302

298303
{elements, tokens} = context_mapper_fold(elements, tokens, opts)
299304

@@ -412,12 +417,21 @@ defmodule Gradient.AstSpecifier do
412417
end
413418
end
414419

415-
def mapper({type, 0, value}, tokens, opts)
420+
def mapper({nil, _}, tokens, opts) do
421+
{:ok, line} = Keyword.fetch(opts, :line)
422+
423+
{nil, line}
424+
|> pass_tokens(tokens)
425+
end
426+
427+
def mapper({type, anno, value}, tokens, opts)
416428
when type in [:atom, :char, :float, :integer, :string, :bin] do
417429
# TODO check what happend for :string
418430
{:ok, line} = Keyword.fetch(opts, :line)
431+
anno = :erl_anno.set_line(line, anno)
432+
anno = :erl_anno.set_generated(Keyword.get(opts, :generated, false), anno)
419433

420-
{type, line, value}
434+
{type, anno, value}
421435
|> specify_line(tokens, opts)
422436
end
423437

@@ -560,9 +574,11 @@ defmodule Gradient.AstSpecifier do
560574
"""
561575
@spec cons_mapper(form(), [token()], options()) :: {form(), tokens()}
562576
def cons_mapper({:cons, anno, value, tail}, tokens, opts) do
563-
{:ok, _, anno, opts, has_line?} = get_line(anno, opts)
577+
{:ok, _, anno0, opts0, _} = get_line(anno, opts)
564578

565-
{anno, opts} = update_line_from_tokens(tokens, anno, opts, has_line?)
579+
{anno, opts} = update_line_from_tokens(tokens, anno0, opts0)
580+
# drop a token that begins list
581+
tokens = drop_tokens_while(tokens, fn t -> elem(t, 0) in [:"["] end)
566582

567583
{new_value, tokens} = mapper(value, tokens, opts)
568584

@@ -720,18 +736,14 @@ defmodule Gradient.AstSpecifier do
720736
{:cons, loc, {:integer, loc, value}, charlist_set_loc(tail, loc)}
721737
end
722738

723-
def charlist_set_loc({nil, loc}, _), do: {nil, loc}
739+
def charlist_set_loc({nil, _}, loc), do: {nil, loc}
724740

725-
def put_line(anno, opts, line) do
726-
{:erl_anno.set_line(line, anno), Keyword.put(opts, :line, line)}
727-
end
728-
729-
def update_line_from_tokens([token | _], anno, opts, false) do
741+
def update_line_from_tokens([token | _], anno, opts) do
730742
line = get_line_from_token(token)
731-
put_line(anno, opts, line)
743+
{:erl_anno.set_line(line, anno), Keyword.put(opts, :line, line)}
732744
end
733745

734-
def update_line_from_tokens(_, anno, opts, _) do
746+
def update_line_from_tokens(_, anno, opts) do
735747
{anno, opts}
736748
end
737749

@@ -761,6 +773,14 @@ defmodule Gradient.AstSpecifier do
761773
end
762774

763775
defp set_form_end_line(opts, form, forms) do
776+
if elem(form, 0) not in [:bin, :cons] do
777+
set_form_end_line_(opts, form, forms)
778+
else
779+
opts
780+
end
781+
end
782+
783+
defp set_form_end_line_(opts, form, forms) do
764784
case Enum.find(forms, fn f ->
765785
anno = elem(f, 1)
766786

lib/gradient/debug.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ defmodule Gradient.Debug do
2424
@spec quoted_to_ast(elixir_form()) :: erlang_form()
2525
def quoted_to_ast(qt) do
2626
env = :elixir_env.new()
27-
{ast, _, _} = :elixir.quoted_to_erl(qt, env)
27+
28+
ast =
29+
:elixir.quoted_to_erl(qt, env)
30+
|> elem(0)
31+
2832
Macro.escape(ast)
2933
end
3034

0 commit comments

Comments
 (0)