mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-02 09:44:44 +08:00
Improve completion (#756)
* Don't show variable value in intellisense * Don't complete quoted atoms
This commit is contained in:
parent
be3225fe3a
commit
b97cde0879
3 changed files with 90 additions and 45 deletions
|
@ -127,21 +127,21 @@ defmodule Livebook.Intellisense do
|
|||
|
||||
defp include_in_completion?(_), do: true
|
||||
|
||||
defp format_completion_item({:variable, name, value}),
|
||||
defp format_completion_item({:variable, name, _value}),
|
||||
do: %{
|
||||
label: name,
|
||||
kind: :variable,
|
||||
detail: "variable",
|
||||
documentation: value_snippet(value, @line_length),
|
||||
documentation: nil,
|
||||
insert_text: name
|
||||
}
|
||||
|
||||
defp format_completion_item({:map_field, name, value}),
|
||||
defp format_completion_item({:map_field, name, _value}),
|
||||
do: %{
|
||||
label: name,
|
||||
kind: :field,
|
||||
detail: "field",
|
||||
documentation: value_snippet(value, @line_length),
|
||||
documentation: nil,
|
||||
insert_text: name
|
||||
}
|
||||
|
||||
|
@ -336,18 +336,9 @@ defmodule Livebook.Intellisense do
|
|||
end
|
||||
end
|
||||
|
||||
defp format_details_item({:variable, name, value}) do
|
||||
join_with_divider([
|
||||
code(name),
|
||||
value_snippet(value, @extended_line_length)
|
||||
])
|
||||
end
|
||||
defp format_details_item({:variable, name, _value}), do: code(name)
|
||||
|
||||
defp format_details_item({:map_field, _name, value}) do
|
||||
join_with_divider([
|
||||
value_snippet(value, @extended_line_length)
|
||||
])
|
||||
end
|
||||
defp format_details_item({:map_field, name, _value}), do: code(name)
|
||||
|
||||
defp format_details_item({:module, _module, display_name, documentation}) do
|
||||
join_with_divider([
|
||||
|
@ -403,14 +394,6 @@ defmodule Livebook.Intellisense do
|
|||
"""
|
||||
end
|
||||
|
||||
defp value_snippet(value, line_length) do
|
||||
"""
|
||||
```
|
||||
#{inspect(value, pretty: true, width: line_length)}
|
||||
```\
|
||||
"""
|
||||
end
|
||||
|
||||
defp format_signatures([], _module), do: nil
|
||||
|
||||
defp format_signatures(signatures, module) do
|
||||
|
|
|
@ -341,7 +341,7 @@ defmodule Livebook.Intellisense.IdentifierMatcher do
|
|||
defp valid_alias_rest?(rest), do: valid_alias_piece?(rest)
|
||||
|
||||
defp usable_as_unquoted_module?(mod) do
|
||||
Code.Identifier.classify(mod) != :other
|
||||
macro_classify_atom(mod) in [:identifier, :unquoted]
|
||||
end
|
||||
|
||||
defp get_matching_modules(hint, ctx) do
|
||||
|
@ -484,4 +484,70 @@ defmodule Livebook.Intellisense.IdentifierMatcher do
|
|||
ctx.matcher.(name, hint),
|
||||
do: {:module_attribute, name, {"text/markdown", info.doc}}
|
||||
end
|
||||
|
||||
# ---
|
||||
|
||||
# TODO use Macro.classify_atom/1 on Elixir 1.14
|
||||
|
||||
def macro_classify_atom(atom) do
|
||||
case macro_inner_classify(atom) do
|
||||
:alias -> :alias
|
||||
:identifier -> :identifier
|
||||
type when type in [:unquoted_operator, :not_callable] -> :unquoted
|
||||
_ -> :quoted
|
||||
end
|
||||
end
|
||||
|
||||
defp macro_inner_classify(atom) when is_atom(atom) do
|
||||
cond do
|
||||
atom in [:%, :%{}, :{}, :<<>>, :..., :.., :., :"..//", :->] ->
|
||||
:not_callable
|
||||
|
||||
atom in [:"::"] ->
|
||||
:quoted_operator
|
||||
|
||||
Macro.operator?(atom, 1) or Macro.operator?(atom, 2) ->
|
||||
:unquoted_operator
|
||||
|
||||
true ->
|
||||
charlist = Atom.to_charlist(atom)
|
||||
|
||||
if macro_valid_alias?(charlist) do
|
||||
:alias
|
||||
else
|
||||
case :elixir_config.identifier_tokenizer().tokenize(charlist) do
|
||||
{kind, _acc, [], _, _, special} ->
|
||||
if kind == :identifier and not :lists.member(?@, special) do
|
||||
:identifier
|
||||
else
|
||||
:not_callable
|
||||
end
|
||||
|
||||
_ ->
|
||||
:other
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp macro_valid_alias?('Elixir' ++ rest), do: macro_valid_alias_piece?(rest)
|
||||
defp macro_valid_alias?(_other), do: false
|
||||
|
||||
defp macro_valid_alias_piece?([?., char | rest]) when char >= ?A and char <= ?Z,
|
||||
do: macro_valid_alias_piece?(macro_trim_leading_while_valid_identifier(rest))
|
||||
|
||||
defp macro_valid_alias_piece?([]), do: true
|
||||
defp macro_valid_alias_piece?(_other), do: false
|
||||
|
||||
defp macro_trim_leading_while_valid_identifier([char | rest])
|
||||
when char >= ?a and char <= ?z
|
||||
when char >= ?A and char <= ?Z
|
||||
when char >= ?0 and char <= ?9
|
||||
when char == ?_ do
|
||||
macro_trim_leading_while_valid_identifier(rest)
|
||||
end
|
||||
|
||||
defp macro_trim_leading_while_valid_identifier(other) do
|
||||
other
|
||||
end
|
||||
end
|
||||
|
|
|
@ -112,6 +112,13 @@ defmodule Livebook.IntellisenseTest do
|
|||
assert lists_item in Intellisense.get_completion_items(" :", binding, env)
|
||||
end
|
||||
|
||||
@tag :erl_docs
|
||||
test "Erlang completion doesn't include quoted atoms" do
|
||||
{binding, env} = eval(do: nil)
|
||||
|
||||
assert [] = Intellisense.get_completion_items(~s{:Elixir}, binding, env)
|
||||
end
|
||||
|
||||
@tag :erl_docs
|
||||
test "Erlang module completion with 'in' operator in spec" do
|
||||
{binding, env} = eval(do: nil)
|
||||
|
@ -589,21 +596,21 @@ defmodule Livebook.IntellisenseTest do
|
|||
label: "bar_1",
|
||||
kind: :field,
|
||||
detail: "field",
|
||||
documentation: ~s{```\n~r/pattern/\n```},
|
||||
documentation: nil,
|
||||
insert_text: "bar_1"
|
||||
},
|
||||
%{
|
||||
label: "bar_2",
|
||||
kind: :field,
|
||||
detail: "field",
|
||||
documentation: ~s{```\ntrue\n```},
|
||||
documentation: nil,
|
||||
insert_text: "bar_2"
|
||||
},
|
||||
%{
|
||||
label: "foo",
|
||||
kind: :field,
|
||||
detail: "field",
|
||||
documentation: ~s{```\n1\n```},
|
||||
documentation: nil,
|
||||
insert_text: "foo"
|
||||
}
|
||||
] = Intellisense.get_completion_items("map.", binding, env)
|
||||
|
@ -613,7 +620,7 @@ defmodule Livebook.IntellisenseTest do
|
|||
label: "foo",
|
||||
kind: :field,
|
||||
detail: "field",
|
||||
documentation: ~s{```\n1\n```},
|
||||
documentation: nil,
|
||||
insert_text: "foo"
|
||||
}
|
||||
] = Intellisense.get_completion_items("map.f", binding, env)
|
||||
|
@ -639,18 +646,7 @@ defmodule Livebook.IntellisenseTest do
|
|||
label: "nested",
|
||||
kind: :field,
|
||||
detail: "field",
|
||||
documentation: """
|
||||
```
|
||||
%{
|
||||
deeply: %{
|
||||
bar_1: 23,
|
||||
bar_2: 14,
|
||||
foo: 1,
|
||||
mod: System
|
||||
}
|
||||
}
|
||||
```\
|
||||
""",
|
||||
documentation: nil,
|
||||
insert_text: "nested"
|
||||
}
|
||||
] = Intellisense.get_completion_items("map.nest", binding, env)
|
||||
|
@ -660,7 +656,7 @@ defmodule Livebook.IntellisenseTest do
|
|||
label: "foo",
|
||||
kind: :field,
|
||||
detail: "field",
|
||||
documentation: ~s{```\n1\n```},
|
||||
documentation: nil,
|
||||
insert_text: "foo"
|
||||
}
|
||||
] = Intellisense.get_completion_items("map.nested.deeply.f", binding, env)
|
||||
|
@ -787,7 +783,7 @@ defmodule Livebook.IntellisenseTest do
|
|||
label: "numbats",
|
||||
kind: :variable,
|
||||
detail: "variable",
|
||||
documentation: ~s{```\n["numbat", "numbat"]\n```},
|
||||
documentation: nil,
|
||||
insert_text: "numbats"
|
||||
}
|
||||
] = Intellisense.get_completion_items("numba", binding, env)
|
||||
|
@ -797,14 +793,14 @@ defmodule Livebook.IntellisenseTest do
|
|||
label: "numbats",
|
||||
kind: :variable,
|
||||
detail: "variable",
|
||||
documentation: ~s{```\n["numbat", "numbat"]\n```},
|
||||
documentation: nil,
|
||||
insert_text: "numbats"
|
||||
},
|
||||
%{
|
||||
label: "number",
|
||||
kind: :variable,
|
||||
detail: "variable",
|
||||
documentation: ~s{```\n3\n```},
|
||||
documentation: nil,
|
||||
insert_text: "number"
|
||||
}
|
||||
] = Intellisense.get_completion_items("num", binding, env)
|
||||
|
@ -814,7 +810,7 @@ defmodule Livebook.IntellisenseTest do
|
|||
label: "nothing",
|
||||
kind: :variable,
|
||||
detail: "variable",
|
||||
documentation: ~s{```\nnil\n```},
|
||||
documentation: nil,
|
||||
insert_text: "nothing"
|
||||
},
|
||||
%{label: "node/0"},
|
||||
|
|
Loading…
Add table
Reference in a new issue