Skip to content

Commit 1533d0a

Browse files
authored
Fix exception when processing a textDocument/didChange notification (#178)
* Fix exception when processing a textDocument/didChange notification If there is a client bug (the client did not notify the server that it was opening a file) or the server doesn't know about the file because it recently restarted then do not try to update a non-existant source file in memory. * Add a warning on the unexpected case
1 parent 24a3f50 commit 1533d0a

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

apps/language_server/lib/language_server/server.ex

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,22 @@ defmodule ElixirLS.LanguageServer.Server do
274274
end
275275

276276
defp handle_notification(did_change(uri, version, content_changes), state) do
277-
update_in(state.source_files[uri], fn source_file ->
278-
source_file = %{source_file | version: version, dirty?: true}
279-
SourceFile.apply_content_changes(source_file, content_changes)
277+
update_in(state.source_files[uri], fn
278+
nil ->
279+
# The source file was not marked as open either due to a bug in the
280+
# client or a restart of the server. So just ignore the message and do
281+
# not update the state
282+
IO.warn(
283+
"Received textDocument/didChange for file that is not open. Received uri: #{
284+
inspect(uri)
285+
}"
286+
)
287+
288+
nil
289+
290+
source_file ->
291+
source_file = %{source_file | version: version, dirty?: true}
292+
SourceFile.apply_content_changes(source_file, content_changes)
280293
end)
281294
end
282295

apps/language_server/test/server_test.exs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,28 @@ defmodule ElixirLS.LanguageServer.ServerTest do
2828
{:ok, %{server: server}}
2929
end
3030

31+
test "textDocument/didChange when the client hasn't claimed ownership with textDocument/didOpen",
32+
%{server: server} do
33+
uri = "file:///file.ex"
34+
35+
content_changes = [
36+
%{
37+
"range" => %{
38+
"end" => %{"character" => 2, "line" => 1},
39+
"start" => %{"character" => 0, "line" => 2}
40+
},
41+
"rangeLength" => 1,
42+
"text" => ""
43+
}
44+
]
45+
46+
version = 2
47+
Server.receive_packet(server, did_change(uri, version, content_changes))
48+
49+
# Wait for the server to process the message and ensure that there is no exception
50+
_ = :sys.get_state(server)
51+
end
52+
3153
test "hover", %{server: server} do
3254
uri = "file:///file.ex"
3355
code = ~S(

0 commit comments

Comments
 (0)