从内部获取堆栈跟踪 Code.eval_quoted

Get stacktrace from inside Code.eval_quoted

在 Elixir 中评估引用块时,是否可以获得完整的堆栈跟踪或查看在哪一行抛出错误?

例如我有这个模块:

defmodule Test do
  def trySomeQuotedCode() do
    quote do
      IO.puts "line 1"
      IO.puts "line 2"
      5/0
    end
    |> evalMyQuoted
  end

  def evalMyQuoted(quoted) do
    Code.eval_quoted(quoted)
  end
end

但是如果你执行它,你会看到:

它显示有一个 ArithmeticError:erlang./(5, 0),这是正确的,但它没有显示引用代码中的位置。通过这个小例子,仍然很容易找到代码中的错误所在,但是如果这个引用的代码更大或更高级,它可能不会那么微不足道。

那么,对于这个例子,是否有可能让堆栈跟踪表明在引用部分的评估中错误出现在 "line 3" 上?或者从 Code.eval_quoted?

中获取行号作为 return 值

TLDR: 使用 location: :keep.


您可以在宏中定义 quote,如下所示:

defmodule Test do
    defmacro my_quote do
        quote do
            IO.puts "line 1"
            IO.puts "line 2"
            5/0
        end
    end

    def try_quote do
        my_quote()  # Line 11
    end
end

正在呼叫 Test.try_quote:

iex(7)> Test.try_quote
line 1
line 2
** (ArithmeticError) bad argument in arithmetic expression
    test.exs:11: Test.try_quote/0

所以我们得到调用引用的行,这更好,但还不是我们想要的。

解决方案可能是使用宏为我们定义一个函数,如下所示:

defmodule TestMacro do
  defmacro my_quote do
    quote do
      def my_function do
        IO.puts "line 1"
        IO.puts "line 2"
        5/0 # Line 7
      end
    end
  end
end

defmodule Test do
  import TestMacro
  my_quote # Line 15
end

现在调用 Test.my_function 给我们:

line 1
line 2
** (ArithmeticError) bad argument in arithmetic expression
    test.exs:15: Test.my_function/0

仍然是调用宏的那一行!但是现在如果我们将引用定义(第 3 行)更改为

quote location: :keep do

我们终于得到了错误发生的确切行:

line 1
line 2
** (ArithmeticError) bad argument in arithmetic expression
    test.exs:7: Test.my_function/0

您要找的是location: :keep option in the call to Kernel.quote/2