From c3b73d82e91a591544f67a3dd6c880cc7aa40c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Samson?= Date: Mon, 19 Sep 2022 08:06:59 +0200 Subject: [PATCH] Add mix clean custom command (#730) * rename compile * add clean * add mix clean as a custom command * add test * fix tests * fix tests --- .../lib/language_server/build.ex | 32 ++++++++++++- .../providers/execute_command.ex | 3 +- .../providers/execute_command/mix_clean.ex | 11 +++++ .../test/fixtures/clean/lib/a.ex | 5 ++ .../test/fixtures/clean/lib/b.ex | 5 ++ .../test/fixtures/clean/lib/c.ex | 5 ++ .../test/fixtures/clean/mix.exs | 15 ++++++ .../execute_command/mix_clean_test.exs | 47 +++++++++++++++++++ 8 files changed, 120 insertions(+), 3 deletions(-) create mode 100644 apps/language_server/lib/language_server/providers/execute_command/mix_clean.ex create mode 100644 apps/language_server/test/fixtures/clean/lib/a.ex create mode 100644 apps/language_server/test/fixtures/clean/lib/b.ex create mode 100644 apps/language_server/test/fixtures/clean/lib/c.ex create mode 100644 apps/language_server/test/fixtures/clean/mix.exs create mode 100644 apps/language_server/test/providers/execute_command/mix_clean_test.exs diff --git a/apps/language_server/lib/language_server/build.ex b/apps/language_server/lib/language_server/build.ex index 4dec17f05..b400019f2 100644 --- a/apps/language_server/lib/language_server/build.ex +++ b/apps/language_server/lib/language_server/build.ex @@ -27,7 +27,7 @@ defmodule ElixirLS.LanguageServer.Build do # if we won't do it elixir >= 1.11 warns that protocols have already been consolidated purge_consolidated_protocols() - {status, diagnostics} = compile() + {status, diagnostics} = run_mix_compile() diagnostics = Diagnostics.normalize(diagnostics, root_path) Server.build_finished(parent, {status, mixfile_diagnostics ++ diagnostics}) @@ -46,6 +46,13 @@ defmodule ElixirLS.LanguageServer.Build do end end + def clean(clean_deps? \\ false) do + with_build_lock(fn -> + Mix.Task.clear() + run_mix_clean(clean_deps?) + end) + end + def with_build_lock(func) do :global.trans({__MODULE__, self()}, func) end @@ -104,7 +111,8 @@ defmodule ElixirLS.LanguageServer.Build do end end - defp compile do + defp run_mix_compile do + # TODO consider adding --no-compile case Mix.Task.run("compile", ["--return-errors", "--ignore-module-conflict"]) do {status, diagnostics} when status in [:ok, :error, :noop] and is_list(diagnostics) -> {status, diagnostics} @@ -117,6 +125,26 @@ defmodule ElixirLS.LanguageServer.Build do end end + defp run_mix_clean(clean_deps?) do + opts = [] + + opts = + if clean_deps? do + opts ++ ["--deps"] + else + opts + end + + results = Mix.Task.run("clean", opts) |> List.wrap() + + if Enum.all?(results, &match?(:ok, &1)) do + :ok + else + JsonRpc.log_message(:error, "mix clean returned #{inspect(results)}") + {:error, :clean_failed} + end + end + defp purge_consolidated_protocols do config = Mix.Project.config() path = Mix.Project.consolidation_path(config) diff --git a/apps/language_server/lib/language_server/providers/execute_command.ex b/apps/language_server/lib/language_server/providers/execute_command.ex index 63b9fdc27..427521244 100644 --- a/apps/language_server/lib/language_server/providers/execute_command.ex +++ b/apps/language_server/lib/language_server/providers/execute_command.ex @@ -9,7 +9,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand do "spec" => ExecuteCommand.ApplySpec, "expandMacro" => ExecuteCommand.ExpandMacro, "manipulatePipes" => ExecuteCommand.ManipulatePipes, - "restart" => ExecuteCommand.Restart + "restart" => ExecuteCommand.Restart, + "mixClean" => ExecuteCommand.MixClean } @callback execute([any], %ElixirLS.LanguageServer.Server{}) :: diff --git a/apps/language_server/lib/language_server/providers/execute_command/mix_clean.ex b/apps/language_server/lib/language_server/providers/execute_command/mix_clean.ex new file mode 100644 index 000000000..4edaa4022 --- /dev/null +++ b/apps/language_server/lib/language_server/providers/execute_command/mix_clean.ex @@ -0,0 +1,11 @@ +defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.MixClean do + @behaviour ElixirLS.LanguageServer.Providers.ExecuteCommand + + @impl ElixirLS.LanguageServer.Providers.ExecuteCommand + def execute([clean_deps?], _state) do + case ElixirLS.LanguageServer.Build.clean(clean_deps?) do + :ok -> {:ok, %{}} + {:error, reason} -> {:error, :server_error, inspect(reason)} + end + end +end diff --git a/apps/language_server/test/fixtures/clean/lib/a.ex b/apps/language_server/test/fixtures/clean/lib/a.ex new file mode 100644 index 000000000..ec7cb179f --- /dev/null +++ b/apps/language_server/test/fixtures/clean/lib/a.ex @@ -0,0 +1,5 @@ +defmodule A do + def fun do + :ok = B.fun() + end +end diff --git a/apps/language_server/test/fixtures/clean/lib/b.ex b/apps/language_server/test/fixtures/clean/lib/b.ex new file mode 100644 index 000000000..b7ce208dc --- /dev/null +++ b/apps/language_server/test/fixtures/clean/lib/b.ex @@ -0,0 +1,5 @@ +defmodule B do + def fun do + :error + end +end diff --git a/apps/language_server/test/fixtures/clean/lib/c.ex b/apps/language_server/test/fixtures/clean/lib/c.ex new file mode 100644 index 000000000..3cce833b8 --- /dev/null +++ b/apps/language_server/test/fixtures/clean/lib/c.ex @@ -0,0 +1,5 @@ +defmodule C do + def myfun do + 1 + end +end diff --git a/apps/language_server/test/fixtures/clean/mix.exs b/apps/language_server/test/fixtures/clean/mix.exs new file mode 100644 index 000000000..c8b5fc4dc --- /dev/null +++ b/apps/language_server/test/fixtures/clean/mix.exs @@ -0,0 +1,15 @@ +defmodule ElixirLS.LanguageServer.Fixtures.Clean.Mixfile do + use Mix.Project + + def project do + [app: :els_clean_test, version: "0.1.0"] + end + + # Configuration for the OTP application + # + # Type "mix help compile.app" for more information + def application do + # Specify extra applications you'll use from Erlang/Elixir + [] + end +end diff --git a/apps/language_server/test/providers/execute_command/mix_clean_test.exs b/apps/language_server/test/providers/execute_command/mix_clean_test.exs new file mode 100644 index 000000000..f9e55464d --- /dev/null +++ b/apps/language_server/test/providers/execute_command/mix_clean_test.exs @@ -0,0 +1,47 @@ +defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.MixCleanTest do + alias ElixirLS.LanguageServer.{Server, Protocol, SourceFile} + use ElixirLS.Utils.MixTest.Case, async: false + use Protocol + + setup do + server = ElixirLS.LanguageServer.Test.ServerTestHelpers.start_server() + + {:ok, %{server: server}} + end + + @tag fixture: true + test "mix clean", %{server: server} do + in_fixture(Path.join(__DIR__, "../.."), "clean", fn -> + root_uri = SourceFile.path_to_uri(File.cwd!()) + Server.receive_packet(server, initialize_req(1, root_uri, %{})) + + Server.receive_packet( + server, + did_change_configuration(%{ + "elixirLS" => %{"dialyzerEnabled" => false} + }) + ) + + assert_receive %{ + "method" => "window/logMessage", + "params" => %{"message" => "Compile took" <> _} + }, + 20000 + + path = ".elixir_ls/build/test/lib/els_clean_test/ebin/Elixir.A.beam" + assert File.exists?(path) + + server_instance_id = :sys.get_state(server).server_instance_id + + Server.receive_packet( + server, + execute_command_req(4, "mixClean:#{server_instance_id}", [false]) + ) + + res = assert_receive(%{"id" => 4}, 5000) + assert res["result"] == %{} + + refute File.exists?(path) + end) + end +end