Skip to content

Commit

Permalink
try to get line from stacktrace if position unknown
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszsamson committed Dec 21, 2023
1 parent be46796 commit cb23ee3
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 25 deletions.
87 changes: 63 additions & 24 deletions apps/language_server/lib/language_server/diagnostics.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,12 @@ defmodule ElixirLS.LanguageServer.Diagnostics do
end

{file, position} =
case diagnostic.file do
nil ->
if candidate =
get_file_position_from_stacktrace(Map.fetch!(diagnostic, :stacktrace), root_path) do
candidate
else
{mixfile, 0}
end

file ->
{file, diagnostic.position}
end
get_file_and_position_with_stacktrace_fallback(
{diagnostic.file, diagnostic.position},
Map.fetch!(diagnostic, :stacktrace),
root_path,
mixfile
)

%__MODULE__{normalized | message: message, file: file, position: position}
else
Expand Down Expand Up @@ -242,17 +236,12 @@ defmodule ElixirLS.LanguageServer.Diagnostics do
root_path
) do
{file, position} =
case file do
nil ->
if candidate = get_file_position_from_stacktrace(stacktrace, root_path) do
candidate
else
{fallback_file, 0}
end

file ->
{file, position}
end
get_file_and_position_with_stacktrace_fallback(
{file, position},
stacktrace,
root_path,
fallback_file
)

%__MODULE__{
compiler_name: "Elixir",
Expand All @@ -274,17 +263,21 @@ defmodule ElixirLS.LanguageServer.Diagnostics do

message =
if position do
# NOTICE get_line_span returns nil position on failure
# known and expected errors have defined position
Exception.format_banner(kind, payload)
else
Exception.format(kind, payload, stacktrace)
end

# try to get position from first matching stacktrace for that file
position = position || get_position_from_stacktrace(stacktrace, file, project_dir)

%__MODULE__{
compiler_name: "Elixir",
stacktrace: stacktrace,
file: file,
position: position || 0,
position: position,
span: span,
message: message,
severity: :error,
Expand Down Expand Up @@ -717,4 +710,50 @@ defmodule ElixirLS.LanguageServer.Diagnostics do
end
end)
end

defp get_position_from_stacktrace(_stacktrace, _file, :no_stacktrace), do: 0

defp get_position_from_stacktrace(stacktrace, file, project_dir) do
Enum.find_value(stacktrace, 0, fn {_, _, _, info} ->
info_file = Keyword.get(info, :file)

if info_file != nil and SourceFile.Path.absname(info_file, project_dir) == file do
Keyword.get(info, :line)
end
end)
end

defp get_file_and_position_with_stacktrace_fallback(
{nil, _},
stacktrace,
root_path,
fallback_file
) do
# file unknown, try to get first matching project file from stacktrace
if candidate = get_file_position_from_stacktrace(stacktrace, root_path) do
candidate
else
# we have to return something
{fallback_file, 0}
end
end

defp get_file_and_position_with_stacktrace_fallback(
{file, 0},
stacktrace,
root_path,
_fallback_file
) do
# file known but position unknown - try first matching stacktrace entry from that file
{file, get_position_from_stacktrace(stacktrace, file, root_path)}
end

defp get_file_and_position_with_stacktrace_fallback(
{file, position},
_stacktrace,
_root_path,
_fallback_file
) do
{file, position}
end
end
3 changes: 2 additions & 1 deletion apps/language_server/lib/language_server/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1628,7 +1628,8 @@ defmodule ElixirLS.LanguageServer.Server do
# combine diagnostics
# they can be duplicated but it is not trivial to deduplicate here
# instead we deduplicate on publish with rendered messages
{parser_diagnostics_document_version, parser_diagnostics ++ build_and_dialyzer_diagnostics}
{parser_diagnostics_document_version,
parser_diagnostics ++ build_and_dialyzer_diagnostics}

true ->
# document closed
Expand Down

0 comments on commit cb23ee3

Please sign in to comment.