From cfed06cdd57603b81532672989c66b79103827be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Ojeda=20B=C3=A4r?= Date: Mon, 22 May 2023 19:10:17 +0200 Subject: [PATCH] dialects: allow embedded dots in extensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolás Ojeda Bär --- CHANGES.md | 3 +++ doc/dune-files.rst | 5 ++-- src/dune_rules/dialect.ml | 14 +++++----- src/dune_rules/melange/melange_stanzas.ml | 7 +---- src/dune_sexp/decoder.ml | 6 +++++ src/dune_sexp/decoder.mli | 4 +++ .../test-cases/dialects/bad3.t/run.t | 2 +- .../test-cases/dialects/dots.t/cppo.ml | 2 ++ .../test-cases/dialects/dots.t/dune | 11 ++++++++ .../dialects/dots.t/dune-project.in | 8 ++++++ .../test-cases/dialects/dots.t/main.cppo.ml | 0 .../test-cases/dialects/dots.t/main.mli | 0 .../test-cases/dialects/dots.t/run.t | 26 +++++++++++++++++++ 13 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 test/blackbox-tests/test-cases/dialects/dots.t/cppo.ml create mode 100644 test/blackbox-tests/test-cases/dialects/dots.t/dune create mode 100644 test/blackbox-tests/test-cases/dialects/dots.t/dune-project.in create mode 100644 test/blackbox-tests/test-cases/dialects/dots.t/main.cppo.ml create mode 100644 test/blackbox-tests/test-cases/dialects/dots.t/main.mli create mode 100644 test/blackbox-tests/test-cases/dialects/dots.t/run.t diff --git a/CHANGES.md b/CHANGES.md index 116c9aa549de..8888397b2c9a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,9 @@ Unreleased - Add additional metadata to the traces provided by `--trace-file` whenever `--trace-extended` is passed (#7778, @rleshchinskiy) +- Extensions used in `(dialect)` can include embedded dots (e.g., `cppo.ml`) for + versions of the Dune language 3.8 and later. (#7782, @nojb) + 3.8.0 (2023-05-23) ------------------ diff --git a/doc/dune-files.rst b/doc/dune-files.rst index fe2cb804b596..c719c8d1b46e 100644 --- a/doc/dune-files.rst +++ b/doc/dune-files.rst @@ -75,9 +75,10 @@ dialect Specify the file extension used for this dialect. - The extension string must not contain any dots and be unique in a given + The extension string must not start with a dot and be unique in a given project (so that a given extension can be mapped back to a - corresponding dialect). + corresponding dialect). In Dune 3.8 and later, the extension string may + contain embedded dots (e.g., `cppo.ml`). This field is required. diff --git a/src/dune_rules/dialect.ml b/src/dune_rules/dialect.ml index cbe815918dbb..ca624ab48a07 100644 --- a/src/dune_rules/dialect.ml +++ b/src/dune_rules/dialect.ml @@ -70,19 +70,19 @@ let encode { name; file_kinds } = let decode = let open Dune_lang.Decoder in let kind kind = - let+ loc, extension = field "extension" (located string) + let+ loc, extension = field "extension" (located extension) and+ preprocess = field_o "preprocess" (located Action.decode_dune_file) and+ format = field_o "format" (map ~f:(fun (loc, x) -> (loc, x, [])) (located Action.decode_dune_file)) - in - let extension = - if String.contains extension '.' then - User_error.raise ~loc [ Pp.textf "extension must not contain '.'" ]; - "." ^ extension - in + and+ syntax_ver = Syntax.get_exn Stanza.syntax in + let ver = (3, 9) in + (if syntax_ver < ver && Option.is_some (String.index_from extension 1 '.') + then + let what = "the possibility of defining extensions with embedded dots" in + Syntax.Error.since loc Stanza.syntax ver ~what); { File_kind.kind; extension; preprocess; format } in fields diff --git a/src/dune_rules/melange/melange_stanzas.ml b/src/dune_rules/melange/melange_stanzas.ml index 9ae568aa2663..b2522346cb20 100644 --- a/src/dune_rules/melange/melange_stanzas.ml +++ b/src/dune_rules/melange/melange_stanzas.ml @@ -24,12 +24,7 @@ module Emit = struct let implicit_alias = Alias.Name.of_string "melange" let decode = - let extension_field = - let+ loc, extension = located string in - if String.is_prefix ~prefix:"." extension then - User_error.raise ~loc [ Pp.textf "extension must not start with '.'" ]; - "." ^ extension - in + let extension_field = extension in let module_systems = let module_system = enum [ ("es6", Melange.Module_system.Es6); ("commonjs", CommonJs) ] diff --git a/src/dune_sexp/decoder.ml b/src/dune_sexp/decoder.ml index f582630f93e1..b3a5891f01eb 100644 --- a/src/dune_sexp/decoder.ml +++ b/src/dune_sexp/decoder.ml @@ -343,6 +343,12 @@ let filename = [ Pp.textf "'.' and '..' are not valid filenames" ] | fn -> fn) +let extension = + plain_string (fun ~loc s -> + if String.is_prefix ~prefix:"." s then + User_error.raise ~loc [ Pp.textf "extension must not start with '.'" ]; + "." ^ s) + let relative_file = plain_string (fun ~loc fn -> if Filename.is_relative fn then fn diff --git a/src/dune_sexp/decoder.mli b/src/dune_sexp/decoder.mli index 33efb82312a6..65363146f1d6 100644 --- a/src/dune_sexp/decoder.mli +++ b/src/dune_sexp/decoder.mli @@ -189,6 +189,10 @@ val plain_string : (loc:Loc.t -> string -> 'a) -> 'a t (** A valid filename, i.e. a string other than "." or ".." *) val filename : Filename.t t +(** An extension: a string not starting with ".". The value returned by the + parser is prefixed with ".". *) +val extension : string t + (** A relative filename *) val relative_file : string t diff --git a/test/blackbox-tests/test-cases/dialects/bad3.t/run.t b/test/blackbox-tests/test-cases/dialects/bad3.t/run.t index 1eb6acbdcd2b..3a099c219534 100644 --- a/test/blackbox-tests/test-cases/dialects/bad3.t/run.t +++ b/test/blackbox-tests/test-cases/dialects/bad3.t/run.t @@ -2,5 +2,5 @@ File "dune-project", line 5, characters 28-32: 5 | (implementation (extension .foo)) ^^^^ - Error: extension must not contain '.' + Error: extension must not start with '.' [1] diff --git a/test/blackbox-tests/test-cases/dialects/dots.t/cppo.ml b/test/blackbox-tests/test-cases/dialects/dots.t/cppo.ml new file mode 100644 index 000000000000..e729c918f0b0 --- /dev/null +++ b/test/blackbox-tests/test-cases/dialects/dots.t/cppo.ml @@ -0,0 +1,2 @@ +let () = + print_endline {|print_endline "Hello, World"|} diff --git a/test/blackbox-tests/test-cases/dialects/dots.t/dune b/test/blackbox-tests/test-cases/dialects/dots.t/dune new file mode 100644 index 000000000000..61867531c4ff --- /dev/null +++ b/test/blackbox-tests/test-cases/dialects/dots.t/dune @@ -0,0 +1,11 @@ +(executable + (name main) + (modules main)) + +(executable + (name cppo) + (modules cppo)) + +(rule + (alias show) + (action (cat main.cppo.ml.ml))) diff --git a/test/blackbox-tests/test-cases/dialects/dots.t/dune-project.in b/test/blackbox-tests/test-cases/dialects/dots.t/dune-project.in new file mode 100644 index 000000000000..2229acf9bc38 --- /dev/null +++ b/test/blackbox-tests/test-cases/dialects/dots.t/dune-project.in @@ -0,0 +1,8 @@ +(dialect + (name cppo) + (implementation + (extension cppo.ml) + (preprocess (run ./cppo.exe %{input-file}))) + (interface + (extension cppo.mli) + (preprocess (run ./cppo.exe %{input-file})))) diff --git a/test/blackbox-tests/test-cases/dialects/dots.t/main.cppo.ml b/test/blackbox-tests/test-cases/dialects/dots.t/main.cppo.ml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/blackbox-tests/test-cases/dialects/dots.t/main.mli b/test/blackbox-tests/test-cases/dialects/dots.t/main.mli new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/blackbox-tests/test-cases/dialects/dots.t/run.t b/test/blackbox-tests/test-cases/dialects/dots.t/run.t new file mode 100644 index 000000000000..0f5e715b8e49 --- /dev/null +++ b/test/blackbox-tests/test-cases/dialects/dots.t/run.t @@ -0,0 +1,26 @@ +Test the (dialect ...) stanza inside the `dune-project` file. + + $ { echo '(lang dune 3.8)'; cat dune-project.in; } >dune-project + + $ dune build --display short + File "dune-project", line 5, characters 13-20: + 5 | (extension cppo.ml) + ^^^^^^^ + Error: the possibility of defining extensions with embedded dots is only + available since version 3.9 of the dune language. Please update your + dune-project file to have (lang dune 3.9). + [1] + + $ { echo '(lang dune 3.9)'; cat dune-project.in; } >dune-project + + $ dune build --display short + ocamlc .cppo.eobjs/byte/dune__exe__Cppo.{cmi,cmti} + ocamlc .main.eobjs/byte/dune__exe__Main.{cmi,cmti} + ocamlopt .cppo.eobjs/native/dune__exe__Cppo.{cmx,o} + ocamlopt cppo.exe + cppo main.cppo.ml.ml + ocamlopt .main.eobjs/native/dune__exe__Main.{cmx,o} + ocamlopt main.exe + + $ dune build @show + print_endline "Hello, World"