Skip to content

Commit c36df0b

Browse files
authored
[merlin] Handle filenames with dot-separated sections (#4264)
* Split filename on `.` and use the first part for config matching * Illustrate usage with some tests * Add some documentation about naming preprocessed files. Signed-off-by: Ulysse Gérard <thevoodoos@gmail.com>
1 parent c507979 commit c36df0b

File tree

5 files changed

+54
-6
lines changed

5 files changed

+54
-6
lines changed

doc/usage.rst

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ There's a few aliases that dune automatically creates for the user
280280
defined in that directory.
281281

282282
* ``check`` - This alias will build the minimal set of targets required for
283-
tooling support. Essentially, this is ``.cmi``, ``.cmt``, ``.cmti``, and
284-
``.merlin`` files.
283+
tooling support. Essentially, this is ``.cmi``, ``.cmt``, ``.cmti`` files and
284+
Merlin configurations.
285285

286286
Variables for artifacts
287287
-----------------------
@@ -587,6 +587,16 @@ be un-commented afterward. This feature does not aim at writing exact or correct
587587
``.merlin`` files, its sole purpose is to lessen the burden of writing the
588588
configuration from scratch.
589589

590-
Both these commands also support an optional path to specify the target
591-
directory. This directory must be in a Dune workspace and the project must have
592-
already been built.
590+
Non-standard filenames
591+
----------------------
592+
593+
Merlin configuration loading is based on filename. That means that if you have
594+
files which are preprocessed by custom rules before they are built, they should
595+
respect the following naming convention: the unprocessed file should start with
596+
the name of the resulting processed file followed by a dot and then the rest
597+
does not matter. Only the name before the first dot will be used by Dune to
598+
match with available configurations.
599+
600+
For example, if you use the ``cppo`` preprocessor to generate the file
601+
``real_module_name.ml`` then the source file could be named
602+
``real_module_name.cppo.ml``.

src/dune_rules/merlin.ml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,14 @@ module Processed = struct
123123
Buffer.contents b
124124

125125
let get { modules; pp_config; config } ~filename =
126-
let fname = Filename.remove_extension filename |> String.lowercase in
126+
(* We only match the first part of the filename : foo.ml -> foo foo.cppo.ml
127+
-> foo *)
128+
let fname =
129+
String.lsplit2 filename ~on:'.'
130+
|> Option.map ~f:fst
131+
|> Option.value ~default:filename
132+
|> String.lowercase
133+
in
127134
List.find_opt modules ~f:(fun name ->
128135
let fname' = Module_name.to_string name |> String.lowercase in
129136
String.equal fname fname')

test/blackbox-tests/test-cases/merlin/server.t/dune

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,8 @@
1111
(name main)
1212
(modules main lib2)
1313
(libraries mylib mylib3))
14+
15+
(executable
16+
(name not-a-module-name)
17+
(modules not-a-module-name)
18+
(flags :standard -w -24))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print_endline "I do not bear a valid module name."

test/blackbox-tests/test-cases/merlin/server.t/run.t

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,28 @@
1616
> (4:File${#FILE}:$FILE)
1717
> EOF
1818
((?:STDLIB?:OPAM_PREFIX/lib/ocaml)(?:EXCLUDE_QUERY_DIR)(?:B?:$TESTCASE_ROOT/_build/default/.mylib.objs/byte)(?:B?:$TESTCASE_ROOT/_build/default/.mylib3.objs/byte)(?:S?:$TESTCASE_ROOT)(?:FLG(?:-open?:Mylib?:-w?:@1..3@5..28@30..39@43@46..47@49..57@61..62-?:-strict-sequence?:-strict-formats?:-short-paths?:-keep-locs)))
19+
20+
If a file has a name of the kind `module_name.xx.xxx.ml/i`
21+
we consider it as ``module_name.ml/i`
22+
This can be useful when some build scripts perform custom
23+
preprocessing and copy files around.
24+
$ FILE=lib3.foobar.ml
25+
$ dune ocaml-merlin <<EOF | sed -E "s/[[:digit:]]+:/\?:/g" | sed 's#'$(opam config var prefix)'#OPAM_PREFIX#'
26+
> (4:File${#FILE}:$FILE)
27+
> EOF
28+
((?:STDLIB?:OPAM_PREFIX/lib/ocaml)(?:EXCLUDE_QUERY_DIR)(?:B?:$TESTCASE_ROOT/_build/default/.mylib.objs/byte)(?:B?:$TESTCASE_ROOT/_build/default/.mylib3.objs/byte)(?:S?:$TESTCASE_ROOT)(?:FLG(?:-open?:Mylib?:-w?:@1..3@5..28@30..39@43@46..47@49..57@61..62-?:-strict-sequence?:-strict-formats?:-short-paths?:-keep-locs)))
29+
30+
If a directory has no configuration the configuration of its parent is used
31+
This can be useful when some build scripts copy files from subdirectories.
32+
$ FILE=some_sub_dir/lib3.foobar.ml
33+
$ dune ocaml-merlin <<EOF | sed -E "s/[[:digit:]]+:/\?:/g" | sed 's#'$(opam config var prefix)'#OPAM_PREFIX#'
34+
> (4:File${#FILE}:$FILE)
35+
> EOF
36+
((?:STDLIB?:OPAM_PREFIX/lib/ocaml)(?:EXCLUDE_QUERY_DIR)(?:B?:$TESTCASE_ROOT/_build/default/.mylib.objs/byte)(?:B?:$TESTCASE_ROOT/_build/default/.mylib3.objs/byte)(?:S?:$TESTCASE_ROOT)(?:FLG(?:-open?:Mylib?:-w?:@1..3@5..28@30..39@43@46..47@49..57@61..62-?:-strict-sequence?:-strict-formats?:-short-paths?:-keep-locs)))
37+
38+
Test of an valid invalid module name
39+
$ FILE=not-a-module-name.ml
40+
$ dune ocaml-merlin <<EOF | sed -E "s/[[:digit:]]+:/\?:/g" | sed 's#'$(opam config var prefix)'#OPAM_PREFIX#'
41+
> (4:File${#FILE}:$FILE)
42+
> EOF
43+
((?:STDLIB?:OPAM_PREFIX/lib/ocaml)(?:EXCLUDE_QUERY_DIR)(?:B?:$TESTCASE_ROOT/_build/default/.not-a-module-name.eobjs/byte)(?:S?:$TESTCASE_ROOT)(?:FLG(?:-w?:@1..3@5..28@30..39@43@46..47@49..57@61..62-?:-strict-sequence?:-strict-formats?:-short-paths?:-keep-locs?:-w?:-24)))

0 commit comments

Comments
 (0)