Skip to content

Commit

Permalink
publish diagnostics for all open files
Browse files Browse the repository at this point in the history
attach document version to diagnostics
without that on restart diagnostics are not cleared as we don't have old_diagnostics

Fixes elixir-lsp/vscode-elixir-ls#389
  • Loading branch information
lukaszsamson committed Oct 20, 2023
1 parent 2cd1172 commit 5ce4c0a
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 25 deletions.
23 changes: 14 additions & 9 deletions apps/language_server/lib/language_server/diagnostics.ex
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,9 @@ defmodule ElixirLS.LanguageServer.Diagnostics do
end)
end

def publish_file_diagnostics(uri, all_diagnostics, source_file) do
diagnostics =
all_diagnostics
|> Enum.filter(&(SourceFile.Path.to_uri(&1.file) == uri))
|> Enum.sort_by(fn %{position: position} -> position end)

def publish_file_diagnostics(uri, uri_diagnostics, source_file, version) do
diagnostics_json =
for diagnostic <- diagnostics do
for diagnostic <- uri_diagnostics do
severity =
case diagnostic.severity do
:error -> 1
Expand All @@ -211,11 +206,21 @@ defmodule ElixirLS.LanguageServer.Diagnostics do
"source" => diagnostic.compiler_name
}
end
|> Enum.sort_by(& &1["range"]["start"])

JsonRpc.notify("textDocument/publishDiagnostics", %{
message = %{
"uri" => uri,
"diagnostics" => diagnostics_json
})
}

message =
if is_integer(version) do
Map.put(message, "version", version)
else
message
end

JsonRpc.notify("textDocument/publishDiagnostics", message)
end

def mixfile_diagnostic({file, line, message}, severity) do
Expand Down
46 changes: 35 additions & 11 deletions apps/language_server/lib/language_server/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1178,17 +1178,41 @@ defmodule ElixirLS.LanguageServer.Server do
end

defp publish_diagnostics(new_diagnostics, old_diagnostics, source_files) do
files =
Enum.uniq(Enum.map(new_diagnostics, & &1.file) ++ Enum.map(old_diagnostics, & &1.file))

for file <- files,
uri = SourceFile.Path.to_uri(file),
do:
Diagnostics.publish_file_diagnostics(
uri,
new_diagnostics,
Map.get_lazy(source_files, uri, fn -> safely_read_file(file) end)
)
# we need to publish diagnostics for all files in new_diagnostics
# to clear diagnostics we need to push empty sets for old_diagnostics
# in case we missed something or restarted and don't have old_diagnostics
# we also push for all open files
uris_from_old_diagnostics = Enum.map(old_diagnostics, &(&1.file |> SourceFile.Path.to_uri()))

new_diagnostics_by_uri =
new_diagnostics
|> Enum.group_by(&(&1.file |> SourceFile.Path.to_uri()))

uris_from_new_diagnostics = Map.keys(new_diagnostics_by_uri)

uris_from_open_files = Map.keys(source_files)

uris_to_publish_diagnostics =
Enum.uniq(uris_from_old_diagnostics ++ uris_from_new_diagnostics ++ uris_from_open_files)

for uri <- uris_to_publish_diagnostics do
uri_diagnostics = Map.get(new_diagnostics_by_uri, uri, [])
# TODO store versions on compile/parse/dialyze?
version =
case source_files[uri] do
nil -> nil
file -> file.version
end

Diagnostics.publish_file_diagnostics(
uri,
uri_diagnostics,
Map.get_lazy(source_files, uri, fn -> safely_read_file(SourceFile.Path.from_uri(uri)) end),
version
)

# TODO dump diagnostics to file
end
end

defp show_version_warnings do
Expand Down
4 changes: 3 additions & 1 deletion apps/language_server/test/dialyzer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,9 @@ defmodule ElixirLS.LanguageServer.DialyzerTest do
assert_receive notification("window/logMessage", %{"message" => "Compile took" <> _}), 5000

# we should not receive Protocol has already been consolidated warnings here
refute_receive notification("textDocument/publishDiagnostics", _), 3000
refute_receive notification("textDocument/publishDiagnostics", %{"diagnostics" => [_ | _]}),
3000

wait_until_compiled(server)
end)
end
Expand Down
8 changes: 4 additions & 4 deletions apps/language_server/test/server_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -494,9 +494,9 @@ defmodule ElixirLS.LanguageServer.ServerTest do
assert %SourceFile{dirty?: false, text: ^code, version: 1} =
Server.get_source_file(state, uri)

refute_receive notification("textDocument/publishDiagnostics", %{
assert_receive notification("textDocument/publishDiagnostics", %{
"uri" => ^uri,
"diagnostics" => _
"diagnostics" => []
}),
1000

Expand Down Expand Up @@ -799,9 +799,9 @@ defmodule ElixirLS.LanguageServer.ServerTest do
fake_initialize(server)
Server.receive_packet(server, did_open(uri, "elixir", 1, code))

refute_receive notification("textDocument/publishDiagnostics", %{
assert_receive notification("textDocument/publishDiagnostics", %{
"uri" => ^uri,
"diagnostics" => _
"diagnostics" => []
}),
1000

Expand Down

0 comments on commit 5ce4c0a

Please sign in to comment.