Skip to content

Commit

Permalink
fix: gracefully handle uninitialized runtime (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
mhanberg committed Jun 23, 2023
1 parent f28af33 commit 9975501
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 27 deletions.
44 changes: 26 additions & 18 deletions lib/next_ls.ex
Original file line number Diff line number Diff line change
Expand Up @@ -96,26 +96,34 @@ defmodule NextLS do

def handle_request(%TextDocumentFormatting{params: %{text_document: %{uri: uri}}}, lsp) do
document = lsp.assigns.documents[uri]

{formatter, _} = Runtime.call(lsp.assigns.runtime, {Mix.Tasks.Format, :formatter_for_file, [".formatter.exs"]})

new_document =
Runtime.call(lsp.assigns.runtime, {Kernel, :apply, [formatter, [Enum.join(document, "\n")]]})
|> IO.iodata_to_binary()

{:reply,
[
%TextEdit{
new_text: new_document,
range: %Range{
start: %Position{line: 0, character: 0},
end: %Position{
line: length(document),
character: document |> List.last() |> String.length() |> Kernel.-(1) |> max(0)
runtime = lsp.assigns.runtime

with {:ok, {formatter, _}} <- Runtime.call(runtime, {Mix.Tasks.Format, :formatter_for_file, [".formatter.exs"]}),
{:ok, response} <- Runtime.call(runtime, {Kernel, :apply, [formatter, [Enum.join(document, "\n")]]}) do
{:reply,
[
%TextEdit{
new_text: IO.iodata_to_binary(response),
range: %Range{
start: %Position{line: 0, character: 0},
end: %Position{
line: length(document),
character: document |> List.last() |> String.length() |> Kernel.-(1) |> max(0)
}
}
}
}
], lsp}
], lsp}
else
{:error, :not_ready} ->
GenLSP.notify(lsp, %GenLSP.Notifications.WindowShowMessage{
params: %GenLSP.Structures.ShowMessageParams{
type: GenLSP.Enumerations.MessageType.info(),
message: "The NextLS runtime is still initializing!"
}
})

{:reply, nil, lsp}
end
end

def handle_request(%Shutdown{}, lsp) do
Expand Down
6 changes: 5 additions & 1 deletion lib/next_ls/runtime.ex
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,11 @@ defmodule NextLS.Runtime do

def handle_call({:call, {m, f, a}}, _from, %{node: node} = state) do
reply = :rpc.call(node, m, f, a)
{:reply, reply, state}
{:reply, {:ok, reply}, state}
end

def handle_call({:call, _}, _from, state) do
{:reply, {:error, :not_ready}, state}
end

def handle_call(:compile, _, %{node: node} = state) do
Expand Down
20 changes: 20 additions & 0 deletions test/next_ls/runtime_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@ defmodule NextLs.RuntimeTest do
[logger: logger, cwd: Path.absname(tmp_dir)]
end

test "returns the response in an ok tuple", %{logger: logger, cwd: cwd} do
start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry})
pid = start_supervised!({Runtime, working_dir: cwd, parent: logger, extension_registry: RuntimeTestRegistry})

Process.link(pid)

assert wait_for_ready(pid)

assert {:ok, "\"hi\""} = Runtime.call(pid, {Kernel, :inspect, ["hi"]})
end

test "call returns an error when the runtime is node ready", %{logger: logger, cwd: cwd} do
start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry})
pid = start_supervised!({Runtime, working_dir: cwd, parent: logger, extension_registry: RuntimeTestRegistry})

Process.link(pid)

assert {:error, :not_ready} = Runtime.call(pid, {IO, :puts, ["hi"]})
end

test "compiles the code and returns diagnostics", %{logger: logger, cwd: cwd} do
start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry})

Expand Down
30 changes: 22 additions & 8 deletions test/next_ls_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,6 @@ defmodule NextLSTest do
params: %{}
})

assert_notification "window/logMessage",
%{"message" => "[NextLS] Runtime ready..."}

notify client, %{
method: "textDocument/didOpen",
jsonrpc: "2.0",
Expand Down Expand Up @@ -229,6 +226,26 @@ defmodule NextLSTest do
}
}

assert_result 2, nil

assert_notification "window/logMessage",
%{"message" => "[NextLS] Runtime ready..."}

request client, %{
method: "textDocument/formatting",
id: 3,
jsonrpc: "2.0",
params: %{
textDocument: %{
uri: "file://lib/foo/bar.ex"
},
options: %{
insertSpaces: true,
tabSize: 2
}
}
}

new_text = """
defmodule Foo.Bar do
def run() do
Expand All @@ -238,14 +255,11 @@ defmodule NextLSTest do
"""

assert_result(
2,
3,
[
%{
"newText" => ^new_text,
"range" => %{
"start" => %{"character" => 0, "line" => 0},
"end" => %{"character" => 0, "line" => 8}
}
"range" => %{"start" => %{"character" => 0, "line" => 0}, "end" => %{"character" => 0, "line" => 8}}
}
]
)
Expand Down

0 comments on commit 9975501

Please sign in to comment.