Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mix clean custom command #730

Merged
merged 6 commits into from
Sep 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions apps/language_server/lib/language_server/build.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand All @@ -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
Expand Down Expand Up @@ -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}
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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{}) ::
Expand Down
Original file line number Diff line number Diff line change
@@ -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
5 changes: 5 additions & 0 deletions apps/language_server/test/fixtures/clean/lib/a.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule A do
def fun do
:ok = B.fun()
end
end
5 changes: 5 additions & 0 deletions apps/language_server/test/fixtures/clean/lib/b.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule B do
def fun do
:error
end
end
5 changes: 5 additions & 0 deletions apps/language_server/test/fixtures/clean/lib/c.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule C do
def myfun do
1
end
end
15 changes: 15 additions & 0 deletions apps/language_server/test/fixtures/clean/mix.exs
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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