Skip to content

Support per-mode Merlin file configurations - #19

Draft
anmonteiro wants to merge 72 commits into
mainfrom
anmonteiro/editor-mode-prototype
Draft

Support per-mode Merlin file configurations#19
anmonteiro wants to merge 72 commits into
mainfrom
anmonteiro/editor-mode-prototype

Conversation

@anmonteiro

@anmonteiro anmonteiro commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Generate and expose every effective library Merlin configuration through an additive tagged protocol request while preserving legacy singular behavior.

Related to anmonteiro/merlin#2 and anmonteiro/ocaml-lsp#2.

shonfeder and others added 25 commits August 21, 2026 16:37
This name is misleading, since the function does not actually check if
package management is enabled, is just checks whether it is
explicitly *disabled*, and, if so, it raises a user error. Renaming the
function makes this behaviour clear.

Signed-off-by: Shon Feder <shon.feder@gmail.com>
`dune pkg outdated` requires that package management already be enabled
to work properly, but it was not checking this (likely due to the
misleadling name of the check it was relying). As a result, it would
start resolving opam repositories over the network before going to look
for the lock directory only to find it didn't exist. As a result,
invoking this command in a project that didn't use package management
paid for a full clone of opam-repository and then failed with a bare
`dune.lock/lock.dune: No such file or directory`.

Signed-off-by: Shon Feder <shon.feder@gmail.com>
Signed-off-by: Ali Caglayan <alizter@gmail.com>
Exercise a scoped package dependency with duplicate public libraries so install-entry indexing continues to report the existing source-located user error.

Signed-off-by: Ali Caglayan <alizter@gmail.com>
Prepare qualified-module dependency lookup once per batch so parent
discovery is not repeated for every dependency name.

Builds on ocaml#15724; behavior is covered by ocaml#15754, ocaml#15759, and ocaml#15823.
Dependency-closure caching is deferred to separate work.

Benchmarks against `6cfbe56ed6` (medians from three alternating 3-second
rounds):

| Case | Base | Batched | Speedup |
|---|---:|---:|---:|
| Empty deep-parent batch | 3.78ns | 2.82ns | 1.34x |
| Reused deep-parent batch | 56.13us | 10.91us | 5.15x |
| Reused qualified-group batch | 25.92us | 14.30us | 1.81x |
| Qualified-group batch, including setup | 490.04us | 454.16us | 1.08x |
| Depth-512 self-only batch | 472.89ns | 456.97ns | 1.03x |
| Single depth-128 group control | 26.50us | 26.24us | 1.01x |

The deep-parent case reduces minor/major allocation by 94.37%/93.67%;
the qualified-group case reduces them by 44.61%/40.72%.

The benchmark harness is not included in this PR.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Build qualified-group dependency closures with a reverse accumulator,
avoiding intermediate subtree lists and quadratic copying for nested
groups.

Local benchmarks show 13.9% lower time for 1,024 flat modules and a 5.2x
speedup at nesting depth 128. The benchmark harness is not included.

Builds on ocaml#15752, which batches qualified dependency lookup.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Return the final element of a non-empty list directly instead of
allocating an intermediate option.

A local benchmark removes two minor-heap words per call for lists longer
than one element. The benchmark harness is not included.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Wait for the watch-mode Dune process to exit before the basic cram test
sandbox is cleaned up.

