summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Mach <wojtekmach@users.noreply.github.com>2019-09-27 17:46:10 +0200
committerFernando Tapia Rico <fertapric@gmail.com>2019-09-27 17:46:10 +0200
commitd199a18075bef37e5184afa17a34c756e4013cdd (patch)
tree7376404071ce67d4ad54ab79959e2f7b07c160fa
parent4253fdaead5f586bc7a3b30478eecd3b7ed7f329 (diff)
downloadelixir-d199a18075bef37e5184afa17a34c756e4013cdd.tar.gz
Warn on circular file imports when loading .iex.exs (#9364)
-rw-r--r--lib/iex/lib/iex/evaluator.ex3
-rw-r--r--lib/iex/lib/iex/helpers.ex11
-rw-r--r--lib/iex/test/iex/helpers_test.exs11
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