Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
otp: ['23.3.4.7', '24.1']
elixir: ['1.12.3']
elixir: ['1.11.4', '1.12.3', '1.13.3']
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
Expand Down
3 changes: 2 additions & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
elixir 1.12.2-otp-23
elixir 1.12.3
erlang 24.1
4 changes: 2 additions & 2 deletions lib/gradient/elixir_expr.ex
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ defmodule Gradient.ElixirExpr do
"reraise " <> pp_expr(var) <> ", " <> pp_expr(var_stacktrace)
end

def pp_expr({:call, _, {:remote, _, {:atom, _, :erlang}, {:atom, _, :error}}, [arg]}) do
def pp_expr({:call, _, {:remote, _, {:atom, _, :erlang}, {:atom, _, :error}}, [arg | _]}) do
"raise " <> pp_raise_arg(arg)
end

Expand Down Expand Up @@ -405,7 +405,7 @@ defmodule Gradient.ElixirExpr do
defp bin_pp_value(val), do: pp_expr(val)

defp bin_set_value("", value), do: value
defp bin_set_value(sufix, value), do: value <> "::" <> sufix
defp bin_set_value(sufix, value), do: "(" <> value <> ")::" <> sufix

defp bin_set_size("", :default), do: ""
defp bin_set_size("", {:integer, _, size}), do: Integer.to_string(size)
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Gradient.MixProject do
[
app: :gradient,
version: "0.1.0",
elixir: "~> 1.12",
elixir: "~> 1.11",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
deps: deps(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule RangeEx do
defmodule RangeStep do
def range do
1..12
end
Expand Down
5 changes: 5 additions & 0 deletions test/examples/simple_range.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule SimpleRange do
def range do
1..12
end
end
2 changes: 1 addition & 1 deletion test/examples/tuple.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
defmodule Tuple do
defmodule TupleEx do
def tuple do
{:ok, 12}
end
Expand Down
74 changes: 55 additions & 19 deletions test/gradient/ast_specifier_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ defmodule Gradient.AstSpecifierTest do
end

test "tuple" do
{tokens, ast} = load("Elixir.Tuple.beam", "tuple.ex")
{tokens, ast} = load("Elixir.TupleEx.beam", "tuple.ex")

[tuple_in_str2, tuple_in_str, tuple_in_list, _list_in_tuple, tuple | _] =
AstSpecifier.run_mappers(ast, tokens) |> Enum.reverse()
Expand Down Expand Up @@ -625,8 +625,29 @@ defmodule Gradient.AstSpecifierTest do
]} = guarded_case
end

@tag :ex_lt_1_12
test "range" do
{tokens, ast} = load("Elixir.RangeEx.beam", "range.ex")
{tokens, ast} = load("Elixir.SimpleRange.beam", "simple_range.ex")

[range | _] = AstSpecifier.run_mappers(ast, tokens) |> Enum.reverse()

assert {:function, 2, :range, 0,
[
{:clause, 2, [], [],
[
{:map, 3,
[
{:map_field_assoc, 3, {:atom, 3, :__struct__}, {:atom, 3, Range}},
{:map_field_assoc, 3, {:atom, 3, :first}, {:integer, 3, 1}},
{:map_field_assoc, 3, {:atom, 3, :last}, {:integer, 3, 12}}
]}
]}
]} = range
end

@tag :ex_gt_1_11
test "step range" do
{tokens, ast} = load("Elixir.RangeStep.beam", "1.12/range_step.ex")

[to_list, match_range, rev_range_step, range_step, range | _] =
AstSpecifier.run_mappers(ast, tokens) |> Enum.reverse()
Expand Down Expand Up @@ -711,6 +732,24 @@ defmodule Gradient.AstSpecifierTest do

[block | _] = AstSpecifier.run_mappers(ast, tokens) |> Enum.reverse()

range =
if System.version() >= "1.12" do
{:map, 11,
[
{:map_field_assoc, 11, {:atom, 11, :__struct__}, {:atom, 11, Range}},
{:map_field_assoc, 11, {:atom, 11, :first}, {:integer, 11, 0}},
{:map_field_assoc, 11, {:atom, 11, :last}, {:integer, 11, 5}},
{:map_field_assoc, 11, {:atom, 11, :step}, {:integer, 11, 1}}
]}
else
{:map, 11,
[
{:map_field_assoc, 11, {:atom, 11, :__struct__}, {:atom, 11, Range}},
{:map_field_assoc, 11, {:atom, 11, :first}, {:integer, 11, 0}},
{:map_field_assoc, 11, {:atom, 11, :last}, {:integer, 11, 5}}
]}
end

