Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/driver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1604,3 +1604,8 @@ let () =
Fn.id)
(fun ~ctxt:_ items -> Utils.prettify_odoc_attributes#signature items);
]

type transformation = Transform.t

let transform_name transform = transform.Transform.name
let all_transforms = Transform.all
5 changes: 5 additions & 0 deletions src/driver.mli
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ val pretty : unit -> bool
(** If [true], code transformations should avoid generating code that is not
strictly necessary, such as extra type annotations. *)

type transformation

val transform_name : transformation -> string
val all_transforms : transformation list ref

(**/**)

val map_structure : structure -> structure
Expand Down
13 changes: 13 additions & 0 deletions test/driver/manual-transforms-order/driver_a_first.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
open Ppxlib

let reorder_transforms l =
List.stable_sort
(fun t t' ->
match (Driver.transform_name t, Driver.transform_name t') with
| "exp_to_a", _ -> -1
| _, "exp_to_a" -> 1
| _, _ -> 0)
l

let () = Driver.all_transforms := reorder_transforms !Driver.all_transforms
let () = Driver.standalone ()
13 changes: 13 additions & 0 deletions test/driver/manual-transforms-order/driver_b_first.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
open Ppxlib

let reorder_transforms l =
List.stable_sort
(fun t t' ->
match (Driver.transform_name t, Driver.transform_name t') with
| "exp_to_b", _ -> -1
| _, "exp_to_b" -> 1
| _, _ -> 0)
l

let () = Driver.all_transforms := reorder_transforms !Driver.all_transforms
let () = Driver.standalone ()
25 changes: 25 additions & 0 deletions test/driver/manual-transforms-order/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
(library
(name exp_to_a)
(kind ppx_rewriter)
(modules exp_to_a)
(libraries ppxlib))

(library
(name exp_to_b)
(kind ppx_rewriter)
(modules exp_to_b)
(libraries ppxlib))

(executable
(name driver_a_first)
(modules driver_a_first)
(libraries ppxlib exp_to_a exp_to_b))

(executable
(name driver_b_first)
(modules driver_b_first)
(libraries ppxlib exp_to_a exp_to_b))

(cram
(package ppxlib)
(deps driver_a_first.exe driver_b_first.exe))
15 changes: 15 additions & 0 deletions test/driver/manual-transforms-order/exp_to_a.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
open Ppxlib

let mapper =
object
inherit Ast_traverse.map as super

method! expression_desc ed =
match ed with
| Pexp_extension ({ txt = "exp"; loc }, PStr []) ->
Pexp_ident { txt = Lident "a"; loc }
| _ -> super#expression_desc ed
end

let impl str = mapper#structure str
let () = Driver.register_transformation ~impl "exp_to_a"
15 changes: 15 additions & 0 deletions test/driver/manual-transforms-order/exp_to_b.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
open Ppxlib

let mapper =
object
inherit Ast_traverse.map as super

method! expression_desc ed =
match ed with
| Pexp_extension ({ txt = "exp"; loc }, PStr []) ->
Pexp_ident { txt = Lident "b"; loc }
| _ -> super#expression_desc ed
end

let impl str = mapper#structure str
let () = Driver.register_transformation ~impl "exp_to_b"
26 changes: 26 additions & 0 deletions test/driver/manual-transforms-order/run.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
This test is here to ensure that the very minimal API we provide to ensure
users can eventually custromize the order of global transformations (i.e.
structure -> structure and signature -> signature) does work as intended.

For this test we have two different ppx-es: exp_to_a and exp_to_b which both
rewrite the same [%exp] into either a or b.

We have two different drivers, both of them have both ppx-es linked but one
reorders transformations to ensure exp_to_a is first in the list and the other
that exp_to_b is first.

If we consider the following ml file:

$ cat > test.ml << EOF
> let x = [%exp]
> EOF

If we run the driver with exp_to_a first:

$ ./driver_a_first.exe test.ml
let x = a

And the one with exp_to_b first:

$ ./driver_b_first.exe test.ml
let x = b
Loading