Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove keywords from completions #259

Merged
merged 5 commits into from
May 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Improvements:
- Vendor Jason library to prevent conflicts with user's code (thanks [Jason Axelson](https://github.com/axelson)) [#253](https://github.com/elixir-lsp/elixir-ls/pull/253)
- Switch to new supervisor format (thanks [Jason Axelson](https://github.com/axelson)) [#260](https://github.com/elixir-lsp/elixir-ls/pull/260)

Changes:
- No longer always return a static list of keywords for completion (thanks [Jason Axelson](https://github.com/axelson)) [#259](https://github.com/elixir-lsp/elixir-ls/pull/259)

Bug Fixes:
- Formatting was returning invalid floating point number (thanks [Thanabodee Charoenpiriyakij](https://github.com/wingyplus)) [#250](https://github.com/elixir-lsp/elixir-ls/pull/250)

Expand Down
44 changes: 12 additions & 32 deletions apps/language_server/lib/language_server/providers/completion.ex
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
"ExUnit.Assertions"
])

@keywords %{
"end" => "end",
"do" => "do\n\t$0\nend",
"true" => "true",
"false" => "false",
"nil" => "nil",
"when" => "when",
"else" => "else\n\t$0",
"rescue" => "rescue\n\t$0",
"catch" => "catch\n\t$0",
"after" => "after\n\t$0"
}

def trigger_characters do
# VS Code's 24x7 autocompletion triggers automatically on alphanumeric characters. We add these
# for "SomeModule." calls and @module_attrs
Expand Down Expand Up @@ -137,7 +124,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
ElixirSense.suggestions(text, line + 1, character + 1)
|> Enum.map(&from_completion_item(&1, context, options))
|> Enum.concat(module_attr_snippets(context))
|> Enum.concat(keyword_completions(context))

items_json =
items
Expand All @@ -146,11 +132,22 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do
|> sort_items()
|> items_to_json(options)

{:ok, %{"isIncomplete" => false, "items" => items_json}}
{:ok, %{"isIncomplete" => is_incomplete(items_json), "items" => items_json}}
end

## Helpers

defp is_incomplete(items) do
if Enum.empty?(items) do
false
else
# By returning isIncomplete = true we tell the client that it should
# always fetch more results, this lets us control the ordering of
# completions accurately
true
end
end

defp from_completion_item(
%{type: :attribute, name: name},
%{
Expand Down Expand Up @@ -555,23 +552,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do

defp module_attr_snippets(_), do: []

# These aren't really useful, to be honest, and it interferes with the auto-indentation
# for "else", but better to show them even if there's no good reason to use them
defp keyword_completions(%{prefix: prefix}) do
@keywords
|> Enum.filter(fn {keyword, _} -> String.starts_with?(keyword, prefix) end)
|> Enum.map(fn {keyword, snippet} ->
%__MODULE__{
label: keyword,
kind: :keyword,
detail: "keyword",
insert_text: snippet,
tags: [],
priority: 1
}
end)
end

defp function_completion(info, context, options) do
%{
type: type,
Expand Down
23 changes: 22 additions & 1 deletion apps/language_server/test/providers/completion_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,33 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do

{line, char} = {4, 14}
TestUtils.assert_has_cursor_char(text, line, char)
{:ok, %{"items" => items}} = Completion.completion(text, line, char, @supports)
{:ok, result} = Completion.completion(text, line, char, @supports)

assert result["isIncomplete"] == true
items = result["items"]

assert ["__struct__", "other", "some"] ==
items |> Enum.filter(&(&1["kind"] == 5)) |> Enum.map(& &1["label"]) |> Enum.sort()

assert (items |> hd)["detail"] == "MyModule struct field"
end

test "isIncomplete is false when there are no results" do
text = """
defmodule MyModule do
defstruct [some: nil, other: 1]

def dummy_function() do
# ^
end
"""

{line, char} = {3, 25}
TestUtils.assert_has_cursor_char(text, line, char)

{:ok, result} = Completion.completion(text, line, char, @supports)
assert result["isIncomplete"] == false
assert result["items"] == []
end
end
end
4 changes: 2 additions & 2 deletions apps/language_server/test/server_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do
resp = assert_receive(%{"id" => 1}, 1000)

assert response(1, %{
"isIncomplete" => false,
"isIncomplete" => true,
"items" => [
%{
"detail" => "behaviour",
Expand Down Expand Up @@ -403,7 +403,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do
resp = assert_receive(%{"id" => 3}, 5000)

assert response(3, %{
"isIncomplete" => false,
"isIncomplete" => true,
"items" => [
%{
"detail" => "module",
Expand Down