assert {:function, 10, :lc_complex, 0,
[
{:clause, 10, [], [],
Expand All @@ -719,13 +758,7 @@ defmodule Gradient.AstSpecifierTest do
[
{:call, 11, {:remote, 11, {:atom, 11, Enum}, {:atom, 11, :reduce}},
[
{:map, 11,
[
{:map_field_assoc, 11, {:atom, 11, :__struct__}, {:atom, 11, Range}},
{:map_field_assoc, 11, {:atom, 11, :first}, {:integer, 11, 0}},
{:map_field_assoc, 11, {:atom, 11, :last}, {:integer, 11, 5}},
{:map_field_assoc, 11, {:atom, 11, :step}, {:integer, 11, 1}}
]},
^range,
{nil, 11},
{:fun, 11,
{:clauses,
Expand Down Expand Up @@ -823,6 +856,7 @@ defmodule Gradient.AstSpecifierTest do
{:bin_element, 7, {:string, 7, 'oops'}, :default, :default}
]}
]}
| _
]}
]},
{:clause, [generated: true, location: 4],
Expand Down Expand Up @@ -950,6 +984,7 @@ defmodule Gradient.AstSpecifierTest do
:default, :default}
]}
]}
| _
]}
], [], [],
[
Expand All @@ -972,6 +1007,7 @@ defmodule Gradient.AstSpecifierTest do
{:cons, 52, {:integer, 52, 49},
{:cons, 52, {:integer, 52, 50}, {nil, 52}}}
]}
| _
]},
{:integer, 53, 1}
], [], [], [{:op, 55, :-, {:integer, 55, 1}}]}
Expand Down Expand Up @@ -1049,6 +1085,8 @@ defmodule Gradient.AstSpecifierTest do
[get2, get, update, empty, struct | _] =
AstSpecifier.run_mappers(ast, tokens) |> Enum.reverse()

anno_line_17 = if(System.version() >= "1.12", do: [generated: true, location: 17], else: 17)

assert {:function, 8, :update, 0,
[
{:clause, 8, [], [],
Expand All @@ -1070,18 +1108,17 @@ defmodule Gradient.AstSpecifierTest do
{:map, 17,
[
{:map_field_exact, 17, {:atom, [generated: true, location: 17], :x},
{:var, [generated: true, location: 17], :_@1}}
{:var, ^anno_line_17, :_@1}}
]}
], [], [{:var, [generated: true, location: 17], :_@1}]},
{:clause, [generated: true, location: 17],
[{:var, [generated: true, location: 17], :_@1}],
], [], [{:var, ^anno_line_17, :_@1}]},
{:clause, [generated: true, location: 17], [{:var, ^anno_line_17, :_@1}],
[
[
{:call, [generated: true, location: 17],
{:remote, [generated: true, location: 17],
{:atom, [generated: true, location: 17], :erlang},
{:atom, [generated: true, location: 17], :is_map}},
[{:var, [generated: true, location: 17], :_@1}]}
[{:var, ^anno_line_17, :_@1}]}
]
],
[
Expand All @@ -1091,16 +1128,15 @@ defmodule Gradient.AstSpecifierTest do
[
{:atom, 17, :badkey},
{:atom, 17, :x},
{:var, [generated: true, location: 17], :_@1}
{:var, ^anno_line_17, :_@1}
]}
]}
]},
{:clause, [generated: true, location: 17],
[{:var, [generated: true, location: 17], :_@1}], [],
{:clause, [generated: true, location: 17], [{:var, ^anno_line_17, :_@1}], [],
[
{:call, [generated: true, location: 17],
{:remote, [generated: true, location: 17],
{:var, [generated: true, location: 17], :_@1}, {:atom, 17, :x}}, []}
{:remote, [generated: true, location: 17], {:var, ^anno_line_17, :_@1},
{:atom, 17, :x}}, []}
]}
]}}
]}
Expand Down
62 changes: 57 additions & 5 deletions test/gradient/elixir_expr_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ defmodule Gradient.ElixirExprTest do
end
|> ElixirExpr.pp_expr()

assert "pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>; for <<r::8, g::8, b::8 <- pixels >>, do: {r, g, b}" ==
assert "pixels = <<213, 45, 132, 64, 76, 32, 76, 0, 0, 234, 32, 15>>; for <<(r)::8, (g)::8, (b)::8 <- pixels >>, do: {r, g, b}" ==
actual
end

Expand All @@ -67,7 +67,7 @@ defmodule Gradient.ElixirExprTest do
end
|> ElixirExpr.pp_expr()

assert "for <<one, _rest::binary-size(3) <- <<1, 2, 3, 4>> >>, do: one" == actual
assert "for <<one, (_rest)::binary-size(3) <- <<1, 2, 3, 4>> >>, do: one" == actual
end

test "receive" do
Expand Down Expand Up @@ -328,8 +328,7 @@ defmodule Gradient.ElixirExprTest do
end

test "pp and format complex try expression" do
{_tokens, ast} =
Gradient.TestHelpers.load("Elixir.CallRemoteException.beam", "call_remote_exception.ex")
ast = Gradient.TestHelpers.load("Elixir.CallRemoteException.beam")

{:function, _, :call, 2, [{:clause, _ann, _args, _guards, [try_expr]}]} =
Enum.reverse(ast) |> List.first()
Expand All @@ -338,7 +337,58 @@ defmodule Gradient.ElixirExprTest do

