Completion adjustments (#456)

* Fix function arity completion

* Add support for operator completion in Elixir 1.13
This commit is contained in:
Jonatan Kłosko 2021-07-21 21:09:28 +02:00 committed by GitHub
parent 31991a12f3
commit 9bbbd4568f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 96 additions and 4 deletions

View file

@ -277,7 +277,14 @@ defmodule Livebook.Intellisense do
defp format_signatures([], _module), do: nil
defp format_signatures(signatures, module) do
module_to_prefix(module) <> Enum.join(signatures, "\n")
signatures_string = Enum.join(signatures, "\n")
# Don't add module prefix to operator signatures
if :binary.match(signatures_string, ["(", "/"]) != :nomatch do
module_to_prefix(module) <> signatures_string
else
signatures_string
end
end
defp module_to_prefix(mod) do

View file

@ -23,6 +23,9 @@ defmodule Livebook.Intellisense.Completion do
@type signature :: String.t()
@type spec :: tuple() | nil
@exact_matcher &Kernel.==/2
@prefix_matcher &String.starts_with?/2
@doc """
Returns a list of identifiers matching the given `hint`
together with relevant information.
@ -40,7 +43,7 @@ defmodule Livebook.Intellisense.Completion do
@spec get_completion_items(String.t(), Code.binding(), Macro.Env.t(), keyword()) ::
list(completion_item())
def get_completion_items(hint, binding, env, opts \\ []) do
matcher = if opts[:exact], do: &Kernel.==/2, else: &String.starts_with?/2
matcher = if opts[:exact], do: @exact_matcher, else: @prefix_matcher
complete(hint, %{binding: binding, env: env, matcher: matcher})
end
@ -57,7 +60,7 @@ defmodule Livebook.Intellisense.Completion do
complete_dot(path, List.to_string(hint), ctx)
{:dot_arity, path, hint} ->
complete_dot(path, List.to_string(hint), ctx)
complete_dot(path, List.to_string(hint), %{ctx | matcher: @exact_matcher})
{:dot_call, _path, _hint} ->
complete_default(ctx)
@ -69,11 +72,20 @@ defmodule Livebook.Intellisense.Completion do
complete_local_or_var(List.to_string(local_or_var), ctx)
{:local_arity, local} ->
complete_local(List.to_string(local), ctx)
complete_local(List.to_string(local), %{ctx | matcher: @exact_matcher})
{:local_call, _local} ->
complete_default(ctx)
{:operator, operator} ->
complete_local_or_var(List.to_string(operator), ctx)
{:operator_arity, operator} ->
complete_local(List.to_string(operator), %{ctx | matcher: @exact_matcher})
{:operator_call, _operator} ->
complete_default(ctx)
{:module_attribute, attribute} ->
complete_module_attribute(List.to_string(attribute), ctx)

View file

@ -313,6 +313,11 @@ defmodule Livebook.IntellisenseTest do
""",
insert_text: "concat"
} in Intellisense.get_completion_items("Enum.concat/", binding, env)
assert [
%{label: "count/1"},
%{label: "count/2"}
] = Intellisense.get_completion_items("Enum.count/", binding, env)
end
test "function completion same name with different arities" do
@ -410,6 +415,69 @@ defmodule Livebook.IntellisenseTest do
] = Intellisense.get_completion_items("mod.ve", binding, env)
end
# TODO: Enable on Elixir 1.13
# test "operator completion" do
# {binding, env} = eval(do: nil)
# assert [
# %{
# label: "++/2",
# kind: :function,
# detail: "left ++ right",
# documentation: """
# List concatenation operator. Concatenates a proper list and a term, returning a list.
# ```
# @spec list() ++ term() ::
# maybe_improper_list()
# ```\
# """,
# insert_text: "++"
# },
# %{
# label: "+/1",
# kind: :function,
# detail: "+value",
# documentation: """
# Arithmetic positive unary operator.
# ```
# @spec +integer() :: integer()
# @spec +float() :: float()
# ```\
# """,
# insert_text: "+"
# },
# %{
# label: "+/2",
# kind: :function,
# detail: "left + right",
# documentation: """
# Arithmetic addition operator.
# ```
# @spec integer() + integer() ::
# integer()
# @spec float() + float() :: float()
# @spec integer() + float() :: float()
# @spec float() + integer() :: float()
# ```\
# """,
# insert_text: "+"
# }
# ] = Intellisense.get_completion_items("+", binding, env)
# assert [
# %{label: "+/1"},
# %{label: "+/2"}
# ] = Intellisense.get_completion_items("+/", binding, env)
# assert [
# %{label: "++/2"}
# ] = Intellisense.get_completion_items("++/", binding, env)
# end
test "map atom key completion" do
{binding, env} =
eval do
@ -692,6 +760,11 @@ defmodule Livebook.IntellisenseTest do
%{label: "derive/2"},
%{label: "derive/3"}
] = Intellisense.get_completion_items("der", binding, env)
assert [
%{label: "count/1"},
%{label: "count/2"}
] = Intellisense.get_completion_items("count/", binding, env)
end
test "ignores quoted variables when performing variable completion" do