From eb9910873e6ba65d14963fe9706e7bf7c5cdc882 Mon Sep 17 00:00:00 2001 From: Jon Carstens Date: Mon, 15 Jun 2020 08:19:00 -0600 Subject: [PATCH] Support setting MIX_TARGET For https://github.com/elixir-lsp/elixir-ls/issues/248 This allows you to set MIX_TARGET in a config and have it used in Elixir versions >= 1.8 This is most often used with Nerves and removes a lot of compilation errors in repos relying on a target to be set --- .../lib/language_server/build.ex | 10 +++++- .../lib/language_server/server.ex | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/apps/language_server/lib/language_server/build.ex b/apps/language_server/lib/language_server/build.ex index 267fc3a87..5255c8606 100644 --- a/apps/language_server/lib/language_server/build.ex +++ b/apps/language_server/lib/language_server/build.ex @@ -10,7 +10,15 @@ defmodule ElixirLS.LanguageServer.Build do with_build_lock(fn -> {us, _} = :timer.tc(fn -> - IO.puts("Compiling with Mix env #{Mix.env()}") + IO.puts("MIX_ENV: #{Mix.env()}") + + if function_exported?(Mix, :target, 0) do + # Even though we know we have the function here, + # Compilation will fail calling Mix.target/0 directly + # since Elixir 1.7 is used to compile - So we get around + # that with apply/3 + IO.puts("MIX_TARGET: #{apply(Mix, :target, [])}") + end prev_deps = cached_deps() :ok = Mix.Project.clear_deps_cache() diff --git a/apps/language_server/lib/language_server/server.ex b/apps/language_server/lib/language_server/server.ex index b6d93f7bc..a167503e2 100644 --- a/apps/language_server/lib/language_server/server.ex +++ b/apps/language_server/lib/language_server/server.ex @@ -748,11 +748,13 @@ defmodule ElixirLS.LanguageServer.Server do Dialyzer.check_support() == :ok && Map.get(settings, "dialyzerEnabled", true) mix_env = Map.get(settings, "mixEnv", "test") + mix_target = Map.get(settings, "mixTarget") project_dir = Map.get(settings, "projectDir") state = state |> set_mix_env(mix_env) + |> maybe_set_mix_target(mix_target) |> set_project_dir(project_dir) |> set_dialyzer_enabled(enable_dialyzer) @@ -787,6 +789,38 @@ defmodule ElixirLS.LanguageServer.Server do state end + defp maybe_set_mix_target(state, nil), do: state + + defp maybe_set_mix_target(state, target) do + if Version.match?(System.version(), ">= 1.8.0") do + set_mix_target(state, target) + else + JsonRpc.show_message( + :warning, + "MIX_TARGET was set, but it requires Elixir >= 1.8.0. This setting will be ignored" + ) + + state + end + end + + defp set_mix_target(state, target) do + target = target || "host" + + prev_target = state.settings["mixTarget"] + + if is_nil(prev_target) or target == prev_target do + # We've already checked for Elixir >= 1.8.0 by this point + # but compilation will fail if we just call Mix.target/0 + # so we get around that via apply/3 + apply(Mix, :target, [String.to_atom(target)]) + else + JsonRpc.show_message(:warning, "You must restart ElixirLS after changing Mix target") + end + + state + end + defp set_project_dir(%{project_dir: prev_project_dir, root_uri: root_uri} = state, project_dir) when is_binary(root_uri) do root_dir = SourceFile.path_from_uri(root_uri)