@@ -304,11 +304,13 @@ module Transform = struct
304304 in
305305 { t with impl = Some map_impl; intf = Some map_intf }
306306
307+ let builtin_context_free_name = " <builtin:context-free>"
308+
307309 let builtin_of_context_free_rewriters ~hook ~rules ~enclose_impl ~enclose_intf
308310 ~input_name =
309311 merge_into_generic_mappers ~hook ~input_name
310312 {
311- name = " <builtin:context-free> " ;
313+ name = builtin_context_free_name ;
312314 aliases = [] ;
313315 impl = None ;
314316 intf = None ;
@@ -323,6 +325,21 @@ module Transform = struct
323325 registered_at = Caller_id. get ~skip: [] ;
324326 }
325327
328+ (* Meant to be used after partitioning *)
329+ let rewrites_not_context_free t =
330+ match t with
331+ | { name; _ } when String. equal name builtin_context_free_name -> false
332+ | {
333+ impl = None ;
334+ intf = None ;
335+ instrument = None ;
336+ preprocess_impl = None ;
337+ preprocess_intf = None ;
338+ _;
339+ } ->
340+ false
341+ | _ -> true
342+
326343 let partition_transformations ts =
327344 let before_instrs, after_instrs, rest =
328345 List. fold_left ts ~init: ([] , [] , [] ) ~f: (fun (bef_i , aft_i , rest ) t ->
@@ -528,11 +545,21 @@ let get_whole_ast_passes ~embed_errors ~hook ~expect_mismatch_handler ~tool_name
528545 linters @ preprocess @ before_instrs @ make_generic cts @ after_instrs
529546
530547let apply_transforms ~tool_name ~file_path ~field ~lint_field ~dropped_so_far
531- ~hook ~expect_mismatch_handler ~input_name ~embed_errors ast =
548+ ~hook ~expect_mismatch_handler ~input_name ~embed_errors ?rewritten ast =
549+ let _ = rewritten in
532550 let cts =
533551 get_whole_ast_passes ~tool_name ~embed_errors ~hook ~expect_mismatch_handler
534552 ~input_name
535553 in
554+ (match rewritten with
555+ | None -> ()
556+ | Some rewritten -> (
557+ match List. filter cts ~f: Transform. rewrites_not_context_free with
558+ | [] -> ()
559+ | _ ->
560+ (* We won't be able to accurately tell whether any rewriting has
561+ happened *)
562+ rewritten := true ));
536563 let finish (ast , _dropped , lint_errors , errors ) =
537564 ( ast,
538565 List. map lint_errors ~f: (fun (loc , s ) ->
@@ -633,8 +660,8 @@ let sort_errors_by_loc errors =
633660
634661(* $*)
635662
636- let map_structure_gen st ~tool_name ~hook ~expect_mismatch_handler ~input_name
637- ~embed_errors =
663+ let map_structure_gen ~tool_name ~hook ~expect_mismatch_handler ~input_name
664+ ~embed_errors ? rewritten st =
638665 Cookies. acknowledge_cookies T ;
639666 if ! perform_checks then (
640667 Attribute. reset_checks () ;
@@ -693,7 +720,7 @@ let map_structure_gen st ~tool_name ~hook ~expect_mismatch_handler ~input_name
693720 ~field: (fun (ct : Transform.t ) -> ct.impl)
694721 ~lint_field: (fun (ct : Transform.t ) -> ct.lint_impl)
695722 ~dropped_so_far: Attribute. dropped_so_far_structure ~hook
696- ~expect_mismatch_handler ~input_name ~embed_errors
723+ ~expect_mismatch_handler ~input_name ~embed_errors ?rewritten
697724 in
698725 st |> lint lint_errors |> cookies_and_check |> with_errors (List. rev errors)
699726
@@ -703,14 +730,14 @@ let map_structure st =
703730 ~tool_name: (Astlib.Ast_metadata. tool_name () )
704731 ~hook: Context_free.Generated_code_hook. nop
705732 ~expect_mismatch_handler: Context_free.Expect_mismatch_handler. nop
706- ~input_name: None ~embed_errors: false
733+ ~input_name: None ~embed_errors: false ?rewritten: None
707734 with
708735 | ast -> ast
709736
710737(* $ str_to_sig _last_text_block *)
711738
712- let map_signature_gen sg ~tool_name ~hook ~expect_mismatch_handler ~input_name
713- ~embed_errors =
739+ let map_signature_gen ~tool_name ~hook ~expect_mismatch_handler ~input_name
740+ ~embed_errors ? rewritten sg =
714741 Cookies. acknowledge_cookies T ;
715742 if ! perform_checks then (
716743 Attribute. reset_checks () ;
@@ -769,7 +796,7 @@ let map_signature_gen sg ~tool_name ~hook ~expect_mismatch_handler ~input_name
769796 ~field: (fun (ct : Transform.t ) -> ct.intf)
770797 ~lint_field: (fun (ct : Transform.t ) -> ct.lint_intf)
771798 ~dropped_so_far: Attribute. dropped_so_far_signature ~hook
772- ~expect_mismatch_handler ~input_name ~embed_errors
799+ ~expect_mismatch_handler ~input_name ~embed_errors ?rewritten
773800 in
774801 sg |> lint lint_errors |> cookies_and_check |> with_errors (List. rev errors)
775802
@@ -779,7 +806,7 @@ let map_signature sg =
779806 ~tool_name: (Astlib.Ast_metadata. tool_name () )
780807 ~hook: Context_free.Generated_code_hook. nop
781808 ~expect_mismatch_handler: Context_free.Expect_mismatch_handler. nop
782- ~input_name: None ~embed_errors: false
809+ ~input_name: None ~embed_errors: false ?rewritten: None
783810 with
784811 | ast -> ast
785812
@@ -917,6 +944,7 @@ type output_mode =
917944 | Dparsetree
918945 | Reconcile of Reconcile .mode
919946 | Null
947+ | Dune_optional_output
920948
921949(* $*)
922950let extract_cookies_str st =
@@ -1036,14 +1064,14 @@ struct
10361064 let set x = t.data < - Some x
10371065end
10381066
1039- let process_ast ( ast : Intf_or_impl.t ) ~input_name ~tool_name ~hook
1040- ~expect_mismatch_handler ~ embed_errors =
1067+ let process_ast ~input_name ~tool_name ~hook ~ expect_mismatch_handler
1068+ ~embed_errors ? rewritten ( ast : Intf_or_impl.t ) =
10411069 match ast with
10421070 | Intf x ->
10431071 let ast =
10441072 match
10451073 map_signature_gen x ~tool_name ~hook ~expect_mismatch_handler
1046- ~input_name: (Some input_name) ~embed_errors
1074+ ~input_name: (Some input_name) ~embed_errors ?rewritten
10471075 with
10481076 | ast -> ast
10491077 in
@@ -1052,18 +1080,28 @@ let process_ast (ast : Intf_or_impl.t) ~input_name ~tool_name ~hook
10521080 let ast =
10531081 match
10541082 map_structure_gen x ~tool_name ~hook ~expect_mismatch_handler
1055- ~input_name: (Some input_name) ~embed_errors
1083+ ~input_name: (Some input_name) ~embed_errors ?rewritten
10561084 with
10571085 | ast -> ast
10581086 in
10591087 Intf_or_impl. Impl ast
10601088
1089+ let pp_ast ~output (ast : Intf_or_impl.t ) =
1090+ with_output output ~binary: false ~f: (fun oc ->
1091+ let ppf = Stdlib.Format. formatter_of_out_channel oc in
1092+ (match ast with
1093+ | Intf ast -> Pprintast. signature ppf ast
1094+ | Impl ast -> Pprintast. structure ppf ast);
1095+ let null_ast = match ast with Intf [] | Impl [] -> true | _ -> false in
1096+ if not null_ast then Stdlib.Format. pp_print_newline ppf () )
1097+
10611098let process_file (kind : Kind.t ) fn ~input_name ~relocate ~output_mode
10621099 ~embed_errors ~output =
10631100 File_property. reset_all () ;
10641101 List. iter (List. rev ! process_file_hooks) ~f: (fun f -> f () );
10651102 corrections := [] ;
10661103 let replacements = ref [] in
1104+ let rewritten = ref false in
10671105 let tool_name = " ppx_driver" in
10681106 let hook : Context_free.Generated_code_hook.t =
10691107 match output_mode with
@@ -1075,6 +1113,7 @@ let process_file (kind : Kind.t) fn ~input_name ~relocate ~output_mode
10751113 (Reconcile.Replacement. make () ~context: (Extension context)
10761114 ~start: loc.loc_start ~stop: loc.loc_end ~repl: generated));
10771115 }
1116+ | Dune_optional_output -> { f = (fun _ _ _ -> rewritten := true ) }
10781117 | _ -> Context_free.Generated_code_hook. nop
10791118 in
10801119 let expect_mismatch_handler : Context_free.Expect_mismatch_handler.t =
@@ -1097,7 +1136,7 @@ let process_file (kind : Kind.t) fn ~input_name ~relocate ~output_mode
10971136 let ast =
10981137 extract_cookies ast
10991138 |> process_ast ~input_name ~tool_name ~hook ~expect_mismatch_handler
1100- ~embed_errors
1139+ ~embed_errors ~rewritten
11011140 in
11021141 (input_fname, input_version, ast)
11031142 with exn when embed_errors ->
@@ -1134,16 +1173,8 @@ let process_file (kind : Kind.t) fn ~input_name ~relocate ~output_mode
11341173
11351174 (match output_mode with
11361175 | Null -> ()
1137- | Pretty_print ->
1138- with_output output ~binary: false ~f: (fun oc ->
1139- let ppf = Stdlib.Format. formatter_of_out_channel oc in
1140- (match ast with
1141- | Intf ast -> Pprintast. signature ppf ast
1142- | Impl ast -> Pprintast. structure ppf ast);
1143- let null_ast =
1144- match ast with Intf [] | Impl [] -> true | _ -> false
1145- in
1146- if not null_ast then Stdlib.Format. pp_print_newline ppf () )
1176+ | Pretty_print -> pp_ast ~output ast
1177+ | Dune_optional_output -> if ! rewritten then pp_ast ~output ast
11471178 | Dump_ast ->
11481179 with_output output ~binary: true ~f: (fun oc ->
11491180 Ast_io. write oc
@@ -1191,7 +1222,10 @@ let set_output_mode mode =
11911222 match (! output_mode, mode) with
11921223 | Pretty_print , _ -> output_mode := mode
11931224 | _ , Pretty_print -> assert false
1194- | Dump_ast , Dump_ast | Dparsetree , Dparsetree -> ()
1225+ | Dune_optional_output , Dune_optional_output
1226+ | Dump_ast , Dump_ast
1227+ | Dparsetree , Dparsetree ->
1228+ ()
11951229 | Reconcile a , Reconcile b when Poly. equal a b -> ()
11961230 | x , y ->
11971231 let arg_of_output_mode = function
@@ -1201,6 +1235,7 @@ let set_output_mode mode =
12011235 | Reconcile Using_line_directives -> " -reconcile"
12021236 | Reconcile Delimiting_generated_blocks -> " -reconcile-with-comments"
12031237 | Null -> " -null"
1238+ | Dune_optional_output -> " -dune-optional-output"
12041239 in
12051240 raise
12061241 (Arg. Bad
@@ -1409,6 +1444,9 @@ let standalone_args =
14091444 ( " -corrected-suffix" ,
14101445 Arg. Set_string corrected_suffix,
14111446 " SUFFIX Suffix to append to corrected files" );
1447+ ( " -dune-optional-output" ,
1448+ Arg. Unit (fun () -> set_output_mode Dune_optional_output ),
1449+ " For dune's internal use only" );
14121450 ]
14131451
14141452let get_args ?(standalone_args = standalone_args) () =
0 commit comments