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

Always return Completion.List with is_incomplete: true #398

Merged
merged 1 commit into from
Oct 11, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ defmodule Lexical.RemoteControl.Completion.Candidate do
end

def from_elixir_sense(elixir_sense_map) do
Logger.warning("Unhandled compleetion suggestion: #{inspect(elixir_sense_map)}")
Logger.warning("Unhandled completion suggestion: #{inspect(elixir_sense_map)}")
nil
end
end
19 changes: 9 additions & 10 deletions apps/server/lib/lexical/server/code_intelligence/completion.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ defmodule Lexical.Server.CodeIntelligence.Completion do
[".", "@", "&", "%", "^", ":", "!", "-", "~"]
end

@spec complete(Project.t(), Document.t(), Position.t(), Completion.Context.t()) :: [
Completion.Item
]
@spec complete(Project.t(), Document.t(), Position.t(), Completion.Context.t()) ::
Completion.List.t()
def complete(
%Project{} = project,
%Document{} = document,
Expand All @@ -40,11 +39,11 @@ defmodule Lexical.Server.CodeIntelligence.Completion do
{:ok, env} ->
completions = completions(project, env, context)
Logger.warning("Emitting completions: #{inspect(completions)}")
completions
completion_list(completions)

{:error, _} = error ->
Logger.error("Failed to build completion env #{inspect(error)}")
empty_completion_list()
completion_list()
end
end

Expand All @@ -53,17 +52,17 @@ defmodule Lexical.Server.CodeIntelligence.Completion do

cond do
prefix_tokens == [] ->
empty_completion_list()
[]

match?([{:operator, :do, _}], prefix_tokens) and Env.empty?(env.suffix) ->
do_end_snippet = "do\n$0\nend"
do_end_snippet = "do\n $0\nend"
scohen marked this conversation as resolved.
Show resolved Hide resolved

env
|> Builder.snippet(do_end_snippet, label: "do/end block")
|> List.wrap()

Enum.empty?(prefix_tokens) or not context_will_give_meaningful_completions?(env) ->
Completion.List.new(items: [], is_incomplete: true)
[]

Env.in_context?(env, :struct_arguments) and not Env.in_context?(env, :struct_field_value) and
not prefix_is_trigger?(env) ->
Expand Down Expand Up @@ -230,7 +229,7 @@ defmodule Lexical.Server.CodeIntelligence.Completion do
true
end

defp empty_completion_list do
Completion.List.new(items: [], is_incomplete: true)
defp completion_list(items \\ []) do
Completion.List.new(items: items, is_incomplete: true)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule Lexical.Server.CodeIntelligence.Completion.Translations.MacroTest do
describe "Kernel* macros" do
test "do/end only has a single completion", %{project: project} do
assert [completion] = complete(project, "def my_thing do|")
assert completion.insert_text == "do\n$0\nend"
assert completion.insert_text == "do\n $0\nend"
assert completion.label == "do/end block"
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,22 @@ defmodule Lexical.Server.CodeIntelligence.CompletionTest do
end

test "ignores erlang modules", %{project: project} do
assert %Completion.List{is_incomplete: true, items: []} = complete(project, ":e|")
assert %Completion.List{is_incomplete: true, items: []} =
complete(project, ":e|", as_list: false)
end
end

describe "ignoring things" do
test "return empty items and mark is_incomplete when single character contexts", %{
project: project
} do
assert complete(project, "def my_thing() d|") == %Completion.List{
is_incomplete: true,
items: []
}
assert %Completion.List{is_incomplete: true, items: []} =
complete(project, "def my_thing() d|", as_list: false)
end

test "returns an incomplete completion list when the context is empty", %{project: project} do
assert %Completion.List{is_incomplete: true, items: []} = complete(project, " ")
assert %Completion.List{is_incomplete: true, items: []} =
complete(project, " ", as_list: false)
end
end

Expand Down
27 changes: 15 additions & 12 deletions apps/server/test/support/lexical/test/completion_case.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ defmodule Lexical.Test.Server.CompletionCase do
end

def complete(project, text, opts \\ []) do
return_as_list? = Keyword.get(opts, :as_list, true)
trigger_character = Keyword.get(opts, :trigger_character)
root_path = Project.root_path(project)

Expand Down Expand Up @@ -69,11 +70,19 @@ defmodule Lexical.Test.Server.CompletionCase do
CompletionContext.new(trigger_kind: :trigger_character)
end

Completion.complete(project, document, position, context)
result = Completion.complete(project, document, position, context)

if return_as_list? do
completion_items(result)
else
result
end
end

def fetch_completion(completions, label_prefix) when is_binary(label_prefix) do
case Enum.filter(completions, &String.starts_with?(&1.label, label_prefix)) do
matcher = &String.starts_with?(&1.label, label_prefix)

case completions |> completion_items() |> Enum.filter(matcher) do
[] -> {:error, :not_found}
[found] -> {:ok, found}
found when is_list(found) -> {:ok, found}
Expand All @@ -91,16 +100,7 @@ defmodule Lexical.Test.Server.CompletionCase do
end)
end

completion_enumerable =
case completions do
%CompletionList{} = completion_list ->
completion_list.items

list when is_list(list) ->
list
end

case Enum.filter(completion_enumerable, matcher) do
case completions |> completion_items() |> Enum.filter(matcher) do
[] -> {:error, :not_found}
[found] -> {:ok, found}
found when is_list(found) -> {:ok, found}
Expand All @@ -122,4 +122,7 @@ defmodule Lexical.Test.Server.CompletionCase do
false
end
end

defp completion_items(%CompletionList{items: items}), do: items
defp completion_items(items) when is_list(items), do: items
end