mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-09-06 13:04:53 +08:00
Completion adjustments (#456)
* Fix function arity completion * Add support for operator completion in Elixir 1.13
This commit is contained in:
parent
31991a12f3
commit
9bbbd4568f
3 changed files with 96 additions and 4 deletions
|
@ -277,7 +277,14 @@ defmodule Livebook.Intellisense do
|
||||||
defp format_signatures([], _module), do: nil
|
defp format_signatures([], _module), do: nil
|
||||||
|
|
||||||
defp format_signatures(signatures, module) do
|
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
|
end
|
||||||
|
|
||||||
defp module_to_prefix(mod) do
|
defp module_to_prefix(mod) do
|
||||||
|
|
|
@ -23,6 +23,9 @@ defmodule Livebook.Intellisense.Completion do
|
||||||
@type signature :: String.t()
|
@type signature :: String.t()
|
||||||
@type spec :: tuple() | nil
|
@type spec :: tuple() | nil
|
||||||
|
|
||||||
|
@exact_matcher &Kernel.==/2
|
||||||
|
@prefix_matcher &String.starts_with?/2
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns a list of identifiers matching the given `hint`
|
Returns a list of identifiers matching the given `hint`
|
||||||
together with relevant information.
|
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()) ::
|
@spec get_completion_items(String.t(), Code.binding(), Macro.Env.t(), keyword()) ::
|
||||||
list(completion_item())
|
list(completion_item())
|
||||||
def get_completion_items(hint, binding, env, opts \\ []) do
|
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})
|
complete(hint, %{binding: binding, env: env, matcher: matcher})
|
||||||
end
|
end
|
||||||
|
@ -57,7 +60,7 @@ defmodule Livebook.Intellisense.Completion do
|
||||||
complete_dot(path, List.to_string(hint), ctx)
|
complete_dot(path, List.to_string(hint), ctx)
|
||||||
|
|
||||||
{:dot_arity, path, hint} ->
|
{: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} ->
|
{:dot_call, _path, _hint} ->
|
||||||
complete_default(ctx)
|
complete_default(ctx)
|
||||||
|
@ -69,11 +72,20 @@ defmodule Livebook.Intellisense.Completion do
|
||||||
complete_local_or_var(List.to_string(local_or_var), ctx)
|
complete_local_or_var(List.to_string(local_or_var), ctx)
|
||||||
|
|
||||||
{:local_arity, local} ->
|
{:local_arity, local} ->
|
||||||
complete_local(List.to_string(local), ctx)
|
complete_local(List.to_string(local), %{ctx | matcher: @exact_matcher})
|
||||||
|
|
||||||
{:local_call, _local} ->
|
{:local_call, _local} ->
|
||||||
complete_default(ctx)
|
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} ->
|
{:module_attribute, attribute} ->
|
||||||
complete_module_attribute(List.to_string(attribute), ctx)
|
complete_module_attribute(List.to_string(attribute), ctx)
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,11 @@ defmodule Livebook.IntellisenseTest do
|
||||||
""",
|
""",
|
||||||
insert_text: "concat"
|
insert_text: "concat"
|
||||||
} in Intellisense.get_completion_items("Enum.concat/", binding, env)
|
} 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
|
end
|
||||||
|
|
||||||
test "function completion same name with different arities" do
|
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)
|
] = Intellisense.get_completion_items("mod.ve", binding, env)
|
||||||
end
|
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
|
test "map atom key completion" do
|
||||||
{binding, env} =
|
{binding, env} =
|
||||||
eval do
|
eval do
|
||||||
|
@ -692,6 +760,11 @@ defmodule Livebook.IntellisenseTest do
|
||||||
%{label: "derive/2"},
|
%{label: "derive/2"},
|
||||||
%{label: "derive/3"}
|
%{label: "derive/3"}
|
||||||
] = Intellisense.get_completion_items("der", binding, env)
|
] = Intellisense.get_completion_items("der", binding, env)
|
||||||
|
|
||||||
|
assert [
|
||||||
|
%{label: "count/1"},
|
||||||
|
%{label: "count/2"}
|
||||||
|
] = Intellisense.get_completion_items("count/", binding, env)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "ignores quoted variables when performing variable completion" do
|
test "ignores quoted variables when performing variable completion" do
|
||||||
|
|
Loading…
Add table
Reference in a new issue