diff --git a/lib/next_ls.ex b/lib/next_ls.ex index 7ba9440d..11590ac9 100644 --- a/lib/next_ls.ex +++ b/lib/next_ls.ex @@ -661,6 +661,7 @@ defmodule NextLS do uri: uri, mix_env: lsp.assigns.init_opts.mix_env, mix_target: lsp.assigns.init_opts.mix_target, + elixir_exec: lsp.assigns.init_opts.elixir_exec, on_initialized: fn status -> if status == :ready do Progress.stop(lsp, token, "NextLS runtime for folder #{name} has initialized!") @@ -1117,6 +1118,7 @@ defmodule NextLS do defstruct mix_target: "host", mix_env: "dev", + elixir_exec: nil, experimental: %NextLS.InitOpts.Experimental{}, extensions: %NextLS.InitOpts.Extensions{} @@ -1126,6 +1128,7 @@ defmodule NextLS do schema(__MODULE__, %{ optional(:mix_target) => str(), optional(:mix_env) => str(), + optional(:elixir_exec) => str(), optional(:experimental) => schema(NextLS.InitOpts.Experimental, %{ optional(:completions) => diff --git a/lib/next_ls/runtime.ex b/lib/next_ls/runtime.ex index 303e50bb..8264611d 100644 --- a/lib/next_ls/runtime.ex +++ b/lib/next_ls/runtime.ex @@ -111,7 +111,7 @@ defmodule NextLS.Runtime do new_path = String.replace(path, bindir <> ":", "") with dir when is_list(dir) <- :code.priv_dir(:next_ls), - elixir_exe when is_binary(elixir_exe) <- System.find_executable("elixir") do + elixir_exe when is_binary(elixir_exe) <- use_or_find_elixir_exec(opts) do exe = dir |> Path.join("cmd") @@ -348,4 +348,16 @@ defmodule NextLS.Runtime do true end end + + defp use_or_find_elixir_exec(opts) do + with path when is_binary(path) <- opts[:elixir_exec], + exec = Path.expand(path), + true <- File.exists?(exec), + {_, 0} <- System.cmd(exec, ["--version"]) do + exec + else + _ -> + System.find_executable("elixir") + end + end end diff --git a/test/next_ls/runtime_test.exs b/test/next_ls/runtime_test.exs index 310e6817..e83c18d7 100644 --- a/test/next_ls/runtime_test.exs +++ b/test/next_ls/runtime_test.exs @@ -253,6 +253,37 @@ defmodule NextLs.RuntimeTest do end end + test "supports using custom elixir_exec path", %{logger: logger, cwd: cwd, on_init: on_init} do + start_supervised!({Registry, keys: :duplicate, name: RuntimeTest.Registry}) + tvisor = start_supervised!(Task.Supervisor) + + # Create local Elixir shim + elixir_exec = Path.join(cwd, "elixir") + File.ln_s!(System.find_executable("elixir"), elixir_exec) + assert {_, 0} = System.cmd(elixir_exec, ["--version"]) + + pid = + start_supervised!( + {Runtime, + name: "my_proj", + on_initialized: on_init, + task_supervisor: tvisor, + working_dir: cwd, + uri: "file://#{cwd}", + parent: self(), + logger: logger, + db: :some_db, + mix_env: "dev", + mix_target: "host", + elixir_exec: elixir_exec, + registry: RuntimeTest.Registry} + ) + + Process.link(pid) + + assert_receive :ready + end + defp flush_messages do receive do _ -> flush_messages()