Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selection ranges porvider #1060

Merged
merged 26 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
409 changes: 409 additions & 0 deletions apps/language_server/lib/language_server/ast_utils.ex

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions apps/language_server/lib/language_server/protocol.ex
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ defmodule ElixirLS.LanguageServer.Protocol do
end
end

defmacro selection_range_req(id, uri, positions) do
quote do
request(unquote(id), "textDocument/selectionRange", %{
"textDocument" => %{"uri" => unquote(uri)},
"positions" => unquote(positions)
})
end
end

defmacro execute_command_req(id, command, arguments) do
quote do
request(unquote(id), "workspace/executeCommand", %{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.CommentBlock do
ranges =
lines
|> group_comments()
|> Enum.filter(fn group -> length(group) > 1 end)
|> Enum.map(&convert_comment_group_to_range/1)

{:ok, ranges}
end

@spec group_comments([Line.t()]) :: [[{Line.cell(), String.t()}]]
defp group_comments(lines) do
def group_comments(lines) do
lines
|> Enum.reduce([[]], fn
{_, cell, "#"}, [[{_, "#"} | _] = head | tail] ->
Expand All @@ -59,7 +60,6 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.CommentBlock do
_, acc ->
acc
end)
|> Enum.filter(fn group -> length(group) > 1 end)
end

@spec convert_comment_group_to_range([[{Line.cell(), String.t()}]]) :: FoldingRange.t()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.Indentation do
{:ok, ranges}
end

defp extract_cell({_line, cell, _first}), do: cell
def extract_cell({_line, cell, _first}), do: cell

@doc """
Pairs cells into {start, end} tuples of regions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,27 +56,33 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.SpecialToken do
end

@spec group_tokens([Token.t()]) :: [[Token.t()]]
defp group_tokens(tokens) do
def group_tokens(tokens) do
do_group_tokens(tokens, [])
end

defp do_group_tokens([], acc), do: acc

# Don't create folding ranges for docs
defp do_group_tokens([{:identifier, _, doc_identifier}, {false, _, _} | rest], acc)
# Don't create folding ranges for @doc false
defp do_group_tokens(
[{:at_op, _, _}, {:identifier, _, doc_identifier}, {false, _, _} | rest],
acc
)
when doc_identifier in @docs do
do_group_tokens(rest, acc)
end

# Start a folding range for `@doc` and `@moduledoc`
defp do_group_tokens([{:identifier, _, doc_identifier} = token | rest], acc)
defp do_group_tokens(
[{:at_op, _, _} = at_op, {:identifier, _, doc_identifier} = token | rest],
acc
)
when doc_identifier in @docs do
acc = [[token] | acc]
acc = [[token, at_op] | acc]
do_group_tokens(rest, acc)
end

# Amend the folding range
defp do_group_tokens([{k, _, _} = token | rest], [[{:identifier, _, _}] = head | tail])
defp do_group_tokens([{k, _, _} = token | rest], [[{:identifier, _, _} | _] = head | tail])
when k in @kinds do
acc = [[token | head] | tail]
do_group_tokens(rest, acc)
Expand Down Expand Up @@ -118,7 +124,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.SpecialToken do
end

defp classify_group({kind, {start_line, _, _}, _}, {_, {end_line, _, _}, _}) do
kind = if kind == :identifier, do: :comment, else: :region
kind = if kind == :at_op, do: :comment, else: :region
{start_line, end_line, kind}
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.TokenPair do
end

@spec pair_tokens([Token.t()]) :: [{Token.t(), Token.t()}]
defp pair_tokens(tokens) do
def pair_tokens(tokens) do
do_pair_tokens(tokens, [], [])
end

Expand All @@ -82,8 +82,8 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.TokenPair do
pairs
) do
head_matches_any? = @token_pairs |> Map.has_key?(head_kind)
# Map.get/2 will always succeed because we only push matches to the stack.
head_matches_top? = @token_pairs |> Map.get(top_kind) |> Enum.member?(head_kind)
# Map.fetch!/2 will always succeed because we only push matches to the stack.
head_matches_top? = @token_pairs |> Map.fetch!(top_kind) |> Enum.member?(head_kind)

{new_stack, new_pairs} =
case {head_matches_any?, head_matches_top?} do
Expand Down
Loading
Loading