Skip to content

Add locate_type_multi query - #1951

Merged
voodoos merged 5 commits into
ocaml:mainfrom
liam923:locate-type-multi
Oct 3, 2025
Merged

voodoos merged 5 commits into
ocaml:mainfrom
liam923:locate-type-multi

Conversation

@liam923

@liam923 liam923 commented Jul 22, 2025

Copy link
Copy Markdown
Contributor

This PR adds a new command, locate-type-multi, that we plan to use at Jane Street for some new VSCode functionality.

A useful current command in VSCode is "Go to Type Definition", which uses the locate-type query to go to the definition of the type of the identifier under the cursor. However, this command is rather limited - it only works on Tconstrs, and when the Tconstr carries arguments, it just ignores the args. In other words, the command doesn't provide the ability to go to a's defintion if the type is any of the following: a t, (a * _), a -> _, _ -> a.

locate-type-multi, instead of always just returning the location of a single identifier, returns a tree structure that represents all the identifiers within a type. So for example, if the type is a -> (b * c), it returns the locations of all of a, b, and c, and this is in a tree-like data structure that makes it easy for VSCode to present this to the user.

Comment thread src/frontend/kernel/dune Outdated
Comment on lines +1 to +5
(library
(name query_protocol_kernel)
(public_name merlin-lib.query_protocol_kernel)
(libraries yojson)
(preprocess (pps ppx_yojson_conv)))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I created this new directory to put useful definitions that are compatible with js_of_ocaml. This is useful for us internally so that a VSCode extension (which is compiled with js_of_ocaml) can depend on the definitions in this directory. Unfortunately query_protocol.ml itself can't be compiled with js_of_ocaml naively due to some of its dependencies.

@xvw

xvw commented Jul 22, 2025

Copy link
Copy Markdown
Member

Oh! That's a great feature!
However, I have a few reservations before embarking on a full review:

  • I'm not at all convinced by the name and wonder if locate-types wouldn't be... better?
  • Currently, Merlin does not depend on Yojson and does not rely on any drifters, and I feel that the current Json model is more than sufficient to avoid including these two somewhat resource-intensive dependencies. What do you think?

@liam923

liam923 commented Jul 22, 2025

Copy link
Copy Markdown
Contributor Author

Wow thanks for the quick resposne!

I'm not at all convinced by the name and wonder if locate-types wouldn't be... better?

Sold, I'll change it.

Currently, Merlin does not depend on Yojson and does not rely on any drifters, and I feel that the current Json model is more than sufficient to avoid including these two somewhat resource-intensive dependencies. What do you think?

I don't think this is true. merlin-lib doesn't currently depend on yojson, but merlin does - the cli uses it to serialize and deserialize json. And the LSP, which to my knowledge is the only user of merlin-lib, also depends on yojson (and ppx_yojson_conv). So I think the only real effect will be making users who use ocamlmerlin directly (which I think is vim and emacs users??) install ppx_yojson_conv. This seems fine to me.

@xvw

xvw commented Jul 22, 2025

Copy link
Copy Markdown
Member

I don't think this is true. merlin-lib doesn't currently depend on yojson, but merlin does - the cli uses it to serialize and deserialize json. And the LSP, which to my knowledge is the only user of merlin-lib, also depends on yojson (and ppx_yojson_conv). So I think the only real effect will be making users who use ocamlmerlin directly (which I think is vim and emacs users??) install ppx_yojson_conv. This seems fine to me.

I generally agree with the analysis, but:

  • I'm not sure I understand what Yojson brings to merlin-lib in this context. I don't really see what it adds that Json doesn't, whose purpose is essentially to describe data. (But I haven't started my review seriously yet, so I may be missing something.)

  • Depending on a ppx in merlin-lib seems potentially laborious to me, as it means depending on a dependency that may change with each OCaml version upgrade. This means that, in order to anticipate Merlin version upgrades (preview releases), we have to wait for ppxlib upgrades (cc @pitag-ha).

