mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-10-09 04:57:18 +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 include_in_completion?(_), do: true
|
||||||
|
|
||||||
defp format_completion_item({:variable, name, value}),
|
defp format_completion_item({:variable, name, _value}),
|
||||||
do: %{
|
do: %{
|
||||||
label: name,
|
label: name,
|
||||||
kind: :variable,
|
kind: :variable,
|
||||||
detail: "variable",
|
detail: "variable",
|
||||||
documentation: value_snippet(value, @line_length),
|
documentation: nil,
|
||||||
insert_text: name
|
insert_text: name
|
||||||
}
|
}
|
||||||
|
|
||||||
defp format_completion_item({:map_field, name, value}),
|
defp format_completion_item({:map_field, name, _value}),
|
||||||
do: %{
|
do: %{
|
||||||
label: name,
|
label: name,
|
||||||
kind: :field,
|
kind: :field,
|
||||||
detail: "field",
|
detail: "field",
|
||||||
documentation: value_snippet(value, @line_length),
|
documentation: nil,
|
||||||
insert_text: name
|
insert_text: name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,18 +336,9 @@ defmodule Livebook.Intellisense do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp format_details_item({:variable, name, value}) do
|
defp format_details_item({:variable, name, _value}), do: code(name)
|
||||||
join_with_divider([
|
|
||||||
code(name),
|
|
||||||
value_snippet(value, @extended_line_length)
|
|
||||||
])
|
|
||||||
end
|
|
||||||
|
|
||||||
defp format_details_item({:map_field, _name, value}) do
|
defp format_details_item({:map_field, name, _value}), do: code(name)
|
||||||
join_with_divider([
|
|
||||||
value_snippet(value, @extended_line_length)
|
|
||||||
])
|
|
||||||
end
|
|
||||||
|
|
||||||
defp format_details_item({:module, _module, display_name, documentation}) do
|
defp format_details_item({:module, _module, display_name, documentation}) do
|
||||||
join_with_divider([
|
join_with_divider([
|
||||||
|
@ -403,14 +394,6 @@ defmodule Livebook.Intellisense do
|
||||||
"""
|
"""
|
||||||
end
|
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([], _module), do: nil
|
||||||
|
|
||||||
defp format_signatures(signatures, module) do
|
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 valid_alias_rest?(rest), do: valid_alias_piece?(rest)
|
||||||
|
|
||||||
defp usable_as_unquoted_module?(mod) do
|
defp usable_as_unquoted_module?(mod) do
|
||||||
Code.Identifier.classify(mod) != :other
|
macro_classify_atom(mod) in [:identifier, :unquoted]
|
||||||
end
|
end
|
||||||
|
|
||||||
defp get_matching_modules(hint, ctx) do
|
defp get_matching_modules(hint, ctx) do
|
||||||
|
@ -484,4 +484,70 @@ defmodule Livebook.Intellisense.IdentifierMatcher do
|
||||||
ctx.matcher.(name, hint),
|
ctx.matcher.(name, hint),
|
||||||
do: {:module_attribute, name, {"text/markdown", info.doc}}
|
do: {:module_attribute, name, {"text/markdown", info.doc}}
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -112,6 +112,13 @@ defmodule Livebook.IntellisenseTest do
|
||||||
assert lists_item in Intellisense.get_completion_items(" :", binding, env)
|
assert lists_item in Intellisense.get_completion_items(" :", binding, env)
|
||||||
end
|
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
|
@tag :erl_docs
|
||||||
test "Erlang module completion with 'in' operator in spec" do
|
test "Erlang module completion with 'in' operator in spec" do
|
||||||
{binding, env} = eval(do: nil)
|
{binding, env} = eval(do: nil)
|
||||||
|
@ -589,21 +596,21 @@ defmodule Livebook.IntellisenseTest do
|
||||||
label: "bar_1",
|
label: "bar_1",
|
||||||
kind: :field,
|
kind: :field,
|
||||||
detail: "field",
|
detail: "field",
|
||||||
documentation: ~s{```\n~r/pattern/\n```},
|
documentation: nil,
|
||||||
insert_text: "bar_1"
|
insert_text: "bar_1"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
label: "bar_2",
|
label: "bar_2",
|
||||||
kind: :field,
|
kind: :field,
|
||||||
detail: "field",
|
detail: "field",
|
||||||
documentation: ~s{```\ntrue\n```},
|
documentation: nil,
|
||||||
insert_text: "bar_2"
|
insert_text: "bar_2"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
label: "foo",
|
label: "foo",
|
||||||
kind: :field,
|
kind: :field,
|
||||||
detail: "field",
|
detail: "field",
|
||||||
documentation: ~s{```\n1\n```},
|
documentation: nil,
|
||||||
insert_text: "foo"
|
insert_text: "foo"
|
||||||
}
|
}
|
||||||
] = Intellisense.get_completion_items("map.", binding, env)
|
] = Intellisense.get_completion_items("map.", binding, env)
|
||||||
|
@ -613,7 +620,7 @@ defmodule Livebook.IntellisenseTest do
|
||||||
label: "foo",
|
label: "foo",
|
||||||
kind: :field,
|
kind: :field,
|
||||||
detail: "field",
|
detail: "field",
|
||||||
documentation: ~s{```\n1\n```},
|
documentation: nil,
|
||||||
insert_text: "foo"
|
insert_text: "foo"
|
||||||
}
|
}
|
||||||
] = Intellisense.get_completion_items("map.f", binding, env)
|
] = Intellisense.get_completion_items("map.f", binding, env)
|
||||||
|
@ -639,18 +646,7 @@ defmodule Livebook.IntellisenseTest do
|
||||||
label: "nested",
|
label: "nested",
|
||||||
kind: :field,
|
kind: :field,
|
||||||
detail: "field",
|
detail: "field",
|
||||||
documentation: """
|
documentation: nil,
|
||||||
```
|
|
||||||
%{
|
|
||||||
deeply: %{
|
|
||||||
bar_1: 23,
|
|
||||||
bar_2: 14,
|
|
||||||
foo: 1,
|
|
||||||
mod: System
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```\
|
|
||||||
""",
|
|
||||||
insert_text: "nested"
|
insert_text: "nested"
|
||||||
}
|
}
|
||||||
] = Intellisense.get_completion_items("map.nest", binding, env)
|
] = Intellisense.get_completion_items("map.nest", binding, env)
|
||||||
|
@ -660,7 +656,7 @@ defmodule Livebook.IntellisenseTest do
|
||||||
label: "foo",
|
label: "foo",
|
||||||
kind: :field,
|
kind: :field,
|
||||||
detail: "field",
|
detail: "field",
|
||||||
documentation: ~s{```\n1\n```},
|
documentation: nil,
|
||||||
insert_text: "foo"
|
insert_text: "foo"
|
||||||
}
|
}
|
||||||
] = Intellisense.get_completion_items("map.nested.deeply.f", binding, env)
|
] = Intellisense.get_completion_items("map.nested.deeply.f", binding, env)
|
||||||
|
@ -787,7 +783,7 @@ defmodule Livebook.IntellisenseTest do
|
||||||
label: "numbats",
|
label: "numbats",
|
||||||
kind: :variable,
|
kind: :variable,
|
||||||
detail: "variable",
|
detail: "variable",
|
||||||
documentation: ~s{```\n["numbat", "numbat"]\n```},
|
documentation: nil,
|
||||||
insert_text: "numbats"
|
insert_text: "numbats"
|
||||||
}
|
}
|
||||||
] = Intellisense.get_completion_items("numba", binding, env)
|
] = Intellisense.get_completion_items("numba", binding, env)
|
||||||
|
@ -797,14 +793,14 @@ defmodule Livebook.IntellisenseTest do
|
||||||
label: "numbats",
|
label: "numbats",
|
||||||
kind: :variable,
|
kind: :variable,
|
||||||
detail: "variable",
|
detail: "variable",
|
||||||
documentation: ~s{```\n["numbat", "numbat"]\n```},
|
documentation: nil,
|
||||||
insert_text: "numbats"
|
insert_text: "numbats"
|
||||||
},
|
},
|
||||||
%{
|
%{
|
||||||
label: "number",
|
label: "number",
|
||||||
kind: :variable,
|
kind: :variable,
|
||||||
detail: "variable",
|
detail: "variable",
|
||||||
documentation: ~s{```\n3\n```},
|
documentation: nil,
|
||||||
insert_text: "number"
|
insert_text: "number"
|
||||||
}
|
}
|
||||||
] = Intellisense.get_completion_items("num", binding, env)
|
] = Intellisense.get_completion_items("num", binding, env)
|
||||||
|
@ -814,7 +810,7 @@ defmodule Livebook.IntellisenseTest do
|
||||||
label: "nothing",
|
label: "nothing",
|
||||||
kind: :variable,
|
kind: :variable,
|
||||||
detail: "variable",
|
detail: "variable",
|
||||||
documentation: ~s{```\nnil\n```},
|
documentation: nil,
|
||||||
insert_text: "nothing"
|
insert_text: "nothing"
|
||||||
},
|
},
|
||||||
%{label: "node/0"},
|
%{label: "node/0"},
|
||||||
|
|
Loading…
Add table
Reference in a new issue