Skip to content

Commit d3ffbaf

Browse files
committed
fix: gracefully handle uninitialized runtime
1 parent f28af33 commit d3ffbaf

File tree

4 files changed

+73
-27
lines changed

4 files changed

+73
-27
lines changed

Diff for: lib/next_ls.ex

+26-18
Original file line numberDiff line numberDiff line change
@@ -96,26 +96,34 @@ defmodule NextLS do
9696

9797
def handle_request(%TextDocumentFormatting{params: %{text_document: %{uri: uri}}}, lsp) do
9898
document = lsp.assigns.documents[uri]
99-
100-
{formatter, _} = Runtime.call(lsp.assigns.runtime, {Mix.Tasks.Format, :formatter_for_file, [".formatter.exs"]})
101-
102-
new_document =
103-
Runtime.call(lsp.assigns.runtime, {Kernel, :apply, [formatter, [Enum.join(document, "\n")]]})
104-
|> IO.iodata_to_binary()
105-
106-
{:reply,
107-
[
108-
%TextEdit{
109-
new_text: new_document,
110-
range: %Range{
111-
start: %Position{line: 0, character: 0},
112-
end: %Position{
113-
line: length(document),
114-
character: document |> List.last() |> String.length() |> Kernel.-(1) |> max(0)
99+
runtime = lsp.assigns.runtime
100+
101+
with {:ok, {formatter, _}} <- Runtime.call(runtime, {Mix.Tasks.Format, :formatter_for_file, [".formatter.exs"]}),
102+
{:ok, response} <- Runtime.call(runtime, {Kernel, :apply, [formatter, [Enum.join(document, "\n")]]}) do
103+
{:reply,
104+
[
105+
%TextEdit{
106+
new_text: IO.iodata_to_binary(response),
107+
range: %Range{
108+
start: %Position{line: 0, character: 0},
109+
end: %Position{
110+
line: length(document),
111+
character: document |> List.last() |> String.length() |> Kernel.-(1) |> max(0)
112+
}
115113
}
116114
}
117-
}
118-
], lsp}
115+
], lsp}
116+
else
117+
{:error, :not_ready} ->
118+
GenLSP.notify(lsp, %GenLSP.Notifications.WindowShowMessage{
119+
params: %GenLSP.Structures.ShowMessageParams{
120+
type: GenLSP.Enumerations.MessageType.info(),
121+
message: "The NextLS runtime is still initializing!"
122+
}
123+
})
124+
125+
{:reply, nil, lsp}
126+
end
119127
end
120128

121129
def handle_request(%Shutdown{}, lsp) do

Diff for: lib/next_ls/runtime.ex

+5-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,11 @@ defmodule NextLS.Runtime do
107107

108108
def handle_call({:call, {m, f, a}}, _from, %{node: node} = state) do
109109
reply = :rpc.call(node, m, f, a)
110-
{:reply, reply, state}
110+
{:reply, {:ok, reply}, state}
111+
end
112+
113+
def handle_call({:call, _}, _from, state) do
114+
{:reply, {:error, :not_ready}, state}
111115
end
112116

113117
def handle_call(:compile, _, %{node: node} = state) do

Diff for: test/next_ls/runtime_test.exs

+20
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ defmodule NextLs.RuntimeTest do
2828
[logger: logger, cwd: Path.absname(tmp_dir)]
2929
end
3030

31+
test "returns the response in an ok tuple", %{logger: logger, cwd: cwd} do
32+
start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry})
33+
pid = start_supervised!({Runtime, working_dir: cwd, parent: logger, extension_registry: RuntimeTestRegistry})
34+
35+
Process.link(pid)
36+
37+
assert wait_for_ready(pid)
38+
39+
assert {:ok, "\"hi\""} = Runtime.call(pid, {Kernel, :inspect, ["hi"]})
40+
end
41+
42+
test "call returns an error when the runtime is node ready", %{logger: logger, cwd: cwd} do
43+
start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry})
44+
pid = start_supervised!({Runtime, working_dir: cwd, parent: logger, extension_registry: RuntimeTestRegistry})
45+
46+
Process.link(pid)
47+
48+
assert {:error, :not_ready} = Runtime.call(pid, {IO, :puts, ["hi"]})
49+
end
50+
3151
test "compiles the code and returns diagnostics", %{logger: logger, cwd: cwd} do
3252
start_supervised!({Registry, keys: :unique, name: RuntimeTestRegistry})
3353

Diff for: test/next_ls_test.exs

+22-8
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,6 @@ defmodule NextLSTest do
190190
params: %{}
191191
})
192192

193-
assert_notification "window/logMessage",
194-
%{"message" => "[NextLS] Runtime ready..."}
195-
196193
notify client, %{
197194
method: "textDocument/didOpen",
198195
jsonrpc: "2.0",
@@ -229,6 +226,26 @@ defmodule NextLSTest do
229226
}
230227
}
231228

229+
assert_result 2, nil
230+
231+
assert_notification "window/logMessage",
232+
%{"message" => "[NextLS] Runtime ready..."}
233+
234+
request client, %{
235+
method: "textDocument/formatting",
236+
id: 3,
237+
jsonrpc: "2.0",
238+
params: %{
239+
textDocument: %{
240+
uri: "file://lib/foo/bar.ex"
241+
},
242+
options: %{
243+
insertSpaces: true,
244+
tabSize: 2
245+
}
246+
}
247+
}
248+
232249
new_text = """
233250
defmodule Foo.Bar do
234251
def run() do
@@ -238,14 +255,11 @@ defmodule NextLSTest do
238255
"""
239256

240257
assert_result(
241-
2,
258+
3,
242259
[
243260
%{
244261
"newText" => ^new_text,
245-
"range" => %{
246-
"start" => %{"character" => 0, "line" => 0},
247-
"end" => %{"character" => 0, "line" => 8}
248-
}
262+
"range" => %{"start" => %{"character" => 0, "line" => 0}, "end" => %{"character" => 0, "line" => 8}}
249263
}
250264
]
251265
)

0 commit comments

Comments
 (0)