However, my goal is absolutely not to categorically block a (useful) patch, but I think that the cost involved in using the Json module (in the right place) and writing our serialisation functions is fairly low. Don't you agree?

@liam923

liam923 commented Jul 22, 2025

Copy link
Copy Markdown
Contributor Author

Regarding the first point, adding yojson as a dependency to merlin-lib is purely driven by adding ppx_yojson_conv as a dependency. All uses of yojson are in ppx_yojson_conv derived code.

Regarding the second, this is something that I hadn't considered so thanks for bringing it up. If relying on a ppx indeed has that implication, I agree this isn't worth it. But I'm mildly surprised that this is an issue. I don't have much context about how OCaml version upgrades are handled, but I would expect the Merlin for the new version to be able to be compiled with the old version, (for example, OxCaml Merlin is currently compiled with 5.2.0) in which case bumping the version used to compile Merlin could simply wait until ppx_yojson_conv is ready. Is this wrong or difficult for a reason I don't understand?

Comment on lines +3 to +11
module Type_tree = struct
type node_data =
| Arrow
| Tuple
| Object
| Type_ref of { path : Path.t; ty : Types.type_expr }

type t = { data : node_data; children : t list }
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe it is related to VSCode but I am not see the point of splitting repr into two types? (Maybe because I do not see cases when we have children in Type_ref?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh I see, in case of type parameters, in (t, k) r:

  • r is the type
  • t and k are children?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes exactly

@liam923

liam923 commented Jul 22, 2025

Copy link
Copy Markdown
Contributor Author

I should also mention that I intend to open a follow-up PR that adds ppx_jane as a dependency. So we may as well hash that out while discussing ppx_yojson_conv.

@sidkshatriya

sidkshatriya commented Jul 23, 2025

Copy link
Copy Markdown
Contributor

Thanks for working on locating multiple (related) type definitions. This is hugely needed in ocamllsp.

Before discussing the approach for OCaml I want to compare with rust-analyzer:

Let's say you have a type in Rust: Sender<EditorResponse> and this snippet of code:

let response : Sender<EditorResponse> = ...

Let's say in your editor you try to locate the type definition of response when your cursor is positioned somewhere on the variable response by clicking/using keyboard shortcuts corresponding to LSP request textDocument/typeDefinition

The response of rust-analyzer to the above request is that you are presented with a list of options to navigate to:

  • Navigate to the definition of type Sender
  • Navigate to the definition of type EditorReponse

I have checked and the standard LSP request textDocument/typeDefinition is issued. This is not some custom request. The response from the LSP looks like this:

[
  {
    "uri": "file:///home/abczy/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/crossbeam-channel-0.5.14/src/channel.rs",
    "range": {
      "start": {
        "line": 354,
        "character": 11
      },
      "end": {
        "line": 354,
        "character": 17
      }
    }
  },
  {
    "uri": "file:///home/abcxyz/kakoune-lsp/src/types.rs",
    "range": {
      "start": {
        "line": 326,
        "character": 11
      },
      "end": {
        "line": 326,
        "character": 25
      }
    }
  }
]

i.e. basically the location of the types EditorResponse and Sender.

Question: Why not follow this behavior of rust-analyzer ? Pardon me if my understanding the discussion on this ticket is wrong but if we follow my suggestion:

  • We are just using the standard textDocument/typeDefinition
  • We don't need to have any tree complication. Just return the list of related types

This also means that the reply will be understood by editors other than VSCode (e.g. neovim, kakoune etc.)

So coming back to OCaml.

If you try to navigate to the type of a variable that has the type queue list you should be given the option to navigate to type of queue and list. This can ride on the standard LSP textDocument/typeDefinition request/response schema

@liam923

liam923 commented Jul 23, 2025

Copy link
Copy Markdown
Contributor Author

Thanks for the thoughts @sidkshatriya! I agree that a nice end-goal would be for the standard textDocument/typeDefinition LSP request to utilize this. My motivation for the tree structure rather than a list is because internally at Jane Street we are making using of this. We have a prototype new VSCode feature that utilizes this command, but it's using something ad-hoc to present the list of types rather than textDocument/typeDefinition. This is for two reasons:

  1. The ad-hoc implementation presents the tree structure to the user, which makes the list a little bit easier to read.
  2. We don't yet feel ready to replace the current textDocument/typeDefinition implementation with this new feature. I have low confidence that it works in all cases that we care about, so this allows us to beta test the functionality. Once we gain more confidence, then updating textDocument/typeDefinition would be a a next-step.
    I also don't think there's much of a downside to using this tree structure. It doesn't increase code complexity much, and the LSP can still easily conert it to a list when implementing testDocument/typeDefinition.

@sidkshatriya

Copy link
Copy Markdown
Contributor

@liam923 Thanks for your thoughts !

We don't yet feel ready to replace the current textDocument/typeDefinition implementation with this new feature

It would be cool if you can allow the current textDocument/typeDefinition to return a list also (simply linearize the tree) and then hide this new feature behind an environment variable. There are a lot of people using OCaml with emacs / vim / neovim etc. and it would be great if you can include them in this important feature addition too :-) !