# FIXME `raise {:badkey, :stack, _gen}` is not correct

expected = ~s"""
expected_v1_11 = ~s"""
try do
:ok
catch
:error, %Plug.Conn.WrapperError{} = e ->
exception =
Exception.normalize(
:error,
case e do
%{reason: _} -> _
_ when :erlang.is_map(_) -> raise {:badkey, :reason, _}
_ -> _.reason()
end,
case e do
%{stack: _} -> _
_ when :erlang.is_map(_) -> raise {:badkey, :stack, _}
_ -> _.stack()
end
)

_ =
Sentry.capture_exception(exception, [
{:stacktrace,
case e do
%{stack: _} -> _
_ when :erlang.is_map(_) -> raise {:badkey, :stack, _}
_ -> _.stack()
end},
{:event_source, :plug}
])

Plug.Conn.WrapperError.reraise(e)

:error, e ->
_ = Sentry.capture_exception(e, [{:stacktrace, __STACKTRACE__}, {:event_source, :plug}])
:erlang.raise(:error, e, __STACKTRACE__)

kind, reason ->
message =
<<"Uncaught ",
case kind do
_gen when :erlang.is_binary(_gen) -> _gen
_gen -> String.Chars.to_string(_gen)
end::binary, " - ", Kernel.inspect(reason)::binary>>

stack = __STACKTRACE__
_ = Sentry.capture_message(message, [{:stacktrace, stack}, {:event_source, :plug}])
:erlang.raise(kind, reason, stack)
end
"""

expected_v1_12 = ~s"""
try do
:ok
catch
Expand Down Expand Up @@ -389,6 +439,8 @@ defmodule Gradient.ElixirExprTest do
end
"""

expected = if(System.version() >= "1.12", do: expected_v1_12, else: expected_v1_11)

assert expected == :erlang.iolist_to_binary(res) <> "\n"
end
end
2 changes: 1 addition & 1 deletion test/mix/tasks/gradient_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ defmodule Mix.Tasks.GradientTest do
assert not String.contains?(output, ex_spec_error_msg)
end

@tag if(System.version() >= "1.13", do: :skip, else: :ok)
@tag :ex_lt_1_13
test "--no-specify option" do
output = run_task(test_opts([@s_wrong_ret_beam]))
assert String.contains?(output, "on line 3")
Expand Down
12 changes: 6 additions & 6 deletions test/support/expr_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ defmodule Gradient.ExprData do
bin_with_bin_var(),
bin_with_pp_int_size(),
bin_with_pp_and_bitstring_size(),
{"bin float", elixir_to_ast(<<4.3::float>>), "<<4.3::float>>"}
{"bin float", elixir_to_ast(<<4.3::float>>), "<<(4.3)::float>>"}
]
end

Expand All @@ -150,7 +150,7 @@ defmodule Gradient.ExprData do
<<a::8, _rest::binary>> = <<1, 2, 3, 4>>
end

{"bin pattern matching with bin var", ast, "<<a::8, _rest::binary>> = <<1, 2, 3, 4>>"}
{"bin pattern matching with bin var", ast, "<<(a)::8, (_rest)::binary>> = <<1, 2, 3, 4>>"}
end

defp bin_joining_syntax do
Expand All @@ -160,7 +160,7 @@ defmodule Gradient.ExprData do
"a" <> x
end

{"binary <> joining", ast, ~s(x = "b"; <<"a", x::binary>>)}
{"binary <> joining", ast, ~s(x = "b"; <<"a", (x\)::binary>>)}
end

defp bin_with_bin_var do
Expand All @@ -170,7 +170,7 @@ defmodule Gradient.ExprData do
<<"a", "b", x::binary>>
end

{"binary with bin var", ast, ~s(x = "b"; <<"a", "b", x::binary>>)}
{"binary with bin var", ast, ~s(x = "b"; <<"a", "b", (x\)::binary>>)}
end

defp bin_with_pp_int_size do
Expand All @@ -179,7 +179,7 @@ defmodule Gradient.ExprData do
<<a::16>> = <<"abcd">>
end

{"binary with int size", ast, ~s(<<a::16>> = "abcd")}
{"binary with int size", ast, ~s(<<(a\)::16>> = "abcd")}
end

defp bin_with_pp_and_bitstring_size do
Expand All @@ -191,7 +191,7 @@ defmodule Gradient.ExprData do
end

expected =
"<<header::8, length::32, message::bitstring-size(144)>> = <<1, 2, 3, 4, 5, 101, 114, 97, 115, 101, 32, 116, 104, 101, 32, 101, 118, 105, 100, 101, 110, 99, 101>>"
"<<(header)::8, (length)::32, (message)::bitstring-size(144)>> = <<1, 2, 3, 4, 5, 101, 114, 97, 115, 101, 32, 116, 104, 101, 32, 101, 118, 105, 100, 101, 110, 99, 101>>"

{"binary with patter matching and bitstring-size", ast, expected}
end
Expand Down
Loading