Observed in ocaml#16089.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Share public-library lookup across site plugin build and install rules.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Centralize RPC connection error construction for socket conversion and
connection failures.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Share rule-mode expansion across one-step and inferred Menhir rules.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Context names become build-directory components and must remain
portable. Reject `:` alongside `/` and `\`, since Dune path parsing
treats colons as separators on Windows and Cygwin. This deliberately
rejects existing context names containing colons rather than
interpreting them differently across platforms.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
)

`Install.Context.of_path` already receives a `Path.Build.t`. Classify it
directly with `Dpath.Target_dir.of_target` instead of wrapping it as a
generic `Path.t` and immediately unwrapping the result. This makes
impossible source and external cases unrepresentable and avoids
intermediate variants while preserving the existing classification.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
## Description

Pin the source-located duplicate-public-library diagnostic when a scoped
package layout indexes install entries by library.

Related to ocaml#15511.
…16084)

## Summary

- Reproduce a portable-lock-directory case where a package is reachable
through a post dependency on Linux and a regular dependency on macOS.
- Verify locking succeeds while the dependency pruned from the Linux
graph is not retained.
- Provide the pre-feature regression test for ocaml#15982.

## Checks

- `dune runtest
test/blackbox-tests/test-cases/pkg/portable-lockdirs/portable-lockdirs-post-dependency-reachability.t`
- `CI=true dune build @fmt @check`
Signed-off-by: Ali Caglayan <alizter@gmail.com>
Add focused coverage for BLAKE3 digest representation and operations
ahead of
the planned compact representation change:

- record the current payload size and layout
- exercise equality, including inputs that will become NaN bit patterns
- check comparison laws and lexicographic ordering
- record the current hashing behavior for digests sharing their first 64
bits

This establishes a green baseline. The follow-up implementation will
update the
representation and hashing expectations.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Bypass the general target-validation path for the common case of a rule
with a single file target. Expose `Array.Set.length` so the singleton
fast path can be detected without converting the compact set
representation.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Use `Readdir.read_directory` while searching ancestor directories for a
VCS root, allowing directory entries to remain `Filename.t` values
instead of converting and revalidating each name. Unreadable parent
directories continue to produce a warning with the detailed Unix error.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
`Module_name.Unique.artifact_filename` always produces a single path
component, but returned it as an unstructured string. Return
`Filename.t` so this invariant is represented in the type and use
filename-aware path construction at call sites.

This avoids sending known filenames through general path parsing and
normalization without changing generated artifact paths.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Several rule generators independently translate an optional project root
into a build directory before looking up its scope. Add
`Scope.DB.find_by_project_root` to centralize this translation and use
it for JavaScript, parameterised, and preprocessing rules.

This removes duplicated lookup logic without changing behavior.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
The fixed js_of_ocaml object-directory name is a single path component,
but it was stored and compared as an unstructured string. Represent it
as `Filename.t`, construct its path with `relative_fname`, and compare
it directly with path basenames.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Reuse the Menhir functor super context and distinguish its inference
compilation context. Follow-up to ocaml#16092.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Resolve the link context once for build-context and build-directory
setup.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
rgrinberg and others added 29 commits August 23, 2026 17:47
Extract the fold that combines all matching cram stanzas for a
discovered test into a dedicated spec_for_test helper. The helper builds
the complete test specification, including aliases, dependencies,
sandboxing, environment, locks, packages, timeouts, setup scripts, and
shell settings.

This keeps rule generation focused on applying package masks and
registering the resulting rules. It also gives other cram consumers a
reusable way to derive the same specification without duplicating stanza
matching and merge behavior.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Add a regression test recording the current failure when `dune ocaml
top-module` is invoked from the module's directory with workspace root
detection enabled.

The test shows that the relative module path is interpreted from the
workspace
root rather than the directory where Dune was started. It is test-only
groundwork
for sharing module-path resolution with `dune ocaml inferred-mli`.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Add `dune ocaml inferred-mli MODULE` to infer an OCaml interface using
the
module's actual build configuration, including preprocessing,
dependencies,
opens, and parameter flags.

Missing or stale interfaces are reported through Dune's correction
workflow and
can be applied with `dune promote`; an up-to-date interface succeeds
without
registering a promotion. This avoids having to reproduce the module's
compiler
configuration manually when generating an interface.

Fixes ocaml#12727

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
)

Centralize command-line source path resolution in `Common.source_path`
and use
it for both `dune ocaml top-module` and `dune ocaml inferred-mli`.

Relative paths are now resolved from the directory where Dune was
started,
which fixes `top-module` when invoked from a workspace subdirectory.
Absolute
paths continue to be accepted only when they are inside the workspace.

This follows ocaml#16111 and the test-only reproduction in ocaml#16134.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Use `Common.source_path`, introduced in ocaml#16135, to resolve the directory
passed
to `dune utop`.

This removes the command's separate relative/absolute localization logic
while
preserving support for relative paths and absolute paths inside the
workspace.
Paths outside the workspace now use the shared source-path error.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Add a regression test recording the current internal error when `dune
ocaml
top` receives an absolute directory path inside the workspace.

This is test-only groundwork for resolving the command's directory
through the
shared `Common.source_path` handling.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Add a regression test recording the current internal error when a
promotion
subcommand receives an absolute source path inside the workspace.

This is test-only groundwork for using the shared `Common.source_path`
handling
for promotion file and directory arguments.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Add a regression test recording that `dune describe workspace` rejects
an
absolute directory filter inside the workspace.

This is test-only groundwork for resolving workspace directory filters
through
the shared `Common.source_path` handling.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Several memoized rule paths repeat the same operation: return an
optional value when present, otherwise lazily compute a monadic default.

Add `Option.value` to the monad interface and use it across executable
configuration, environment lookup, JavaScript and Rocq rules, and
subsystem selection. The default remains a thunk, so existing
short-circuiting behavior is preserved.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Parse `dune describe workspace` directory filters as path strings and
resolve
them through `Common.source_path`.

Absolute directory filters inside the workspace now select the same
source
directory as relative filters, fixing the rejection recorded in ocaml#16140.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Resolve the directory passed to `dune ocaml top` through
`Common.source_path`, then map the resulting source path into the
selected
build context.

This accepts absolute directories inside the workspace instead of
raising the
internal error recorded in ocaml#16137.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
Resolve promotion file and directory arguments through
`Common.source_path`.
Absolute paths inside the workspace now select the same pending
promotions as
their relative forms.

This fixes the internal error recorded in ocaml#16139.

Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
…#16066)

Extend the installed Melange virtual-library regression test to cover
CMT-based dependency discovery, including private and unused modules.

Follows ocaml#16034.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
…6067)

Add a separate cram test for installed Melange virtual libraries built
without binary annotations, including private modules and a reverse
virtual-module dependency.

Companion to ocaml#16066.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Adds regression coverage for fail-fast installation errors discovered
while reviewing concurrent installation in ocaml#13054.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Adds regression coverage for artifact-substitution staging paths that
alias install destinations through symlinks, discovered while reviewing
ocaml#13054.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Share JS and Wasm compiler selection across configuration resolution and
compiler rules.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Share repeated js_of_ocaml program and version resolution.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Resolve the build context once for source mapping and per-file copy
rules.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Share the inline-test library-name pform binding across runner and
partition flags.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Centralize lock-package basenames shared by package files directories
and lock filenames.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Resolve the context once when generating opam aliases.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Reuse the resolved OCaml toolchain for MDX mode and library include
paths.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Share formatting, cram, and reverse-dependency rule setup across
source-only and grouped directories.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
…5493)

Represent each stanza's persisted Merlin configuration as a
default-first nonempty group while preserving existing singular lookup
and debug behavior.

Preparation for ocaml#15557; all current producers remain singleton.

Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Signed-off-by: Antonio Nuno Monteiro <anmonteiro@gmail.com>
Retain both OCaml and Melange configurations for mixed-mode libraries and prefer exact file matches over extensionless fallbacks.
@anmonteiro
anmonteiro force-pushed the anmonteiro/editor-mode-prototype branch from eb042b9 to efe8bb8 Compare August 24, 2026 03:28
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.

4 participants