@liam923

liam923 commented Jul 23, 2025

Copy link
Copy Markdown
Contributor Author

@sidkshatriya that seems like a good idea. I think it's outside the scope of this PR though as it would require making changes in https://github.com/ocaml/ocaml-lsp. I also have limited familiarity with the LSP, so I'm not sure I'm the best person to make that change.

@xvw

xvw commented Jul 23, 2025

Copy link
Copy Markdown
Member

I also have limited familiarity with the LSP, so I'm not sure I'm the best person to make that change.

We can do it, at Tarides.

@sidkshatriya

Copy link
Copy Markdown
Contributor

We can do it, at Tarides.

This would be very welcome. A linearized version of this tree output via textDocument/typeDefinition (behind a feature flag / environment variable) would give this feature a lot more testing and visibility

@liam923

liam923 commented Jul 23, 2025

Copy link
Copy Markdown
Contributor Author

I expect a lot of Jane Street users will also be excited about using this toggle.

@pitag-ha

Copy link
Copy Markdown
Member

Sorry for the late answer!

Depending on a ppx in merlin-lib seems potentially laborious to me, as it means depending on a dependency that may change with each OCaml version upgrade. This means that, in order to anticipate Merlin version upgrades (preview releases), we have to wait for ppxlib upgrades (cc @pitag-ha).

A agree. Merlin is installed in almost any opam switch, so we should keep the package restrictions it adds to a switch to a minimum. Depending on a PPX would be the opposite.

@liam923

liam923 commented Jul 25, 2025

Copy link
Copy Markdown
Contributor Author

It's still not clear to me that this will actually affect users much in practice. It will only affect users who a) don't use the lsp and b) don't already have this ppx as a dependency. (a) negates any vscode users, and for (b) ppx_yojson_conv is fairly common, and its (few) dependencies are extremely common. So I suspect most switches will have either no or minimal impact.

Also if I'm wrong about the above and this does impact a large amount of switches, I still think this is acceptable. I don't see why we should treat this much different from the LSP's dependencies, as the LSP has the same use case as Merlin. Maybe I'm wrong, but I'd be surprised if there are many people choosing Merlin over the LSP because Merlin is lighter-weight and not some other reason (ease of setup, etc).

@Octachron

Octachron commented Jul 28, 2025

Copy link
Copy Markdown
Member

Merlin for new version of the compiler is built with the new version of the compiler. Adding a dependency on ppxlib is already not ideal, and I would argue it is not worth the increased depth of the ecosystem bootstrap just to avoid writing a handful of small functions.

Moreover, adding a dependency on a ppx_jane feels like an even worse idea to me, since this adds a dependency on base . Unfortunately, currently the base library does not have a good history of anticipating the update of the compiler in time for new alpha releases of the compiler. Typically, base was only made compatible with Ocaml 5.4.0 at version v17.3 released on the 10th June, while the Merlin-preview for 5.4 was released on the 26th May.

