@@ -258,6 +258,24 @@ let recover (type a) : a Ast_passes.Ast0.t -> _ -> a = function
258
258
| Module_type -> failwith " no recovery for module_type"
259
259
| Expression -> failwith " no recovery for expression"
260
260
261
+ let strconst_mapper locs =
262
+ let constant self c =
263
+ match c with
264
+ | Parsetree. Pconst_string (_, {Location. loc_start; loc_end; _}, Some _)
265
+ ->
266
+ locs := (loc_start.Lexing. pos_cnum, loc_end.Lexing. pos_cnum) :: ! locs ;
267
+ c
268
+ | _ -> Ast_mapper. default_mapper.constant self c
269
+ in
270
+ {Ast_mapper. default_mapper with constant}
271
+
272
+ let collect_strlocs (type a ) (fgN : a Ast_passes.Ast_final.t ) (ast : a ) :
273
+ (int * int ) list =
274
+ let locs = ref [] in
275
+ let _ = Ast_passes.Ast_final. map fgN (strconst_mapper locs) ast in
276
+ let compare (c1 , _ ) (c2 , _ ) = Stdlib. compare c1 c2 in
277
+ List. sort ~compare ! locs
278
+
261
279
let format (type a b ) (fg0 : a Ast_passes.Ast0.t )
262
280
(fgN : b Ast_passes.Ast_final.t ) ?output_file ~input_name ~prev_source
263
281
~parsed conf opts =
@@ -307,7 +325,8 @@ let format (type a b) (fg0 : a Ast_passes.Ast0.t)
307
325
if opts.Conf. margin_check then
308
326
check_margin conf ~fmted
309
327
~filename: (Option. value output_file ~default: input_name) ;
310
- Ok fmted )
328
+ let strlocs = collect_strlocs fgN t.ast in
329
+ Ok (strlocs, fmted) )
311
330
else
312
331
let exn_args () =
313
332
[(" output file" , dump_formatted ~suffix: " .invalid-ast" fmted)]
@@ -412,29 +431,34 @@ let parse_result ?(f = Ast_passes.Ast0.Parse.ast) fragment conf ~source
412
431
| exception exn -> Error (Error. Invalid_source {exn ; input_name})
413
432
| parsed -> Ok parsed
414
433
415
- let normalize_eol ~line_endings s =
434
+ let normalize_eol ~strlocs ~ line_endings s =
416
435
let buf = Buffer. create (String. length s) in
417
- let rec loop seen_cr i =
418
- if i = String. length s then (
419
- if seen_cr then Buffer. add_char buf '\r' ;
420
- Buffer. contents buf )
436
+ let add_cr n = Buffer. add_string buf (String. init n ~f: (fun _ -> '\r' )) in
437
+ let rec normalize_segment ~seen_cr i stop =
438
+ if i = stop then add_cr seen_cr
421
439
else
422
- match (s.[i], line_endings) with
423
- | '\r' , _ ->
424
- if seen_cr then Buffer. add_char buf '\r' ;
425
- loop true (i + 1 )
426
- | '\n' , `Crlf ->
427
- Buffer. add_string buf " \r\n " ;
428
- loop false (i + 1 )
429
- | '\n' , `Lf ->
430
- Buffer. add_char buf '\n' ;
431
- loop false (i + 1 )
432
- | c , _ ->
433
- if seen_cr then Buffer. add_char buf '\r' ;
440
+ match s.[i] with
441
+ | '\r' -> normalize_segment ~seen_cr: (seen_cr + 1 ) (i + 1 ) stop
442
+ | '\n' ->
443
+ Buffer. add_string buf
444
+ (match line_endings with `Crlf -> " \r\n " | `Lf -> " \n " ) ;
445
+ normalize_segment ~seen_cr: 0 (i + 1 ) stop
446
+ | c ->
447
+ add_cr seen_cr ;
434
448
Buffer. add_char buf c ;
435
- loop false (i + 1 )
449
+ normalize_segment ~seen_cr: 0 (i + 1 ) stop
450
+ in
451
+ let rec loop locs i =
452
+ match locs with
453
+ | [] ->
454
+ normalize_segment ~seen_cr: 0 i (String. length s) ;
455
+ Buffer. contents buf
456
+ | (start , stop ) :: xs ->
457
+ normalize_segment ~seen_cr: 0 i start ;
458
+ Buffer. add_substring buf s ~pos: start ~len: (stop - start) ;
459
+ loop xs stop
436
460
in
437
- loop false 0
461
+ loop strlocs 0
438
462
439
463
let parse_and_format (type a b ) (fg0 : a Ast_passes.Ast0.t )
440
464
(fgN : b Ast_passes.Ast_final.t ) ?output_file ~input_name ~source conf
@@ -445,8 +469,8 @@ let parse_and_format (type a b) (fg0 : a Ast_passes.Ast0.t)
445
469
let parsed = {parsed with ast= Ast_passes. run fg0 fgN parsed.ast} in
446
470
format fg0 fgN ?output_file ~input_name ~prev_source: source ~parsed conf
447
471
opts
448
- >> = fun formatted ->
449
- Ok (normalize_eol ~line_endings: conf.Conf. line_endings formatted)
472
+ >> = fun ( strlocs , formatted ) ->
473
+ Ok (normalize_eol ~strlocs ~ line_endings: conf.Conf. line_endings formatted)
450
474
451
475
let parse_and_format = function
452
476
| Syntax. Structure -> parse_and_format Structure Structure
@@ -483,7 +507,7 @@ let numeric (type a b) (fg0 : a list Ast_passes.Ast0.t)
483
507
let parsed = {parsed with ast= Ast_passes. run fg0 fgN parsed.ast} in
484
508
let {ast= parsed_ast; source= parsed_src; _} = parsed in
485
509
match format fg0 fgN ~input_name ~prev_source: src ~parsed conf opts with
486
- | Ok fmted_src -> (
510
+ | Ok ( _ , fmted_src ) -> (
487
511
match parse_result fg0 ~source: fmted_src conf ~input_name with
488
512
| Ok {ast = fmted_ast ; source = fmted_src ; _} ->
489
513
let fmted_ast = Ast_passes. run fg0 fgN fmted_ast in
0 commit comments