-
Notifications
You must be signed in to change notification settings - Fork 41
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
New suggestions engine #99
Conversation
One thing a forgot to mention is that the new approach not only makes it adding new suggestions a breeze (we just need to add a new reducer), but it also opens opportunities for optimizations. The last argument of a reducer, the |
def func(%MyServer{} = some_arg) do | ||
%MyServer{so | ||
end | ||
end | ||
""" | ||
|
||
list = ElixirSense.suggestions(buffer, 8, 17) | ||
list = ElixirSense.suggestions(buffer, 12, 17) | ||
|
||
assert list == [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't some_func/0
be inluded here? Consider code like
var = %{DateTime.now | seconds: 0}
{:halt, %{acc | result: fields}} | ||
|
||
{fields, :maybe_struct_update} -> | ||
{:cont, %{acc | result: fields, reducers: [:populate_common, :variables]}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO attributes and functions should be included here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good catch. Although is more common to see the update syntax being used with variables, functions and attributes are valid suggestions. I'll update it.
Nice @msaraiva. I was thinking about doing a similar refactoring some day. I left some small comments in the code. One particular improvement I would like to introduce later is providing more scope context so typespec suggestions show only inside |
@lukaszsamson regarding:
do you think we should remove it? |
I'd rather leave it. We don't filter other hidden APIs and this one is officially documented. I personally happen to use it now and then. Anyway, there was a plan to mark hidden stuff in metadata and deprioretize such suggestions in elixir-ls. |
We might be able to handle Opened elixir-lsp/elixir-ls#259 to test removing the static keyword list. But since that list was previously always being added to completions I think it is safe to remove. |
I also used the Anyway, I have no problem leaving it and I have the same feeling regarding hidden functions like If we had a configuration for that (which is probably not worth it), I would not include any of those Maybe just deprioritizing them is the best default. |
@lukaszsamson I think we're good to go here. As soon as we start updating existing reducers and adding new ones, we'll get more insights about the direction we should take. I think the most important thing here was to split the implementation in individual reducers and centralize the main logic. From now on, any change we need will be much easier to implement. |
* Remove keywords from completions They were being returned regardless of context which made them very noisy. Related: * elixir-lsp/elixir_sense#99 * #251 * Add changelog entry * Return isIncomplete = true for completions * Fix tests and add a couple.
Closes #98.
This PR changes the logic to provide suggestions by splitting each individual type of suggestion into its own reducer. The main algorithm was simplified a lot and reduced to a single
Enum.reduce_while/3
that traverses the list of reducers as you can see here:elixir_sense/lib/elixir_sense/providers/suggestion.ex
Lines 82 to 95 in 013f490
The new approach removes a lot of the conditionals that was necessary and allows each reducer to make decisions about how the final list of suggestions should look like based on the information they have about the context. Here's an example:
The list of suggestions provided inside a literal struct can be one of:
Currently, it works like this:
The list of keywords suggested do not apply here, so they just add noise. This is one of many cases where they show up and that's why I'm suggesting to remove them in elixir-lsp/elixir-ls#251. So let's remove them and see how it goes:
We still have a bunch of other suggestions that don't apply here either.
With this PR, there's now a way to easily restrict the list of suggestions based on the context. For our example, the
Struct.add_fields/5
reducer can change the final list in 3 different ways:The code:
elixir_sense/lib/elixir_sense/providers/suggestion/reducers/struct.ex
Lines 22 to 31 in 013f490
The final result:
Personally, I'd even remove the
__struct__
field since its use is discouraged.The above improvement was already included in this PR. Another similar improvement is regarding the list of callbacks.
Before:
After:
The code:
elixir_sense/lib/elixir_sense/providers/suggestion/reducers/callbacks.ex
Lines 61 to 70 in 013f490
In both cases, the logic was isolated inside each reducer and there was no need to change the main algorithm.
@lukaszsamson I don't think there's any need to review the whole thing since most of the changes was just about moving each piece of logic to its own reducer, however, if you have the time and can take a look at https://github.com/elixir-lsp/elixir_sense/blob/ms-new-suggestion-engine/lib/elixir_sense/providers/suggestion.ex, you'll find more info about the usage so you can selectively review whatever you find necessary.
Important note: I didn't remove the hint suggestion logic nor touched the
Complete
module. I wanted to minimize the changes in this PR so I'm currently just ignoring it.