diff --git a/lib/livebook/intellisense.ex b/lib/livebook/intellisense.ex index af364c47a..6768fbfd3 100644 --- a/lib/livebook/intellisense.ex +++ b/lib/livebook/intellisense.ex @@ -24,9 +24,38 @@ defmodule Livebook.Intellisense do map_binding: (Code.binding() -> any()) } + @doc """ + Adjusts the system for more accurate intellisense. + """ + @spec load() :: :ok + def load() do + # Completion looks for modules in loaded applications, so we ensure + # that the most relevant built-in applications are loaded + apps = [:erts, :crypto, :inets, :public_key, :runtime_tools, :ex_unit, :iex] + + for app <- apps do + Application.load(app) + end + + :ok + end + + @doc """ + Clears all cache stored by the intellisense modules. + """ + @spec clear_cache() :: :ok + def clear_cache() do + for node <- Node.list() do + clear_cache(node) + end + + :ok + end + @doc """ Clear any cache stored related to the given node. """ + @spec clear_cache(node()) :: :ok def clear_cache(node) do IdentifierMatcher.clear_all_loaded(node) end diff --git a/lib/livebook/runtime/erl_dist/node_manager.ex b/lib/livebook/runtime/erl_dist/node_manager.ex index 110db1009..59470596c 100644 --- a/lib/livebook/runtime/erl_dist/node_manager.ex +++ b/lib/livebook/runtime/erl_dist/node_manager.ex @@ -146,6 +146,10 @@ defmodule Livebook.Runtime.ErlDist.NodeManager do Code.prepend_path(ebin_path) end + Livebook.Intellisense.load() + + :net_kernel.monitor_nodes(true, node_type: :all) + {:ok, %{ unload_modules_on_termination: unload_modules_on_termination, @@ -163,6 +167,8 @@ defmodule Livebook.Runtime.ErlDist.NodeManager do @impl true def terminate(_reason, state) do + Livebook.Intellisense.clear_cache() + Code.compiler_options(ignore_module_conflict: state.initial_ignore_module_conflict) if ansi_syntax_colors = state.initial_ansi_syntax_colors do @@ -238,6 +244,11 @@ defmodule Livebook.Runtime.ErlDist.NodeManager do {:noreply, state} end + def handle_info({:nodedown, node, _metadata}, state) do + Livebook.Intellisense.clear_cache(node) + {:noreply, state} + end + def handle_info(_message, state), do: {:noreply, state} defp make_tmp_dir() do diff --git a/lib/livebook/runtime/erl_dist/runtime_server.ex b/lib/livebook/runtime/erl_dist/runtime_server.ex index 4bef9e64a..80f2ac203 100644 --- a/lib/livebook/runtime/erl_dist/runtime_server.ex +++ b/lib/livebook/runtime/erl_dist/runtime_server.ex @@ -335,7 +335,7 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServer do @impl true def init(opts) do Process.send_after(self(), :check_owner, @await_owner_timeout) - :net_kernel.monitor_nodes(true, node_type: :all) + schedule_memory_usage_report() {:ok, evaluator_supervisor} = ErlDist.EvaluatorSupervisor.start_link() @@ -383,11 +383,6 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServer do end end - def handle_info({:nodedown, node, _metadata}, state) do - Livebook.Intellisense.clear_cache(node) - {:noreply, state} - end - def handle_info({:DOWN, _, :process, owner, _}, %{owner: owner} = state) do {:stop, :shutdown, state} end diff --git a/test/test_helper.exs b/test/test_helper.exs index ef264e54b..29f160b5b 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -6,9 +6,6 @@ Livebook.Runtime.ErlDist.NodeManager.start( unload_modules_on_termination: false ) -# We load erts so we can access its modules for completion. -Application.load(:erts) - # Use the embedded runtime in tests by default, so they are cheaper # to run. Other runtimes can be tested by setting them explicitly Application.put_env(:livebook, :default_runtime, Livebook.Runtime.Embedded.new())