Skip to content

Commit 5ce4c0a

Browse files
committed
publish diagnostics for all open files
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
1 parent 2cd1172 commit 5ce4c0a

File tree

4 files changed

+56
-25
lines changed

4 files changed

+56
-25
lines changed

apps/language_server/lib/language_server/diagnostics.ex

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,9 @@ defmodule ElixirLS.LanguageServer.Diagnostics do
182182
end)
183183
end
184184

185-
def publish_file_diagnostics(uri, all_diagnostics, source_file) do
186-
diagnostics =
187-
all_diagnostics
188-
|> Enum.filter(&(SourceFile.Path.to_uri(&1.file) == uri))
189-
|> Enum.sort_by(fn %{position: position} -> position end)
190-
185+
def publish_file_diagnostics(uri, uri_diagnostics, source_file, version) do
191186
diagnostics_json =
192-
for diagnostic <- diagnostics do
187+
for diagnostic <- uri_diagnostics do
193188
severity =
194189
case diagnostic.severity do
195190
:error -> 1
@@ -211,11 +206,21 @@ defmodule ElixirLS.LanguageServer.Diagnostics do
211206
"source" => diagnostic.compiler_name
212207
}
213208
end
209+
|> Enum.sort_by(& &1["range"]["start"])
214210

215-
JsonRpc.notify("textDocument/publishDiagnostics", %{
211+
message = %{
216212
"uri" => uri,
217213
"diagnostics" => diagnostics_json
218-
})
214+
}
215+
216+
message =
217+
if is_integer(version) do
218+
Map.put(message, "version", version)
219+
else
220+
message
221+
end
222+
223+
JsonRpc.notify("textDocument/publishDiagnostics", message)
219224
end
220225

221226
def mixfile_diagnostic({file, line, message}, severity) do

apps/language_server/lib/language_server/server.ex

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,17 +1178,41 @@ defmodule ElixirLS.LanguageServer.Server do
11781178
end
11791179

11801180
defp publish_diagnostics(new_diagnostics, old_diagnostics, source_files) do
1181-
files =
1182-
Enum.uniq(Enum.map(new_diagnostics, & &1.file) ++ Enum.map(old_diagnostics, & &1.file))
1183-
1184-
for file <- files,
1185-
uri = SourceFile.Path.to_uri(file),
1186-
do:
1187-
Diagnostics.publish_file_diagnostics(
1188-
uri,
1189-
new_diagnostics,
1190-
Map.get_lazy(source_files, uri, fn -> safely_read_file(file) end)
1191-
)
1181+
# we need to publish diagnostics for all files in new_diagnostics
1182+
# to clear diagnostics we need to push empty sets for old_diagnostics
1183+
# in case we missed something or restarted and don't have old_diagnostics
1184+
# we also push for all open files
1185+
uris_from_old_diagnostics = Enum.map(old_diagnostics, &(&1.file |> SourceFile.Path.to_uri()))
1186+
1187+
new_diagnostics_by_uri =
1188+
new_diagnostics
1189+
|> Enum.group_by(&(&1.file |> SourceFile.Path.to_uri()))
1190+
1191+
uris_from_new_diagnostics = Map.keys(new_diagnostics_by_uri)
1192+
1193+
uris_from_open_files = Map.keys(source_files)
1194+
1195+
uris_to_publish_diagnostics =
1196+
Enum.uniq(uris_from_old_diagnostics ++ uris_from_new_diagnostics ++ uris_from_open_files)
1197+
1198+
for uri <- uris_to_publish_diagnostics do
1199+
uri_diagnostics = Map.get(new_diagnostics_by_uri, uri, [])
1200+
# TODO store versions on compile/parse/dialyze?
1201+
version =
1202+
case source_files[uri] do
1203+
nil -> nil
1204+
file -> file.version
1205+
end
1206+
1207+
Diagnostics.publish_file_diagnostics(
1208+
uri,
1209+
uri_diagnostics,
1210+
Map.get_lazy(source_files, uri, fn -> safely_read_file(SourceFile.Path.from_uri(uri)) end),
1211+
version
1212+
)
1213+
1214+
# TODO dump diagnostics to file
1215+
end
11921216
end
11931217

11941218
defp show_version_warnings do

apps/language_server/test/dialyzer_test.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,9 @@ defmodule ElixirLS.LanguageServer.DialyzerTest do
398398
assert_receive notification("window/logMessage", %{"message" => "Compile took" <> _}), 5000
399399

400400
# we should not receive Protocol has already been consolidated warnings here
401-
refute_receive notification("textDocument/publishDiagnostics", _), 3000
401+
refute_receive notification("textDocument/publishDiagnostics", %{"diagnostics" => [_ | _]}),
402+
3000
403+
402404
wait_until_compiled(server)
403405
end)
404406
end

apps/language_server/test/server_test.exs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,9 @@ defmodule ElixirLS.LanguageServer.ServerTest do
494494
assert %SourceFile{dirty?: false, text: ^code, version: 1} =
495495
Server.get_source_file(state, uri)
496496

497-
refute_receive notification("textDocument/publishDiagnostics", %{
497+
assert_receive notification("textDocument/publishDiagnostics", %{
498498
"uri" => ^uri,
499-
"diagnostics" => _
499+
"diagnostics" => []
500500
}),
501501
1000
502502

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

802-
refute_receive notification("textDocument/publishDiagnostics", %{
802+
assert_receive notification("textDocument/publishDiagnostics", %{
803803
"uri" => ^uri,
804-
"diagnostics" => _
804+
"diagnostics" => []
805805
}),
806806
1000
807807

0 commit comments

Comments
 (0)