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

Use the vendored parser to drive autocomplete. #388

Merged
merged 135 commits into from
Apr 23, 2022
Merged

Conversation

cristianoc
Copy link
Collaborator

@cristianoc cristianoc commented Apr 9, 2022

The vendored parser has a recovery mechanism where parsing continues past an error. This makes it suitable to support autocomplete, which is triggered on incomplete code which would normally not parse.
This replaces the previous hand-crafted mini-parser used specifically for autocomplete, which would start from the cursor position, and try to parse backwards figuring out the context the cursor happens to be in.

The new mechanism starts from the current position and the parse tree produced by the parser. For example, List. gets parsed as List._ where the dummy identifier _ is inserted by the recovery mechanism.
If the cursor position is immediately after ., the mechanism finds the relevant node in the parse tree which represents expression List._, and uses that information for autocomplete.

One of the benefits of this new approach is that relying on the actual parser gives a better handling of corner cases (e.g. support for template literals inside strings comes for free), and avoids the maintenance burden of supporting/extending the ad-hoc parser.
Another benefit is that the parser provides contextual information, which can be used to decide whether e.g. the current context is a value context or type context, or variant context, or field name context. So that let x = List.m will complete values from List, while let f : Js.Promise. will complete types from module Js.Promise.

First step: find the parsetree expression for the item to be completed.
<div x=Outer.Inner. name="" />

parses as x=Outer.Inner.name
Sometimes "Foo. " is followed by "bar" and the parser's behaviour is to parse as "Foo.bar".
This gets back the intended path "Foo."
Complete with anything in scope including open modules and pervasives.
When completing `x=`, if the following contains `name=...`, then the parser interprets it as `x=name`.

Now detect that the cursor is after the  label `x` but before `name`, and don;t interpret the situation as label completion.
Use symbol "_" like in other places in the parser.
cristianoc added a commit to rescript-lang/syntax that referenced this pull request Apr 22, 2022
More fine grained error recovery from parsing longidents.
E.g. Foo. gives Foo._ instead of a default expression which erases info on what's parser already.

From: rescript-lang/rescript-vscode#388
cristianoc added a commit to rescript-lang/syntax that referenced this pull request Apr 22, 2022
More fine grained error recovery from parsing longidents.
E.g. Foo. gives Foo._ instead of a default expression which erases info on what's parser already.

From: rescript-lang/rescript-vscode#388
cristianoc added a commit to rescript-lang/syntax that referenced this pull request Apr 22, 2022
More fine grained error recovery from parsing longidents.
E.g. Foo. gives Foo._ instead of a default expression which erases info on what's parser already.

From: rescript-lang/rescript-vscode#388
@cristianoc cristianoc merged commit cd065b4 into master Apr 23, 2022
@cristianoc cristianoc deleted the autocomplete branch April 23, 2022 06:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant