From 01af89d2f11e8c012975bb1b449bcee32726ccb1 Mon Sep 17 00:00:00 2001 From: Jean Klingler Date: Mon, 30 Sep 2024 16:31:31 +0900 Subject: [PATCH] Fix handling of erlang syntax errors (#2800) --- lib/livebook/runtime/evaluator.ex | 27 +++------------ test/livebook/runtime/evaluator_test.exs | 42 +++++++++++++++++++++--- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/lib/livebook/runtime/evaluator.ex b/lib/livebook/runtime/evaluator.ex index 518e90c7a..2343b8479 100644 --- a/lib/livebook/runtime/evaluator.ex +++ b/lib/livebook/runtime/evaluator.ex @@ -785,29 +785,10 @@ defmodule Livebook.Runtime.Evaluator do end defp make_snippet(code, location) do - start_line = 1 - start_column = 1 - line = :erl_anno.line(location) - - case :erl_anno.column(location) do - :undefined -> - nil - - column -> - lines = :string.split(code, "\n", :all) - snippet = :lists.nth(line - start_line + 1, lines) - - offset = - if line == start_line do - column - start_column - else - column - 1 - end - - case :string.trim(code, :leading) do - [] -> nil - _ -> %{content: snippet, offset: offset} - end + if :erl_anno.column(location) != :undefined and :string.trim(code, :leading) != [] do + line = :erl_anno.line(location) + lines = :string.split(code, "\n", :all) + :lists.nth(line, lines) end end diff --git a/test/livebook/runtime/evaluator_test.exs b/test/livebook/runtime/evaluator_test.exs index e3541c773..6d2fe89f0 100644 --- a/test/livebook/runtime/evaluator_test.exs +++ b/test/livebook/runtime/evaluator_test.exs @@ -1373,22 +1373,56 @@ defmodule Livebook.Runtime.EvaluatorTest do # Incomplete input Evaluator.evaluate_code(evaluator, :erlang, "X =", :code_1, []) assert_receive {:runtime_evaluation_response, :code_1, error(message), metadata()} - assert "\e[31m** (TokenMissingError)" <> _ = message + + assert clean_message(message) === """ + ** (TokenMissingError) token missing on nofile:1:4: + error: syntax error before: + │ + 1 │ X = + │ ^ + │ + └─ nofile:1:4\ + """ # Parser error Evaluator.evaluate_code(evaluator, :erlang, "X ==/== a.", :code_2, []) assert_receive {:runtime_evaluation_response, :code_2, error(message), metadata()} - assert "\e[31m** (SyntaxError)" <> _ = message + + assert clean_message(message) === """ + ** (SyntaxError) invalid syntax found on nofile:1:5: + error: syntax error before: /= + │ + 1 │ X ==/== a. + │ ^ + │ + └─ nofile:1:5\ + """ # Tokenizer error Evaluator.evaluate_code(evaluator, :erlang, "$a$", :code_3, []) assert_receive {:runtime_evaluation_response, :code_3, error(message), metadata()} - assert "\e[31m** (SyntaxError)" <> _ = message + + assert clean_message(message) === """ + ** (SyntaxError) invalid syntax found on nofile:1:3: + error: unterminated character + │ + 1 │ $a$ + │ ^ + │ + └─ nofile:1:3\ + """ # Erlang exception Evaluator.evaluate_code(evaluator, :erlang, "list_to_binary(1).", :code_4, []) assert_receive {:runtime_evaluation_response, :code_4, error(message), metadata()} - assert "\e[31mexception error: bad argument" <> _ = message + + assert clean_message(message) === """ + exception error: bad argument + in function list_to_binary/1 + called as list_to_binary(1) + *** argument 1: not an iolist term + in call from erl_eval:do_apply/7 (erl_eval.erl, line 900)\ + """ end end