@liam923

liam923 commented Jul 28, 2025

Copy link
Copy Markdown
Contributor Author

I've discussed this with @pitag-ha and @xvw offline and they convinced me the ppxes are a bad idea. I'll update the PR to remove them.

@liam923

liam923 commented Jul 29, 2025

Copy link
Copy Markdown
Contributor Author

I'm taking one more stab at using PPXes because I had an idea that I think will work well. We can make use of [@@deriving_inline ] (here's some relevent docs, although they're a bit limited). Basically, the idea is that dune will inline the ppx-expanded code by correcting the file with the ppx-generated code. Then the ml/mli file can be compiling without depending on the ppx.

For example, if you write:

type t = Foo [@@deriving_inline to_string]
[@@@end]

Dune will correct this to:

type t = Foo [@@deriving_inline to_string]
let to_string _ = "Foo"
[@@@end]

This allows us to add ppx_yojson_conv as a with-test dependency - ie, we only need it while developing. During a version upgrade, we can temporarily remove it from our opam switch and disable the dune rule that runs the ppx.

The only compilation dependency this change now adds is to ppx_yojson_conv_lib. Would this throw a wrench in the public release process? It's small and seems trivial to update for new versions, but I also see that it's a Jane Street maintained library, which I'm afraid might make things more difficult?

Comment thread src/frontend/kernel/dune Outdated
; [@@deriving_inline] gets expanded by the `@lint` dune alias. This makes `@lint` get run
; when we run the `@runtest` alias, which aides development.
(alias
(name runtest)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It would be convenient for this to get run as part of the default alias. But there's two things that give me pause:

  1. I'm not sure if that will make opam try to run the ppx during compilation.
  2. Maybe this is bad practice since ppx_yojson_conv is a with-test dependency, and this would make that a bit of a lie.

Comment thread src/commands/query_json.ml Outdated
("position", mk_position pos)
]
| Locate_type pos -> mk "locate-type" [ ("position", mk_position pos) ]
| Locate_type_multi pos -> mk "locate-types" [ ("position", mk_position pos) ]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

WDYT about using Locate_types instead of Locate_type_multi?

@xvw

xvw commented Aug 20, 2025

Copy link
Copy Markdown
Member

Hi!
The current patch seems to still depends/introduces PPX. Are you plan to remove it?
Thanks in advance!

@liam923

liam923 commented Aug 20, 2025

Copy link
Copy Markdown
Contributor Author

Hi! The current patch seems to still depends/introduces PPX. Are you plan to remove it? Thanks in advance!

See my above comment about using @@deriving_inline, which I think addresses a lot of the hestitations we had with using a ppx. But let me know if you think that still would be problematic.

@liam923
liam923 force-pushed the locate-type-multi branch 4 times, most recently from bd55709 to 6e265b3 Compare August 25, 2025 21:36

@xvw xvw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I just have a small nitpicking but I approve the PR.
Thanks a lot for the feature (and for being understanding about PPXs)

Comment thread src/frontend/query_commands.ml Outdated

@xvw xvw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!
(cc @pitag-ha)

@voodoos voodoos left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks a lot @liam923, that does sounds like a useful feature. Additionally, I suspect the client work for this will also be reusable for when we will finally propose "locate declarationS".

Do you already have such work done on your LSP server / client ?

Comment on lines +405 to +410
| `Builtin (_, s) -> `Builtin s
| `Not_in_env _ as s -> s
| `Not_found _ as s -> s
| `Found { file; location; _ } ->
`Found (Some file, location.loc_start)
| `File_not_found result -> `File_not_found result.file

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to perform that additional mapping here ? It could be done in one pass when Query_json serializes it, as long as we pass along enough information.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The reason for this was to make Locate_types_result.t a type that can round trip back from json easily. That way, clients of Merlin can use Locate_types_result.t to represent the parsed result. (We make use of this fact in our internal client implementation.)

