Skip to content

Commit 43e17f9

Browse files
committed
Get end_of_expression from parent end location
Fixes #938
1 parent 72ae78b commit 43e17f9

File tree

2 files changed

+60
-21
lines changed

2 files changed

+60
-21
lines changed

apps/language_server/lib/language_server/providers/document_symbols.ex

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
113113
mod_defns
114114
|> Enum.map(&extract_symbol(module_name, &1))
115115
|> Enum.reject(&is_nil/1)
116+
|> Enum.map(fn info ->
117+
%{info | location: Keyword.put(info.location, :parent_location, location)}
118+
end)
116119

117120
type =
118121
case defname do
@@ -154,8 +157,6 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
154157
[]
155158
end
156159

157-
# TODO there is no end/closing metadata in the AST - use literal encoder
158-
159160
%Info{
160161
type: :struct,
161162
name: "#{defname} #{module_name}",
@@ -164,7 +165,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
164165
}
165166
end
166167

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

170171
# Types
@@ -440,31 +441,69 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do
440441
end
441442

442443
defp location_to_range(location, text, symbol) do
444+
lines = SourceFile.lines(text)
445+
443446
{start_line, start_character} =
444-
SourceFile.elixir_position_to_lsp(text, {location[:line], location[:column]})
447+
SourceFile.elixir_position_to_lsp(lines, {location[:line], location[:column]})
445448

446449
{end_line, end_character} =
447450
cond do
448451
end_location = location[:end_of_expression] ->
449-
SourceFile.elixir_position_to_lsp(text, {end_location[:line], end_location[:column]})
452+
SourceFile.elixir_position_to_lsp(lines, {end_location[:line], end_location[:column]})
450453

451454
end_location = location[:end] ->
452455
SourceFile.elixir_position_to_lsp(
453-
text,
456+
lines,
454457
{end_location[:line], end_location[:column] + 3}
455458
)
456459

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

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

471+
parent_end_line =
472+
location
473+
|> Keyword.get(:parent_location, [])
474+
|> Keyword.get(:end, [])
475+
|> Keyword.get(:line) ->
476+
# last expression in block does not have end_of_expression
477+
parent_do_line = location[:parent_location][:do][:line]
478+
479+
if parent_end_line > parent_do_line do
480+
# take end location from parent and assume end_of_expression is last char in previous line
481+
end_of_expression =
482+
Enum.at(lines, parent_end_line - 2)
483+
|> String.length()
484+
485+
SourceFile.elixir_position_to_lsp(
486+
lines,
487+
{parent_end_line - 1, end_of_expression + 1}
488+
)
489+
else
490+
# take end location from parent and assume end_of_expression is last char before final ; trimmed
491+
line = Enum.at(lines, parent_end_line - 1)
492+
parent_end_column = location[:parent_location][:end][:column]
493+
494+
end_of_expression =
495+
line
496+
|> String.slice(0..(parent_end_column - 2))
497+
|> String.trim_trailing()
498+
|> String.replace_trailing(";", "")
499+
|> String.length()
500+
501+
SourceFile.elixir_position_to_lsp(
502+
lines,
503+
{parent_end_line, end_of_expression + 1}
504+
)
505+
end
506+
468507
true ->
469508
{start_line, start_character}
470509
end

apps/language_server/test/providers/document_symbols_test.exs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
827827
kind: 12,
828828
name: "def size(binary)",
829829
range: %{
830-
"end" => %{"character" => 18, "line" => 6},
830+
"end" => %{"character" => 41, "line" => 6},
831831
"start" => %{"character" => 2, "line" => 6}
832832
},
833833
selectionRange: %{
@@ -854,7 +854,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
854854
kind: 12,
855855
name: "def size(param)",
856856
range: %{
857-
"end" => %{"character" => 17, "line" => 10},
857+
"end" => %{"character" => 36, "line" => 10},
858858
"start" => %{"character" => 2, "line" => 10}
859859
},
860860
selectionRange: %{
@@ -912,7 +912,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
912912
name: "def size(data)",
913913
location: %{
914914
range: %{
915-
"end" => %{"character" => 2, "line" => 2},
915+
"end" => %{"character" => 16, "line" => 2},
916916
"start" => %{"character" => 2, "line" => 2}
917917
}
918918
},
@@ -933,7 +933,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
933933
name: "def size(binary)",
934934
location: %{
935935
range: %{
936-
"end" => %{"character" => 2, "line" => 6},
936+
"end" => %{"character" => 41, "line" => 6},
937937
"start" => %{"character" => 2, "line" => 6}
938938
}
939939
},
@@ -954,7 +954,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
954954
name: "def size(param)",
955955
location: %{
956956
range: %{
957-
"end" => %{"character" => 2, "line" => 10},
957+
"end" => %{"character" => 36, "line" => 10},
958958
"start" => %{"character" => 2, "line" => 10}
959959
}
960960
},
@@ -1008,11 +1008,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
10081008
kind: 23,
10091009
name: "defstruct MyModule",
10101010
range: %{
1011-
"end" => %{"character" => 2, "line" => 1},
1011+
"end" => %{"character" => 39, "line" => 1},
10121012
"start" => %{"character" => 2, "line" => 1}
10131013
},
10141014
selectionRange: %{
1015-
"end" => %{"character" => 2, "line" => 1},
1015+
"end" => %{"character" => 39, "line" => 1},
10161016
"start" => %{"character" => 2, "line" => 1}
10171017
}
10181018
}
@@ -1043,7 +1043,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
10431043
kind: 23,
10441044
location: %{
10451045
range: %{
1046-
"end" => %{"character" => 2, "line" => 1},
1046+
"end" => %{"character" => 39, "line" => 1},
10471047
"start" => %{"character" => 2, "line" => 1}
10481048
}
10491049
},
@@ -1106,11 +1106,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
11061106
kind: 23,
11071107
name: "defexception MyError",
11081108
range: %{
1109-
"end" => %{"character" => 2, "line" => 1},
1109+
"end" => %{"character" => 25, "line" => 1},
11101110
"start" => %{"character" => 2, "line" => 1}
11111111
},
11121112
selectionRange: %{
1113-
"end" => %{"character" => 2, "line" => 1},
1113+
"end" => %{"character" => 25, "line" => 1},
11141114
"start" => %{"character" => 2, "line" => 1}
11151115
}
11161116
}
@@ -1141,7 +1141,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
11411141
name: "defexception MyError",
11421142
location: %{
11431143
range: %{
1144-
"end" => %{"character" => 2, "line" => 1},
1144+
"end" => %{"character" => 25, "line" => 1},
11451145
"start" => %{"character" => 2, "line" => 1}
11461146
}
11471147
},
@@ -1893,11 +1893,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
18931893
kind: 12,
18941894
name: "test \"does something\"",
18951895
range: %{
1896-
"end" => %{"character" => 8, "line" => 3},
1896+
"end" => %{"character" => 38, "line" => 3},
18971897
"start" => %{"character" => 8, "line" => 3}
18981898
},
18991899
selectionRange: %{
1900-
"end" => %{"character" => 8, "line" => 3},
1900+
"end" => %{"character" => 38, "line" => 3},
19011901
"start" => %{"character" => 8, "line" => 3}
19021902
}
19031903
}
@@ -1934,7 +1934,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do
19341934
kind: 12,
19351935
location: %{
19361936
range: %{
1937-
"end" => %{"character" => 8, "line" => 3},
1937+
"end" => %{"character" => 38, "line" => 3},
19381938
"start" => %{"character" => 8, "line" => 3}
19391939
}
19401940
},

0 commit comments

Comments
 (0)