diff options
author | Wojtek Mach <wojtekmach@users.noreply.github.com> | 2019-09-27 17:46:10 +0200 |
---|---|---|
committer | Fernando Tapia Rico <fertapric@gmail.com> | 2019-09-27 17:46:10 +0200 |
commit | d199a18075bef37e5184afa17a34c756e4013cdd (patch) | |
tree | 7376404071ce67d4ad54ab79959e2f7b07c160fa | |
parent | 4253fdaead5f586bc7a3b30478eecd3b7ed7f329 (diff) | |
download | elixir-d199a18075bef37e5184afa17a34c756e4013cdd.tar.gz |
Warn on circular file imports when loading .iex.exs (#9364)
-rw-r--r-- | lib/iex/lib/iex/evaluator.ex | 3 | ||||
-rw-r--r-- | lib/iex/lib/iex/helpers.ex | 11 | ||||
-rw-r--r-- | lib/iex/test/iex/helpers_test.exs | 11 |
3 files changed, 24 insertions, 1 deletions
diff --git a/lib/iex/lib/iex/evaluator.ex b/lib/iex/lib/iex/evaluator.ex index c6415fd31..ff86ed339 100644 --- a/lib/iex/lib/iex/evaluator.ex +++ b/lib/iex/lib/iex/evaluator.ex @@ -186,6 +186,7 @@ defmodule IEx.Evaluator do # Evaluate the contents in the same environment server_loop will run in env = :elixir.env_for_eval(state.env, file: path, line: 1) + Process.put(:iex_imported_paths, MapSet.new([path])) {_result, binding, env, _scope} = :elixir.eval_forms(quoted, state.binding, env) %{state | binding: binding, env: :elixir.env_for_eval(env, file: "iex", line: 1)} catch @@ -193,6 +194,8 @@ defmodule IEx.Evaluator do io_result("Error while evaluating: #{path}") print_error(kind, error, __STACKTRACE__) state + after + Process.delete(:iex_imported_paths) end end diff --git a/lib/iex/lib/iex/helpers.ex b/lib/iex/lib/iex/helpers.ex index 773ea0376..9ca9c0159 100644 --- a/lib/iex/lib/iex/helpers.ex +++ b/lib/iex/lib/iex/helpers.ex @@ -1068,7 +1068,16 @@ defmodule IEx.Helpers do path = Path.expand(path) if not optional? or File.exists?(path) do - path |> File.read!() |> Code.string_to_quoted!(file: path) + if imported_paths = Process.get(:iex_imported_paths) do + if path in imported_paths do + IO.warn("path #{path} was already imported, skipping circular file imports", []) + else + Process.put(:iex_imported_paths, MapSet.put(imported_paths, path)) + path |> File.read!() |> Code.string_to_quoted!(file: path) + end + else + path |> File.read!() |> Code.string_to_quoted!(file: path) + end end end diff --git a/lib/iex/test/iex/helpers_test.exs b/lib/iex/test/iex/helpers_test.exs index dc9821a80..d6e33638b 100644 --- a/lib/iex/test/iex/helpers_test.exs +++ b/lib/iex/test/iex/helpers_test.exs @@ -1000,6 +1000,17 @@ defmodule IEx.HelpersTest do test "does not raise if file is missing and using import_file_if_available" do assert "nil" == capture_iex("import_file_if_available \"nonexistent\"") end + + test "circular imports" do + dot_1 = "import_file \"dot-iex-2\"" + dot_2 = "import_file \"dot-iex-1\"" + + with_file(["dot-iex-1", "dot-iex-2"], [dot_1, dot_2], fn -> + assert capture_io(:stderr, fn -> + assert capture_iex(":ok", [], dot_iex_path: "dot-iex-1") == ":ok" + end) =~ "dot-iex-2 was already imported, skipping circular file imports" + end) + end end describe "import_if_available" do |