Comment on lines +136 to +155
module Locate_types_result = struct
type node_data =
| Arrow
| Tuple
| Object
| Poly_variant
| Type_ref of
{ type_ : string;
result :
[ `Found of string option * Lexing.position
| `Builtin of string
| `Not_in_env of string
| `File_not_found of string
| `Not_found of string * string option ]
}

type type_tree = { data : node_data; children : type_tree list }

type t = Success of type_tree | Invalid_context
end

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

At first I was a bit sad to see this type repeated in Locate_type, and thought it would be better to parametrize the tree. But after making the change in I am not sure if it's actually "better". WDYT ? (and @xvw ?)

My attempt: voodoos@d7cb643

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Even if it's just a minor detail, I also prefer @voodoos's approach (parametric).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I pushed a change to make this parametric.

| #Msource.position as pos ->
run buffer (Query_protocol.Locate_type pos)
end;
command "locate-types"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This new command should be documented in https://github.com/ocaml/merlin/blob/main/doc/dev/PROTOCOL.md

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've done so

@liam923

liam923 commented Sep 17, 2025

Copy link
Copy Markdown
Contributor Author

Do you already have such work done on your LSP server / client ?

We have, but we don't think that it's work that we can easily contribute. We didn't make any lsp changes to support this feature. Rather, we made our internal VSCode extension use the call-compatible lsp request to directly call the Merlin query. My understanding is that our extension is substantially different from the OCaml Platform extension, so unfortunately I don't think there's a staightforward way to share those changes.

To give some more details of the user experience:

  1. The user runs a vscode command that runs this new Merlin command.
  2. A modal pop-up displays the result of the call.
  3. The user can select which type they want to jump to.
    Here's some screenshots to give an idea. This is displaying the type:
Mpipeline.t ->
[> `Assoc of (modname * [> `Int of int ]) list
 | `Int of int
 | `String of modname ]
list -> json

but using an older version of this command that doesn't support polymorphic variants.
image
image

@voodoos
voodoos force-pushed the locate-type-multi branch from 07d1066 to 1f0fc7d Compare October 2, 2025 10:04
@voodoos

voodoos commented Oct 2, 2025

Copy link
Copy Markdown
Collaborator

Thanks Liam, I just rebased and moved the changelog entry to the unreleased section

@liam923

liam923 commented Oct 2, 2025

Copy link
Copy Markdown
Contributor Author

Great, thanks! Is this ready to merge then, or are there other changes I should make? (I don't have the power to click merge.)

@voodoos

voodoos commented Oct 3, 2025

Copy link
Copy Markdown
Collaborator

We're all good, I was just sleeping for the CI !

@voodoos
voodoos merged commit 53e0f14 into ocaml:main Oct 3, 2025
9 of 10 checks passed
voodoos added a commit to voodoos/opam-repository that referenced this pull request Oct 3, 2025
CHANGES:

Tue Jun 24 17:10:42 CEST 2025

  + merlin binary
    - Add `locate-types` command (ocaml/merlin#1951)
  + merlin library
    - Fix `merlin_reader` for OpenBSD (ocaml/merlin#1956)
    - Improve recovery of mutually recursive definitions (ocaml/merlin#1962, ocaml/merlin#1963, fixes ocaml/merlin#1953)
  + vim plugin
    - Fix error when `:MerlinOccurrencesProjectWide` fails to gather code previews (ocaml/merlin#1970)
    - Add more short-paths tests cases (ocaml/merlin#1904)
voodoos added a commit to voodoos/opam-repository that referenced this pull request Oct 4, 2025
CHANGES:

Sat Oct 04 15:10:42 CEST 2025

  + merlin binary
    - Add `locate-types` command (ocaml/merlin#1951)
  + merlin library
    - Fix `merlin_reader` for OpenBSD (ocaml/merlin#1956)
    - Improve recovery of mutually recursive definitions (ocaml/merlin#1962, ocaml/merlin#1963, fixes ocaml/merlin#1953)
    - Support for OCaml 5.4 (ocaml/merlin#1974)
  + vim plugin
    - Fix error when `:MerlinOccurrencesProjectWide` fails to gather code previews (ocaml/merlin#1970)
    - Add more short-paths tests cases (ocaml/merlin#1904)
voodoos added a commit to voodoos/opam-repository that referenced this pull request Apr 9, 2026
CHANGES:

Thu Apr 09 09:59:38 WAT 2026

  + merlin library
    - Implement new refactor-extract-region command for extracting region to a fresh let binding (warning: this feature is still experimental) (ocaml/merlin#1948)
    - Add "Other" variant to locate-types result (ocaml/merlin#2025)
    - Don't include `option` in locate-types result for optional parameters (ocaml/merlin#2027)
    - Fix record field autocompletion (ocaml/merlin#2028)
    - Signature help should not loop over the parameters once it is finished (ocaml/merlin#2023)
    - Fix bugs on signature help about labelled and optional parameters (ocaml/merlin#2032)
    - Add `-end-position` parameter for `enclosing` (ocaml/merlin#2029)
    - Signature help should appear even if the 'in' is not written (ocaml/merlin#2036)
    - Improve type enclosing behavior on various class and object related items
      (ocaml/merlin#2053)
  + merlin binary
    - Define PATH_MAX to 4096 if undefined (eg. hurd) (ocaml/merlin#2039)
  + test suite
    - Add a reproduction case for ocaml/merlin#1214, the issue has been resolved before (ocaml/merlin#2022)
    - Add reproduction case for ocaml/merlin#1763 but it is not failing anymore (ocaml/merlin#2021)
    - Add a test to reproduce [Locate command fails on multi-line type definitions](ocaml/merlin#1987) (ocaml/merlin#2020)
    - Add a regression test for issue ocaml/merlin#2019 (ocaml/merlin#2030)

merlin 5.6.1
Sat Dec 20 11:15:42 CET 2025

  + merlin binary
    - Fix a plethora of minor issues with the C code (ocaml/merlin#1998)
  + merlin library
    - Signature help should not appear on the function name (ocaml/merlin#1997)
    - Fix completion not working for inlined records labels (ocaml/merlin#1978, fixes ocaml/merlin#1977)
    - Perform buffer indexing only if the query requires it (ocaml/merlin#1990 and ocaml/merlin#1991)
    - Stop unnecessarily forcing substitutions when initializing short-paths graph (ocaml/merlin#1988)
    - Fix Mocaml.with_printer didn't update replacement_printer_doc (ocaml/merlin#2010)
  + test suite
    - Add a test to ensure the behavior showed in issue ocaml/merlin#1517 is no longer relevant (ocaml/merlin#1995)
    - Add a test to ensure the code fragment exhibited in issue ocaml/merlin#1118 no longer makes Merlin crash (ocaml/merlin#1996)
    - Add a test case illustrating how a snippet produces two unrelated errors in issue ocaml/merlin#2000. (ocaml/merlin#2003)
    - Add a test reproducing issue ocaml/merlin#1983 where `document` command which sometime concatenates consecutive variants and labels (ocaml/merlin#2005)
    - Signature-help should trigger on unfinished `let ... in` bindings (ocaml/merlin#2009)

merlin 5.6
Sat Oct 04 15:10:42 CEST 2025

  + merlin binary
    - Add `locate-types` command (ocaml/merlin#1951)
  + merlin library
    - Implement new refactor-extract-region command for extracting region to a fresh let binding (ocaml/merlin#1948)
    - Fix `merlin_reader` for OpenBSD (ocaml/merlin#1956)
    - Improve recovery of mutually recursive definitions (ocaml/merlin#1962, ocaml/merlin#1963, fixes ocaml/merlin#1953)
    - Support for OCaml 5.4 (ocaml/merlin#1974)
  + vim plugin
    - Fix error when `:MerlinOccurrencesProjectWide` fails to gather code previews (ocaml/merlin#1970)
  + test suite
    - Add more short-paths tests cases (ocaml/merlin#1904)
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.

6 participants