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

feat(lsp): Add autocomplete #1900

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

spotandjake
Copy link
Member

@spotandjake spotandjake commented Jul 23, 2023

This pr adds autocomplete to the grain language. I think we may want to expand this in the future. Possibly with a better parser to improve finding the current context of completion. Right now we just treat = as indicating you want value completions and : as indicating you want type completions There are a few issues with this approach though, such as ew do not currently trigger completions 1 + <here> in the position of <here> and other similar cases. we also mistreat type T = as value completions currently, so some more consideration may need to be given on parsing rules. Im opening the pr now though as I am hoping to get feedback on parsing rules here.

Another possible addition would be to try and use the sourceTree to give context, I didnt take this approach as in most cases sourceTree is very far behind where your autocompleting and not very helpful, it would have to be used in addition to the half parser though rather than as an alternative.

Another possible future expansion is adding autocompletes to includes that scan the directory for .gr files and suggest them. I think this could come in a later pr though, maybe after we determine the new include syntax.

Another possible future expansion would be adding snippet completions to keywords. but i feel this can come in a later pr.

This pr replaces: #1262, Thanks to marcus for the initial implementation from that pr.

@spotandjake spotandjake added enhancement lsp Issues related to the language server. labels Jul 23, 2023
@spotandjake spotandjake self-assigned this Jul 23, 2023
Copy link
Member

@marcusroberts marcusroberts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some excellent work here @spotandjake and so fantastic to get this into the LSP!

@ospencer
Copy link
Member

I think we need to go ahead and handle the cases for completion a little better—going ahead and looking for the let ... = for value completions and type ... = for type completions. We can fall back to just = but we should look for the let first.

@spotandjake
Copy link
Member Author

I made that change and improved the way detection is done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we name this file document.re? I don't want to get it confused with doc.re in the formatter.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im a fan of that change

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made that change

Copy link
Member

@ospencer ospencer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty reasonable, but we'll need to do some work on how we find completeable states.

);
};

let supressed_types = [Builtin_types.path_void, Builtin_types.path_bool];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not all builtin types?

Comment on lines 138 to 139
let source =
Str.global_replace(Str.regexp({|\r\n|}), {|\n|}, source_code);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? This is extremely expensive.

Comment on lines 141 to 144
let source_chars =
List.rev(
String_utils.explode(String_utils.slice(~last=offset, source)),
);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really expensive too. I imagine it's cheaper just to check string prefixes directly.

root_decl: Types.module_declaration,
path: list(string),
) => {
// Get The Modules Exports
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Get The Modules Exports
// Get the module's exports

Some(build_type_completion(~env, (ident.name, decl)))
| TSigModule(ident, decl, _) =>
Some(build_module_completion(~env, (ident.name, decl)))
// Dissabled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Dissabled
// Disabled

// Find The Top Level Modules
let completions =
switch (search) {
// User Wrote Nothing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// User Wrote Nothing
// User wrote nothing

switch (search) {
// User Wrote Nothing
| []
// User Wrote A Single Word, i.e Top Level Search
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// User Wrote A Single Word, i.e Top Level Search
// User wrote a single word, i.e top-level search

| []
// User Wrote A Single Word, i.e Top Level Search
| [_] => completions
// User Wrote A Path
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// User Wrote A Path
// User wrote a path

| [_] => completions
// User Wrote A Path
| [search, ...path] =>
// Find Module Root
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Find Module Root
// Find module root

}
};
// Remove Operators
let operators = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would also be good to have this at the top level.

@spotandjake
Copy link
Member Author

@ospencer if you get a chance would you be willing to review the new implementation. It needs more work before its good so im going to convert this to a draft.

@spotandjake spotandjake marked this pull request as draft February 27, 2024 23:33
Copy link
Member

@ospencer ospencer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general the new approach seems really smart!

@spotandjake
Copy link
Member Author

mentioned in the grain meeting, but if anyone wants to take over this pr feel free ive gotten a little burnt out from it,My current approach was to run the lexer and get the lexing token and then try to recover the current state from the cursor to get some context for what were working on from there I was using the cached program to get varaibles and stuff this could be combined with sourcetree to get additonal information such as some program scope.

Things I was considering: I was trying to leave room in my implementation so that we could look into recovering some parse state from the parser in the future this could be combined with the lexing approach to get a more accurate state of whats going on, addittionally I was trying to make sure adding new states didnt require touching the parsing logic instead it just required defining the state, handling the parsing seperatly from our completion states also would let us fall back to a simple parser like what reasonml does in their autocomplete engine for cases where we lose complete context.

If anyone decides to take this up feel free to send me a message here or on discord and I give a better explanation of the technique I was trying to use if needed.

@spotandjake spotandjake removed their assignment Oct 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement lsp Issues related to the language server.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants