Ocaml-lsp find references in whole project?

Hello,

I’m getting my whole lsp ecosystem working in emacs under eglot, and I’m wondering if the reference finding in ocaml-lsp only works inside the buffer the request is in. For example, in Python and TypeScript it works across the entire project. I’m trying to determine if this is an issue in my configuration or how the LSP works.

If it only currently works inside the same buffer, are there any plans to extend it to be the entire project?

1 Like

Is there any documentation about the advantages of using OCaml-LSP over Merlin directly? E.g. is this find-references from Merlin or something else? My brief check seemed to indicated that OCaml-LSP is mostly a wrapper around Merlin.

The reason I want it is because the LSP’s have a common interface so its unifying all of my configuration and interfaces. I switch between 3 or 4 languages daily and it’s nice in that regard.

1 Like

Right now, find references only works on a single file. There’s an open issue on the merlin repository: Global API search · Issue #61 · ocaml/merlin · GitHub.

Perhaps it’s an issue with my setup, but find references doesn’t work for record fields even inside a single buffer, e.g. when the field is a part of a pattern match on a record.

Apart from unifying the interface as @orbitz mentioned, LSP (eglot or LSP-mode) does it’s thing more asynchronously then merlin’s emacs integration. For example in a larger buffer I can see merlin adding a lot of latency to typing with completion, while eglot seemingly does not.

1 Like

The biggest difference as of today is that LSP integrates with dune’s watch mode better. This means that LSP will show project global diagnostics (from dune) when watch mode is turned on.

3 Likes

Good to know! I guess at some point I might revisit it OCaml-LSP then.

Can anybody describe why whole project analysis is not done? Do we have any fundamental stopper?

I think merlin has all the necessary infrastructure. Someone just needs to build it. It could be you!

2 Likes

Project-wide occurrences is actually a feature that is being actively worked-on in Merlin ! (and because ocaml-lsp uses merlin under the hood it wil get it shortly after)

3 Likes

Glad to hear that.
I hope that indexing of a whole project will not take 6 cores and 6 GB of memory (I observed things like that with IntelliJ Idea)

Is this still unresolved? Is there a way, inside a dune project, to find all usages of a given function / type ?

You can grep, but you may get false positives due to other functions of the same name. Doing this project-wide in a way that scales well to large codebase is hard, and Merlin is trying to do that – which explains why the feature takes its time coming. (For the particularly curious, see maybe [occurrences] Store modules' shapes in env sumaries by voodoos · Pull Request #11983 · ocaml/ocaml · GitHub for an example of in-progress work on the road to this feature.)

1 Like

I don’t mean to sound ungrateful / entitled. Is there anything (type system?) that makes this harder in OCaml than in Rust? Find all references works in IntelliJ/Rust; so the problem seems do-able, unless some PL design of OCaml adds additional complexity to this.

They mention some difficulties.

Off the top of my head (and I’m no expert here, so there’s surely more to it), OCaml’s module system uniquely complicates this sort of code-mapping task because of functors, and the availability of include. I’ve done some work in building tooling (ages ago now, for a lisp, mostly in the Eclipse and emacs worlds), and just those two features of the module system would have given me fits in an untyped context. :weary:

I personally wouldn’t say that the question (or implication) indicates entitlement, but I would suggest stepping back from the technical and considering the structural differences between the OCaml community and e.g. Rust (tho you could make the comparison with any other language that has “crossed the chasm” in a mainstream way, like Java or Javascript or Python). In short, larger communities have much, much more funding sloshing around to pay top folks to improve community facilities, and this find-references question is a single context that illustrates the broader pattern.

AFAIK, the basis of much of Rust’s quality tooling is the rust-analyzer project, the top two contributors to which both work at Ferrous Systems. Ferrous is a Rust-focused consultancy, but they also have a product, Ferrocene, which aims to provide an ISO26262-qualified Rust compiler toolchain. You should assume that the customers and partners they have interested in such standards-compliance work come to the table looking to spend notable sums.

This is not to say that there aren’t companies in the OCaml space that contribute heavily to the commons (s/o Tarides, OCamlPro, LexiFi, and ofc Jane Street, among others), but it remains the case that much of what keeps OCaml moving forward is the work of academics, their students, and volunteers, and that in general, companies that sponsor work in the OCaml space are not doing it in service of their primary business (like a standards-qualified compiler toolchain, for example!). In this case re: find-references, the “leads” of Merlin (voodoos and @trefis) are both with Tarides AFAICT, with the former just off of his PhD; the foundational work for Merlin’s tooling support goes back years (here’s a key PR to OCaml from 2021 introducing “module shapes”, which actually includes a great walkthrough of what makes even find-definition hard in the face of e.g. functors, search for “How does this help tooling”). I’m going to go out on a ledge and say that improved OCaml tooling experiences is not a headline product at Tarides, though I’m certain their clients appreciate it. :wink:

This is all a case study to say, it’s unfair (though very understandable) to let the experience of more mainstream languages’ tooling and libraries inform our expectations elsewhere. There’s just no substitute for having anywhere from multiple brigades (in Rust) to multiple armies (in Java or Javascript) pushing hard work uphill to make everyone else’s day-to-day as plush as possible. To complete this tortured analogy, I’m incredibly grateful to the companies and persistent solo operators that have improved OCaml so notably, even in the handful of years I’ve been present to experience said change. :heart:

4 Likes
  1. I’m 99% sure IntelliJ Rust plugin does not use rust-analyzer.

  2. I can understand things being messy for non-parsing / non-typechecking programs. However, for programs that typecheck, it feels like all the goto-def / goto-impl / goto-ref information should be already computed during the type checking phase.

You’re right in part, per https://plugins.jetbrains.com/plugin/8182-rust/docs/rust-faq.html:

The plugin’s language analysis is implemented from scratch, leveraging the IntelliJ Platform infrastructure for incremental analysis and indexing. However, IntelliJ Rust shares some code for procedural macros expansion with rust-analyzer.

I was not trying to address IntelliJ at all, but this does underline the fundamental point I was trying to make, another part of the elephant if you will: there is sufficient demand and dollars for a top-tier tooling vendor like Jetbrains to put nontrivial resources behind their Rust support. So much so that duplicative analysis efforts are acceptable! Such is not (yet) the case for OCaml.

I’m still curious: during type checking, we need to take every node of the AST, figure out what it resolves to, then do HM type checking.

The information specified in “what it resolves it” – is this enough for goto-def, goto-impl, list-all-usages ?

If not, I’m interested in why not.