| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
- Move Io, Chan, and listen infrastructure to server.ml - Simplify on_request to take a packed request directly - Add basic hover response with markdown content - Rename public executable to rescript-language-server
- Add `parse_implementation_from_source` to parsing/print engine types and all engine implementations, enabling parsing from a string source rather than a filename - Use `parse_implementation_from_source` in CompletionFrontEnd - Rename package from `rescript-lsp` to `rescript-language-server` - Refactor LSP server with typed state, document store, and diagnostics - Add hover support via completion backend integration
Move LSP modules under lsp/src/ with a thin lsp/bin/ entry point, add a configuration module, and introduce a tests/lsp_tests workspace exercising hover end-to-end.
Splits `Commands.ml` into a pure layer that returns OCaml values (option, list, typed records like Protocol.hover, Protocol.signatureHelp, Protocol.completionItem) and a new `analysis/src/Cli.ml` that does the stringify-and-print step. `analysis/bin/main.ml` now dispatches to `Cli.*`, while the LSP server consumes `Commands.*` directly. Makes the parsers accept source strings: `res_driver` gains `parse_interface_from_source` alongside the existing `parse_implementation_from_source`
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. Thanks for integrating Codecov - We've got you covered ☂️ |
Sorry, something went wrong.
- Rename Helper module to Client - Move expected output files into workspace directories - Improve request log format to show file path:line:col - Simplify hover.ml by removing intermediate result binding - Disable in-source compilation for basic-workspace
`file://name.res#LX,Y` Works in VSCode and Zed!!
Merge all diagnostic sources when serving requests and serializing state. Ignore partial compiler logs until #Done, then publish the completed snapshot and refresh pull diagnostics so clients clear resolved warnings without flickering.
| Back | FazBrowse Home | New Git URL |
This branch introduces a standalone ReScript LSP server
(rescript lsp subcommand) built on top of the existing analysis library.
It's a separate, OCaml-side exploration alongside the Rust/rewatch-based
experiment in #8243, the two share the same goal (a LSP server for ReScript) but
approach it from different ends of the toolchain.
Why rewriting the server in OCaml is a good fit
The editor features are already implemented in the OCaml analysis library.
Hover, completion, references, rename, document symbols, code actions, and
diagnostics all depend on compiler data structures such as .cmt / .cmti,
typed trees, locations, package metadata, and compiler diagnostics. Running the
LSP server in OCaml lets the server call those APIs directly instead of shelling
out to rescript-editor-analysis.exe or passing JSON through stdin. That
removes a large amount of process orchestration and serialization glue, and
keeps the LSP closer to the compiler types it needs to understand. This also
makes the server easier to evolve with the compiler. When typedtree, diagnostic
formats, package discovery, or .cmt handling changes, the LSP can be updated
in the same language and build system as the analysis code. That reduces version
skew and makes bugs easier to reproduce with Dune/expect tests.
Why ship the language server with the compiler
The language server is tightly coupled to the compiler version used by a
project. It reads .cmt and .cmti files containing marshalled compiler
internals such as Typedtree, Types, and Env. These files are not a stable,
schema-aware protocol: changing one of those OCaml types can make an analysis
binary incompatible with artifacts produced by another compiler revision.
This is not only a theoretical compatibility concern. In
#8475, adding typedtree
constructors for for...of without changing the CMT magic number allowed a
newer analysis binary to read incompatible ReScript 12 artifacts and
segmentation fault. The same class of failure appeared after record-rest
changes altered compiler data stored in CMT files. Bumping the CMT magic number
makes these mismatches rejectable, but the project must still be rebuilt with
the matching compiler.
Shipping the server in the same platform package as the compiler, and exposing
it through rescript lsp --stdio, gives clients one project-local entrypoint.
The selected ReScript dependency then supplies bsc, the analysis code, and the
language server from the same release. This has several practical benefits:
Bundling does not make stale artifacts safe. Compiler changes that alter
marshalled CMT data must still bump the magic number, and the server should turn
version mismatches into an actionable request to rebuild. A separately
versioned server becomes practical only if analysis moves to a stable,
explicitly versioned artifact format or maintains decoders for multiple
compiler-internal formats. Until then, promising one server binary that supports
multiple compiler versions would hide a compatibility boundary that already
exists.
What's here
with its own opam file (rescript-language-server.opam). Depends on lsp (>=
1.22.0), eio/eio_main, ppx_deriving_yojson, ppx_expect and the in-tree
analysis library.
compiler.
Status / what's not here yet
The main objective is to first maintain feature parity with the current server
(server.ts) as much as possible. Below is a list of some requests and
notifications. Some are out of scope because they don't make sense.
implemented for now.
dependency errors be published?
does not point at a precise source range. When the document is open, we
expand the diagnostic range to cover the whole document so the editor can
display a file-level diagnostic. If the document is not open, we keep the
range parsed from the compiler log, i.e.,
{start: {line: 0, character: 0}, end: {line: 0, character: 6}}
Protocol positions are zero-based, so the position is length - 1.
parser.
provide instant feedback.
for more examples.
generated with build_root field for each subpackage.
.compiler.log files, which usually means a ReScript build has finished.
When a watched log changes, the server re-reads every known compiler log and
republishes diagnostics so stale errors are cleared and monorepo diagnostics
stay in sync.
suffix and package-specs are needed to create the code action
Open compiled JS file. Changes in dependencies impact various
functionalities because they modify the state in
Analysis.Shared_types.state.
dynamically. The server does not know all file-watch patterns during the
static initialize response. In this LSP, the watcher list depends on
project state, especially .sourcedirs.json, which tells us where each
ReScript build root lives. In monorepos, that means the server needs to
register watchers for compiler logs after initialization, once it has
workspace context. That means watching generated .compiler.log files. When
the client sees one change, it sends workspace/didChangeWatchedFiles, and
the server refreshes diagnostics.
for now.
implemented for now.
Support v12 CMT files in analysis #8477
implemented for now.
tree-sitter is not used for document symbols.
now.
rescript/openCompiled)
rescript/createInterface)
rescript/switchImplementationInterface)
now.
now.
now.
be implemented for now.
implemented for now.
implemented for now.
implemented for now.
implemented for now.
implemented for now.
implemented for now.
now.
implemented for now.
implemented for now.
analysis state (Analysis.Shared_types.state) and compiler config).
interface file if the client supports the window/showDocument request.
CodeAction.command = "rescript/commandName" ↓ workspace/executeCommand handler ↓ server sends window/showDocument ↓ client opens fileLSP: support windows/showDocument zed-industries/zed#58099.
client side, but it could be a command triggered by a code action.
will be done. See last point. It will not be implemented for now
initialization and drop this custom request?
server to the client when compilation is finished
uses it to run Code Analysis. The server sends it when .compiler.log
changes. Only VSCode uses this notification.
reanalyze may be integrated into the server instead of running on the
client side.
compilation status from the server to the client.
bar. Only VSCode uses this notification.
client uses node-ipc. This implementation supports only stdio.
not be implemented for now.
produced by an existing rescript build, rather than the LSP starting or
managing builds itself.
for now. Idea to explore.
in memory?
Tests
tests/lsp_tests/ adds a dune-driven integration test (test.ml) that boots
the server against a real ReScript workspace (basic-workspace/), initializes
the LSP session, sends the initialized notification, opens source documents,
and snapshots responses for representative fixtures.
The LSP test target now also runs dune runtest, covering inline tests such as
.sourcedirs.json build-root, .compiler.log parsing used by diagnostics and
file-watcher setup.
Breaking Changes
settings coming from initializationOptions. See
Spec should discourage abuse of initializationOptions and didChangeConfiguration microsoft/language-server-protocol#567 (comment).
We use workspace/configuration.
Server settings
Proposed interface.
feature, but some clients don't have good support; Neovim are a example.
Therefore, I'm promoting it to a setting so users can enable or disable it.
Release and transition plan
Other related topics
Refactor analysis for use on the server side
#8426
#8466
#8478
##8436
#8465