From 5d4014fb1aa759445e067d16cd027bb4c6915fce Mon Sep 17 00:00:00 2001 From: Zach Allaun Date: Wed, 11 Oct 2023 10:48:11 -0400 Subject: [PATCH] Don't return empty completions for single char prefix Related: #400 VS Code in particular handles empty completions lists very poorly, refusing to make further completion requests. This commit removes the logic that was preventing completions from being returned when the prefix is a single character. --- .../server/code_intelligence/completion.ex | 33 ++----------------- .../code_intelligence/completion_test.exs | 16 ++++----- 2 files changed, 9 insertions(+), 40 deletions(-) diff --git a/apps/server/lib/lexical/server/code_intelligence/completion.ex b/apps/server/lib/lexical/server/code_intelligence/completion.ex index 8ba760724..c24e99253 100644 --- a/apps/server/lib/lexical/server/code_intelligence/completion.ex +++ b/apps/server/lib/lexical/server/code_intelligence/completion.ex @@ -4,7 +4,6 @@ defmodule Lexical.Server.CodeIntelligence.Completion do alias Lexical.Completion.Translatable alias Lexical.Document alias Lexical.Document.Position - alias Lexical.Math alias Lexical.Project alias Lexical.Protocol.Types.Completion alias Lexical.Protocol.Types.InsertTextFormat @@ -38,7 +37,7 @@ defmodule Lexical.Server.CodeIntelligence.Completion do case Env.new(project, document, position) do {:ok, env} -> completions = completions(project, env, context) - Logger.warning("Emitting completions: #{inspect(completions)}") + Logger.info("Emitting completions: #{inspect(completions)}") completion_list(completions) {:error, _} = error -> @@ -51,7 +50,7 @@ defmodule Lexical.Server.CodeIntelligence.Completion do prefix_tokens = Env.prefix_tokens(env, 1) cond do - prefix_tokens == [] -> + prefix_tokens == [] or not context_will_give_meaningful_completions?(env) -> [] match?([{:operator, :do, _}], prefix_tokens) and Env.empty?(env.suffix) -> @@ -61,9 +60,6 @@ defmodule Lexical.Server.CodeIntelligence.Completion do |> Builder.snippet(do_end_snippet, label: "do/end block") |> List.wrap() - Enum.empty?(prefix_tokens) or not context_will_give_meaningful_completions?(env) -> - [] - Env.in_context?(env, :struct_arguments) and not Env.in_context?(env, :struct_field_value) and not prefix_is_trigger?(env) -> project @@ -107,30 +103,7 @@ defmodule Lexical.Server.CodeIntelligence.Completion do end defp context_will_give_meaningful_completions?(%Env{} = env) do - case Code.Fragment.cursor_context(env.prefix) do - {:local_or_var, name} -> - local_length = length(name) - - surround_begin = - Math.clamp(env.position.character - local_length - 1, 1, env.position.character) - - case Code.Fragment.surround_context(env.prefix, {1, surround_begin}) do - :none -> - local_length > 1 - - _other -> - true - end - - :none -> - false - - {:unquoted_atom, name} -> - length(name) > 1 - - _ -> - true - end + Code.Fragment.cursor_context(env.prefix) != :none end defp displayable?(%Project{} = project, result) do diff --git a/apps/server/test/lexical/server/code_intelligence/completion_test.exs b/apps/server/test/lexical/server/code_intelligence/completion_test.exs index bcf81afee..d9f0a2006 100644 --- a/apps/server/test/lexical/server/code_intelligence/completion_test.exs +++ b/apps/server/test/lexical/server/code_intelligence/completion_test.exs @@ -52,20 +52,16 @@ defmodule Lexical.Server.CodeIntelligence.CompletionTest do end end - test "ignores erlang modules", %{project: project} do - assert %Completion.List{is_incomplete: true, items: []} = - complete(project, ":e|", as_list: false) + test "completes erlang modules", %{project: project} do + assert [_ | _] = completions = complete(project, ":e|") + + for completion <- completions do + assert completion.kind == :module + end end end describe "ignoring things" do - test "return empty items and mark is_incomplete when single character contexts", %{ - project: project - } do - 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, " ", as_list: false)