diff --git a/apps/elixir_ls_debugger/lib/debugger/server.ex b/apps/elixir_ls_debugger/lib/debugger/server.ex index 646ce5329..14b5c400b 100644 --- a/apps/elixir_ls_debugger/lib/debugger/server.ex +++ b/apps/elixir_ls_debugger/lib/debugger/server.ex @@ -401,11 +401,19 @@ defmodule ElixirLS.Debugger.Server do 0 _ -> - Output.debugger_important("Task failed: " <> Exception.format_exit(reason)) + Output.debugger_important("Mix task failed") 1 end + IO.puts( + "Mix task exited with reason\n#{Exception.format_exit(reason)}\nreturning code #{exit_code}" + ) + + Output.debugger_console( + "Mix task exited with reason\n#{Exception.format_exit(reason)}\nreturning code #{exit_code}" + ) + Output.send_event("exited", %{"exitCode" => exit_code}) Output.send_event("terminated", %{"restart" => false}) @@ -577,9 +585,14 @@ defmodule ElixirLS.Debugger.Server do {:DOWN, ^ref, :process, _pid, reason} -> if reason != :normal do - Output.debugger_important("Initialization failed: " <> Exception.format_exit(reason)) + Output.debugger_important("Launch request failed") + + Output.debugger_console( + "Launch request failed with reason\n" <> Exception.format_exit(reason) + ) - Output.send_event("exited", %{"exitCode" => 1}) + exit_code = 1 + Output.send_event("exited", %{"exitCode" => exit_code}) Output.send_event("terminated", %{"restart" => false}) config else diff --git a/apps/elixir_ls_debugger/test/debugger_test.exs b/apps/elixir_ls_debugger/test/debugger_test.exs index 67c0ba09a..7dc9f1e49 100644 --- a/apps/elixir_ls_debugger/test/debugger_test.exs +++ b/apps/elixir_ls_debugger/test/debugger_test.exs @@ -72,6 +72,26 @@ defmodule ElixirLS.Debugger.ServerTest do end) end + test "fails when not supported arguments passed", %{server: server} do + in_fixture(__DIR__, "mix_project", fn -> + Server.receive_packet( + server, + initialize_req(1, %{"clientID" => "some_id", "linesStartAt1" => false}) + ) + + assert_receive( + error_response( + _, + 1, + "initialize", + "invalidRequest", + "0-based lines are not supported", + %{} + ) + ) + end) + end + test "rejects requests when not initialized", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( @@ -372,6 +392,151 @@ defmodule ElixirLS.Debugger.ServerTest do assert_receive(event(_, "terminated", %{"restart" => false})) end) end + + @tag :fixture + test "launch mix task that raises", %{server: server} do + in_fixture(__DIR__, "mix_project", fn -> + Server.receive_packet( + server, + initialize_req(1, %{ + "supportsVariablePaging" => true, + "supportsVariableType" => true + }) + ) + + assert_receive(response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true})) + + Server.receive_packet( + server, + launch_req(2, %{ + "request" => "launch", + "type" => "mix_task", + "noDebug" => true, + "task" => "run", + "taskArgs" => ["-e", "MixProject.Crash.fun_that_raises()"], + "projectDir" => File.cwd!() + }) + ) + + assert_receive(response(_, 2, "launch", %{}), 5000) + assert_receive(event(_, "initialized", %{})) + + Server.receive_packet(server, request(5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone", %{})) + + assert_receive event(_, "output", %{ + "category" => "console", + "output" => + "Mix task exited with reason\nan exception was raised:\n ** (RuntimeError) foo" <> + _ + }), + 3000 + + assert_receive( + event(_, "exited", %{ + "exitCode" => 1 + }), + 3000 + ) + + assert_receive(event(_, "terminated", %{"restart" => false})) + end) + end + + @tag :fixture + test "launch mix task that fails to initialze", %{server: server} do + in_fixture(__DIR__, "mix_project", fn -> + Server.receive_packet( + server, + initialize_req(1, %{ + "supportsVariablePaging" => true, + "supportsVariableType" => true + }) + ) + + assert_receive(response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true})) + + Server.receive_packet( + server, + launch_req(2, %{ + "request" => "launch", + "type" => "mix_task", + "noDebug" => true, + "task" => "ru/n", + "taskArgs" => [], + "projectDir" => File.cwd!() + }) + ) + + assert_receive(response(_, 2, "launch", %{}), 5000) + refute_receive(event(_, "initialized", %{})) + + assert_receive event(_, "output", %{ + "category" => "console", + "output" => + "Launch request failed with reason\nan exception was raised:\n ** (Mix.NoTaskError)" <> + _ + }), + 3000 + + assert_receive( + event(_, "exited", %{ + "exitCode" => 1 + }), + 3000 + ) + + assert_receive(event(_, "terminated", %{"restart" => false})) + end) + end + + @tag :fixture + test "launch invalid mix task", %{server: server} do + in_fixture(__DIR__, "mix_project", fn -> + Server.receive_packet( + server, + initialize_req(1, %{ + "supportsVariablePaging" => true, + "supportsVariableType" => true + }) + ) + + assert_receive(response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true})) + + Server.receive_packet( + server, + launch_req(2, %{ + "request" => "launch", + "type" => "mix_task", + "noDebug" => true, + "task" => "nonexisting", + "taskArgs" => [], + "projectDir" => File.cwd!() + }) + ) + + assert_receive(response(_, 2, "launch", %{}), 5000) + assert_receive(event(_, "initialized", %{})) + + Server.receive_packet(server, request(5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone", %{})) + + assert_receive event(_, "output", %{ + "category" => "console", + "output" => + "Mix task exited with reason\nan exception was raised:\n ** (Mix.NoTaskError) The task \"nonexisting\" could not be found" <> + _ + }), + 3000 + + assert_receive( + event(_, "exited", %{ + "exitCode" => 1 + }), + 3000 + ) + + assert_receive(event(_, "terminated", %{"restart" => false})) end) end diff --git a/apps/elixir_ls_debugger/test/fixtures/mix_project/lib/crash.ex b/apps/elixir_ls_debugger/test/fixtures/mix_project/lib/crash.ex new file mode 100644 index 000000000..54cd2cbd3 --- /dev/null +++ b/apps/elixir_ls_debugger/test/fixtures/mix_project/lib/crash.ex @@ -0,0 +1,5 @@ +defmodule MixProject.Crash do + def fun_that_raises() do + raise "foo" + end +end