Skip to content

Improve enclosing ("Selection Range" in the LSP jargon) - #2121

Open
panglesd wants to merge 14 commits into
ocaml:mainfrom
panglesd:improve-selection-range
Open

panglesd wants to merge 14 commits into
ocaml:mainfrom
panglesd:improve-selection-range

Conversation

@panglesd

@panglesd panglesd commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Made with @PizieDust.

Drastically improve the enclosing request.

Going down-right

It used to follow exactly the Mbrowse.node hierarchy. But we don't always want to select "whole nodes", as for instance in:

let () =
  let x = 1 in
  let y = 1 in
  let z = 1 in
  let t = 1 in
  x, y, z, t

we don't want to go from

let () =
  let x = [1] in
  let y = 1 in
  let z = 1 in
  let t = 1 in
  x, y, z, t

to:

let () =
  [let x = 1 in
  let y = 1 in
  let z = 1 in
  let t = 1 in
  x, y, z, t]

although this is the parent expression. It would be downright bad!

Instead, the new implementation goes "down-right" on expression nodes when it comes from the left:

let () =
  [let x = 1 in]
  let y = 1 in
  let z = 1 in
  let t = 1 in
  x, y, z, t

then

let () =
  [let x = 1 in
  let y = 1 in]
  let z = 1 in
  let t = 1 in
  x, y, z, t

then

let () =
  [let x = 1 in
  let y = 1 in
  let z = 1 in]
  let t = 1 in
  x, y, z, t

...

And I say down-right, because the (virtual) AST looks like that:

downright

Better locations

This PR improves locations by adding a merlin loc to sequences (expr1 ; expr2). It is also careful with which kind of locations to consider.

Care for constraints

The following expression ((((x : int) : int) : int) : int) is a single expression node... the constraints (and their location) being in the exp_extra field of the expression
This PR makes different enclosing for each layer.

Conclusion

I can clean the history, but it should be ok to review it all at once (not commit by commit) since we went in several wrong directions, but at then end it is not too big.

🎸

@panglesd
panglesd force-pushed the improve-selection-range branch from e31d8b0 to d3a9d49 Compare September 7, 2026 16:13
@panglesd

panglesd commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator Author

There is an issue with begin ... end and ( ... ) as in the typedtree, apart from locations, there is no distinction between:

let () = 
  f ();
  ( f ();
    f () )

and

let () = 
  f ();
  f ();
  f ()

As a consequence, we might include ( without the closing one, eg as in:

let () = 
  [f ();
  ( f ();]
    f () )

I'll investigate, but I'm not sure how accessible those locations are... I would say this PR is already mergeable as is. I'll include the problem as a FIXME in the test.

@panglesd
panglesd force-pushed the improve-selection-range branch 4 times, most recently from dcb4244 to c29d2a5 Compare September 9, 2026 06:00
panglesd added a commit to panglesd/merlin that referenced this pull request Sep 9, 2026
panglesd added a commit to panglesd/merlin that referenced this pull request Sep 9, 2026
@panglesd
panglesd force-pushed the improve-selection-range branch from f08b060 to 4105532 Compare September 9, 2026 06:14
panglesd added a commit to panglesd/merlin that referenced this pull request Sep 9, 2026
@panglesd
panglesd force-pushed the improve-selection-range branch from 4105532 to edc9668 Compare September 9, 2026 06:24
panglesd added a commit to panglesd/merlin that referenced this pull request Sep 9, 2026
@panglesd
panglesd force-pushed the improve-selection-range branch from edc9668 to b1aaaf1 Compare September 9, 2026 06:30
panglesd added a commit to panglesd/merlin that referenced this pull request Sep 9, 2026
@panglesd
panglesd force-pushed the improve-selection-range branch from b1aaaf1 to d2d15e3 Compare September 9, 2026 06:31
@panglesd

panglesd commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

I've reworked the history to make it easier to review, since the last commits introduced a few "special cases".

The first commit is the core of the rewrite of enclosing.ml. It is hopefully relatively generic and easy to review. The commit also contains many tests, some of which are FIXMEs, mainly due to corner cases in the locations:

  • Sequences are missing their merlin_loc
  • Parenthesized expression/pattern/coretype only have their parenthesized location

The next commits fix those FIXME one by one, and each of them is fairly small.

panglesd and others added 10 commits September 9, 2026 08:53
Allow incomplete node to be selected. This is the base implementation, there are
several corner cases that are left as FIXME in the test and are going to be
fixed in the next commits.

The idea is still "going up nodes from the cursor". However, this time we can
also go "down right" to select a node in several step. For instance, we don't go from:

```ocaml
let x = [1] in
let y = 1 in
x + y
```
to the parent node:
```ocaml
[let x = 1 in
let y = 1 in
x + y]
```
Instead, we include "intermediate steps for the parent node" by filling it from
left to right:
```ocaml
[let x = 1 in]
let y = 1 in
x + y
```
then
```ocaml
[let x = 1 in
let y = 1 in]
x + y
```
and finally
```ocaml
[let x = 1 in
let y = 1 in
x + y]
```

Co-authored-by: PizieDust <[email protected]>
Instead of starting from scratch
Require adding some attributes since the loc information was gone.
They are non-splittable because they are nested in a `begin ... end` or
parenthesis.
@panglesd
panglesd force-pushed the improve-selection-range branch from 276a47d to 7cca587 Compare September 9, 2026 06:54
@panglesd

panglesd commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

CI is green, this is ready for review!

@panglesd

panglesd commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

For the last 4 commits: I made an AI review, added the relevant findings as tests, and fixed them.

@PizieDust

Copy link
Copy Markdown
Contributor

Thanks @panglesd
I tested it and everything seems to work well. Thank you for the tests.

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.

2 participants