Skip to content

Commit 2f840d4

Browse files
authored
5.3 support: Versioned keywords (#2623)
Backport the 5.3 changes related to the new `keyword_edition` feature and connect it to OCamlformat's `ocaml_version` option. This will allow to parse pre-5.3 code that uses `effect` as identifiers.
1 parent cdb0099 commit 2f840d4

File tree

19 files changed

+299
-156
lines changed

19 files changed

+299
-156
lines changed

CHANGES.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ profile. This started with version 0.26.0.
1414
This might change the formatting of some functions due to the formatting code
1515
being completely rewritten.
1616

17-
- Support OCaml 5.3 syntax (#2609, #2610, #2611, #2622, @Julow)
17+
- Support OCaml 5.3 syntax (#2609, #2610, #2611, #2622, #2623, @Julow)
1818
This adds support for short functor type arguments syntax and utf8
1919
identifiers.
20+
To format code using the new `effect` syntax, add this option to your
21+
`.ocamlformat`:
22+
```
23+
ocaml-version = 5.3
24+
```
2025

2126
- Documentation comments are now formatted by default (#2390, @Julow)
2227
Use the option `parse-docstrings = false` to restore the previous behavior.

lib/Extended_ast.ml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,15 +242,18 @@ module Parse = struct
242242
map fg (normalize_mapper ~ocaml_version ~preserve_beginend)
243243
@@
244244
let lexbuf = Lexing.from_string str in
245+
let ocaml_version =
246+
Some Ocaml_version.(major ocaml_version, minor ocaml_version)
247+
in
245248
Location.init_info lexbuf input_name ;
246249
match fg with
247-
| Structure -> Parse.implementation lexbuf
248-
| Signature -> Parse.interface lexbuf
249-
| Use_file -> Parse.use_file lexbuf
250-
| Core_type -> Parse.core_type lexbuf
251-
| Module_type -> Parse.module_type lexbuf
252-
| Expression -> Parse.expression lexbuf
253-
| Repl_file -> Toplevel_lexer.repl_file lexbuf
250+
| Structure -> Parse.implementation ~ocaml_version lexbuf
251+
| Signature -> Parse.interface ~ocaml_version lexbuf
252+
| Use_file -> Parse.use_file ~ocaml_version lexbuf
253+
| Core_type -> Parse.core_type ~ocaml_version lexbuf
254+
| Module_type -> Parse.module_type ~ocaml_version lexbuf
255+
| Expression -> Parse.expression ~ocaml_version lexbuf
256+
| Repl_file -> Toplevel_lexer.repl_file ~ocaml_version lexbuf
254257
| Documentation ->
255258
let pos = (Location.curr lexbuf).loc_start in
256259
let pos = {pos with pos_fname= input_name} in

lib/Parse_with_comments.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ let parse ?(disable_w50 = false) ?(disable_deprecated = false) parse fragment
8484
if Warning.is_deprecated_alert alert && disable_deprecated then false
8585
else not conf.opr_opts.quiet.v )
8686
~f:(fun () ->
87-
let ast = parse fragment ~input_name source in
87+
let ocaml_version = conf.opr_opts.ocaml_version.v in
88+
let ast = parse fragment ~ocaml_version ~input_name source in
8889
Warnings.check_fatal () ;
8990
let comments =
9091
let mk_cmt = function
@@ -102,9 +103,8 @@ let parse ?(disable_w50 = false) ?(disable_deprecated = false) parse fragment
102103
in
103104
match List.rev !w50 with [] -> t | w50 -> raise (Warning50 w50)
104105

105-
let parse_ast (conf : Conf.t) fg ~input_name s =
106-
let ocaml_version = conf.opr_opts.ocaml_version.v
107-
and preserve_beginend = Poly.(conf.fmt_opts.exp_grouping.v = `Preserve) in
106+
let parse_ast (conf : Conf.t) fg ~ocaml_version ~input_name s =
107+
let preserve_beginend = Poly.(conf.fmt_opts.exp_grouping.v = `Preserve) in
108108
Extended_ast.Parse.ast fg ~ocaml_version ~preserve_beginend ~input_name s
109109

110110
(** [is_repl_block x] returns whether [x] is a list of REPL phrases and

lib/Parse_with_comments.mli

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ exception Warning50 of (Location.t * Warnings.t) list
2929
val parse :
3030
?disable_w50:bool
3131
-> ?disable_deprecated:bool
32-
-> ('b -> input_name:string -> string -> 'a)
32+
-> ( 'b
33+
-> ocaml_version:Ocaml_version.t
34+
-> input_name:string
35+
-> string
36+
-> 'a )
3337
-> 'b
3438
-> Conf.t
3539
-> input_name:string
@@ -50,5 +54,10 @@ val parse_toplevel :
5054
function handles [conf.parse_toplevel_phrases]. *)
5155

5256
val parse_ast :
53-
Conf.t -> 'a Extended_ast.t -> input_name:string -> string -> 'a
57+
Conf.t
58+
-> 'a Extended_ast.t
59+
-> ocaml_version:Ocaml_version.t
60+
-> input_name:string
61+
-> string
62+
-> 'a
5463
(** Argument to {!parse}. *)

lib/Std_ast.ml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,19 @@ let map (type a) (x : a t) (m : Ast_mapper.mapper) : a -> a =
5656
| Documentation -> Fn.id
5757

5858
module Parse = struct
59-
let ast (type a) (fg : a t) ~input_name str : a =
59+
let ast (type a) (fg : a t) ~ocaml_version ~input_name str : a =
6060
let lexbuf = Lexing.from_string str in
61+
let ocaml_version =
62+
Some Ocaml_version.(major ocaml_version, minor ocaml_version)
63+
in
6164
Location.init_info lexbuf input_name ;
6265
match fg with
63-
| Structure -> Parse.implementation lexbuf
64-
| Signature -> Parse.interface lexbuf
65-
| Use_file -> Parse.use_file lexbuf
66-
| Core_type -> Parse.core_type lexbuf
67-
| Module_type -> Parse.module_type lexbuf
68-
| Expression -> Parse.expression lexbuf
66+
| Structure -> Parse.implementation ~ocaml_version lexbuf
67+
| Signature -> Parse.interface ~ocaml_version lexbuf
68+
| Use_file -> Parse.use_file ~ocaml_version lexbuf
69+
| Core_type -> Parse.core_type ~ocaml_version lexbuf
70+
| Module_type -> Parse.module_type ~ocaml_version lexbuf
71+
| Expression -> Parse.expression ~ocaml_version lexbuf
6972
| Repl_file -> ()
7073
| Documentation -> ()
7174
end

lib/Std_ast.mli

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ type any_t = Any : 'a t -> any_t [@@unboxed]
3333
val of_syntax : Syntax.t -> any_t
3434

3535
module Parse : sig
36-
val ast : 'a t -> input_name:string -> string -> 'a
36+
val ast :
37+
'a t
38+
-> ocaml_version:Ocaml_version.t
39+
-> input_name:string
40+
-> string
41+
-> 'a
3742
end
3843

3944
val equal : 'a t -> 'a -> 'a -> bool

lib/Toplevel_lexer.mli

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@
99
(* *)
1010
(**************************************************************************)
1111

12-
val repl_file : Lexing.lexbuf -> Parsetree.repl_phrase list
12+
val repl_file :
13+
ocaml_version:(int * int) option
14+
-> Lexing.lexbuf
15+
-> Parsetree.repl_phrase list

lib/Toplevel_lexer.mll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ and phrase buf = parse
5252
| _ as c { Buffer.add_char buf c; phrase buf lexbuf }
5353

5454
{
55-
let repl_file lx =
55+
let repl_file ~ocaml_version lx =
5656
let x = token lx in
5757
let open Ocamlformat_parser_extended.Parsetree in
5858
List.fold_left (fun acc -> function
@@ -61,7 +61,7 @@ let repl_file lx =
6161
let filename = (Location.curr lx).loc_start.pos_fname in
6262
Lexing.set_filename cmd_lexbuf filename ;
6363
Lexing.set_position cmd_lexbuf pos_start ;
64-
{ prepl_phrase= Parse.toplevel_phrase cmd_lexbuf
64+
{ prepl_phrase= Parse.toplevel_phrase ~ocaml_version cmd_lexbuf
6565
; prepl_output= "" }
6666
:: acc
6767
| `Output ("", _) -> acc

test/passing/gen/dune.inc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3712,6 +3712,21 @@
37123712
(alias runtest)
37133713
(action (diff polytypes.ml.err polytypes.ml.stderr)))
37143714

3715+
(rule
3716+
(deps .ocamlformat dune-project)
3717+
(action
3718+
(with-stdout-to pre42_syntax.ml.stdout
3719+
(with-stderr-to pre42_syntax.ml.stderr
3720+
(run %{bin:ocamlformat} --name pre42_syntax.ml --margin-check --ocaml-version=4.1 %{dep:../tests/pre42_syntax.ml})))))
3721+
3722+
(rule
3723+
(alias runtest)
3724+
(action (diff pre42_syntax.ml.ref pre42_syntax.ml.stdout)))
3725+
3726+
(rule
3727+
(alias runtest)
3728+
(action (diff pre42_syntax.ml.err pre42_syntax.ml.stderr)))
3729+
37153730
(rule
37163731
(deps .ocamlformat dune-project)
37173732
(action
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
type nonrec = nonrec
2+
(** The [nonrec] keyword has been added in OCaml 4.2. *)
3+
4+
let nonrec nonrec : nonrec = nonrec

0 commit comments

Comments
 (0)