Skip to content

Commit

Permalink
Get end_of_expression from parent end location
Browse files Browse the repository at this point in the history
Fixes #938
  • Loading branch information
lukaszsamson committed Oct 14, 2023
1 parent 72ae78b commit 43e17f9
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
mod_defns
|> Enum.map(&extract_symbol(module_name, &1))
|> Enum.reject(&is_nil/1)
|> Enum.map(fn info ->
%{info | location: Keyword.put(info.location, :parent_location, location)}
end)

type =
case defname do
Expand Down Expand Up @@ -154,8 +157,6 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
[]
end

# TODO there is no end/closing metadata in the AST - use literal encoder

%Info{
type: :struct,
name: "#{defname} #{module_name}",
Expand All @@ -164,7 +165,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
}
end

# We skip attributes only supplementoing the symbol
# We skip attributes only supplementing the symbol
defp extract_symbol(_, {:@, _, [{kind, _, _}]}) when kind in @supplementing_attributes, do: nil

# Types
Expand Down Expand Up @@ -440,31 +441,69 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
end

defp location_to_range(location, text, symbol) do
lines = SourceFile.lines(text)

{start_line, start_character} =
SourceFile.elixir_position_to_lsp(text, {location[:line], location[:column]})
SourceFile.elixir_position_to_lsp(lines, {location[:line], location[:column]})

{end_line, end_character} =
cond do
end_location = location[:end_of_expression] ->
SourceFile.elixir_position_to_lsp(text, {end_location[:line], end_location[:column]})
SourceFile.elixir_position_to_lsp(lines, {end_location[:line], end_location[:column]})

end_location = location[:end] ->
SourceFile.elixir_position_to_lsp(
text,
lines,
{end_location[:line], end_location[:column] + 3}
)

end_location = location[:closing] ->
# all closing tags we expect here are 1 char width
SourceFile.elixir_position_to_lsp(
text,
lines,
{end_location[:line], end_location[:column] + 1}
)

symbol != nil ->
end_char = SourceFile.elixir_character_to_lsp(symbol, String.length(symbol))
{start_line, start_character + end_char + 1}

parent_end_line =
location
|> Keyword.get(:parent_location, [])
|> Keyword.get(:end, [])
|> Keyword.get(:line) ->
# last expression in block does not have end_of_expression
parent_do_line = location[:parent_location][:do][:line]

if parent_end_line > parent_do_line do
# take end location from parent and assume end_of_expression is last char in previous line
end_of_expression =
Enum.at(lines, parent_end_line - 2)
|> String.length()

SourceFile.elixir_position_to_lsp(
lines,
{parent_end_line - 1, end_of_expression + 1}
)
else
# take end location from parent and assume end_of_expression is last char before final ; trimmed
line = Enum.at(lines, parent_end_line - 1)
parent_end_column = location[:parent_location][:end][:column]

end_of_expression =
line
|> String.slice(0..(parent_end_column - 2))
|> String.trim_trailing()
|> String.replace_trailing(";", "")
|> String.length()

SourceFile.elixir_position_to_lsp(
lines,
{parent_end_line, end_of_expression + 1}
)
end

true ->
{start_line, start_character}
end
Expand Down
28 changes: 14 additions & 14 deletions apps/language_server/test/providers/document_symbols_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
kind: 12,
name: "def size(binary)",
range: %{
"end" => %{"character" => 18, "line" => 6},
"end" => %{"character" => 41, "line" => 6},
"start" => %{"character" => 2, "line" => 6}
},
selectionRange: %{
Expand All @@ -854,7 +854,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
kind: 12,
name: "def size(param)",
range: %{
"end" => %{"character" => 17, "line" => 10},
"end" => %{"character" => 36, "line" => 10},
"start" => %{"character" => 2, "line" => 10}
},
selectionRange: %{
Expand Down Expand Up @@ -912,7 +912,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
name: "def size(data)",
location: %{
range: %{
"end" => %{"character" => 2, "line" => 2},
"end" => %{"character" => 16, "line" => 2},
"start" => %{"character" => 2, "line" => 2}
}
},
Expand All @@ -933,7 +933,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
name: "def size(binary)",
location: %{
range: %{
"end" => %{"character" => 2, "line" => 6},
"end" => %{"character" => 41, "line" => 6},
"start" => %{"character" => 2, "line" => 6}
}
},
Expand All @@ -954,7 +954,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
name: "def size(param)",
location: %{
range: %{
"end" => %{"character" => 2, "line" => 10},
"end" => %{"character" => 36, "line" => 10},
"start" => %{"character" => 2, "line" => 10}
}
},
Expand Down Expand Up @@ -1008,11 +1008,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
kind: 23,
name: "defstruct MyModule",
range: %{
"end" => %{"character" => 2, "line" => 1},
"end" => %{"character" => 39, "line" => 1},
"start" => %{"character" => 2, "line" => 1}
},
selectionRange: %{
"end" => %{"character" => 2, "line" => 1},
"end" => %{"character" => 39, "line" => 1},
"start" => %{"character" => 2, "line" => 1}
}
}
Expand Down Expand Up @@ -1043,7 +1043,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
kind: 23,
location: %{
range: %{
"end" => %{"character" => 2, "line" => 1},
"end" => %{"character" => 39, "line" => 1},
"start" => %{"character" => 2, "line" => 1}
}
},
Expand Down Expand Up @@ -1106,11 +1106,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
kind: 23,
name: "defexception MyError",
range: %{
"end" => %{"character" => 2, "line" => 1},
"end" => %{"character" => 25, "line" => 1},
"start" => %{"character" => 2, "line" => 1}
},
selectionRange: %{
"end" => %{"character" => 2, "line" => 1},
"end" => %{"character" => 25, "line" => 1},
"start" => %{"character" => 2, "line" => 1}
}
}
Expand Down Expand Up @@ -1141,7 +1141,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
name: "defexception MyError",
location: %{
range: %{
"end" => %{"character" => 2, "line" => 1},
"end" => %{"character" => 25, "line" => 1},
"start" => %{"character" => 2, "line" => 1}
}
},
Expand Down Expand Up @@ -1893,11 +1893,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
kind: 12,
name: "test \"does something\"",
range: %{
"end" => %{"character" => 8, "line" => 3},
"end" => %{"character" => 38, "line" => 3},
"start" => %{"character" => 8, "line" => 3}
},
selectionRange: %{
"end" => %{"character" => 8, "line" => 3},
"end" => %{"character" => 38, "line" => 3},
"start" => %{"character" => 8, "line" => 3}
}
}
Expand Down Expand Up @@ -1934,7 +1934,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
kind: 12,
location: %{
range: %{
"end" => %{"character" => 8, "line" => 3},
"end" => %{"character" => 38, "line" => 3},
"start" => %{"character" => 8, "line" => 3}
}
},
Expand Down

0 comments on commit 43e17f9

Please sign in to comment.