@@ -54,60 +54,67 @@ let printMl ~isInterface ~filename =
5454 parseResult.parsetree
5555
5656(* How does printing Reason to Res work?
57- * -> Run refmt in parallel with the program,
58- * the standard input and standard output of the refmt command are redirected
59- * to pipes connected to the two returned channels
60- * -> Read the source code of "filename"
61- * -> Write the source code to output channel (i.e. the input of refmt)
62- * -> Read the marshalled ast from the input channel (i.e. the output of refmt)
57+ * -> open a tempfile
58+ * -> write the source code found in "filename" into the tempfile
59+ * -> run refmt in-place in binary mode on the tempfile,
60+ * mutates contents tempfile with marshalled AST.j
61+ * -> read the marshalled ast (from the binary output in the tempfile)
6362 * -> re-read the original "filename" and extract string + comment data
6463 * -> put the comment- and string data back into the unmarshalled parsetree
65- * -> normalize the ast to conform to the napkin printer
6664 * -> pretty print to res
6765 * -> take a deep breath and exhale slowly *)
6866let printReason ~refmtPath ~isInterface ~filename =
69- (* Run refmt in parallel with the program *)
70- let refmtCmd = Printf. sprintf " %s --print=binary --interface=%b" refmtPath isInterface in
71- let (refmtOutput, refmtInput) = Unix. open_process refmtCmd in
72- (* Read the source code of "filename" *)
73- let source = IO. readFile ~filename in
74- (* Write the source code to output channel (i.e. the input of refmt) *)
75- output_string refmtInput source;
76- close_out refmtInput;
77- (* Read the marshalled ast from the input channel (i.e. the output of refmt) *)
78- let magic = if isInterface then Config. ast_intf_magic_number else Config. ast_impl_magic_number in
79- ignore ((really_input_string [@ doesNotRaise]) refmtOutput (String. length magic));
80- ignore (input_value refmtOutput);
81- let ast = input_value refmtOutput in
82- close_in refmtOutput;
83- (* re-read the original "filename" and extract string + comment data *)
84- let (comments, stringData) = Napkin_reason_binary_driver. extractConcreteSyntax filename in
85- if isInterface then
86- let ast = ast
67+ (* open a tempfile *)
68+ let (tempFilename, chan) =
69+ (* refmt is just a prefix, `open_temp_file` takes care of providing a random name
70+ * It tries 1000 times in the case of a name conflict.
71+ * In practise this means that we shouldn't worry too much about filesystem races *)
72+ Filename. open_temp_file " refmt" (if isInterface then " .rei" else " .re" ) in
73+ close_out chan;
74+ (* Write the source code found in "filename" into the tempfile *)
75+ IO. writeFile ~filename: tempFilename ~content: (IO. readFile ~filename );
76+ let cmd = Printf. sprintf " %s --print=binary --in-place --interface=%b %s" refmtPath isInterface tempFilename in
77+ (* run refmt in-place in binary mode on the tempfile *)
78+ ignore (Sys. command cmd);
79+ let result =
80+ if isInterface then
81+ let parseResult =
82+ (* read the marshalled ast (from the binary output in the tempfile) *)
83+ Napkin_reason_binary_driver. parsingEngine.parseInterface ~for Printer:true ~filename: tempFilename in
84+ (* re-read the original "filename" and extract string + comment data *)
85+ let (comments, stringData) = Napkin_reason_binary_driver. extractConcreteSyntax filename in
8786 (* put the comment- and string data back into the unmarshalled parsetree *)
88- |> Napkin_ast_conversion. replaceStringLiteralSignature stringData
89- (* normalize the ast to conform to the napkin printer *)
90- |> Napkin_ast_conversion. normalizeReasonAritySignature ~for Printer:true
91- |> Napkin_ast_conversion. signature
92- in
93- (* pretty print to res *)
94- Napkin_printer. printInterface
95- ~width: defaultPrintWidth
96- ~comments: comments
97- ast
98- else
99- let ast = ast
87+ let parseResult = {
88+ parseResult with
89+ parsetree =
90+ parseResult.parsetree |> Napkin_ast_conversion. replaceStringLiteralSignature stringData;
91+ comments = comments;
92+ } in
93+ (* pretty print to res *)
94+ Napkin_printer. printInterface
95+ ~width: defaultPrintWidth
96+ ~comments: parseResult.comments
97+ parseResult.parsetree
98+ else
99+ let parseResult =
100+ (* read the marshalled ast (from the binary output in the tempfile) *)
101+ Napkin_reason_binary_driver. parsingEngine.parseImplementation ~for Printer:true ~filename: tempFilename in
102+ let (comments, stringData) = Napkin_reason_binary_driver. extractConcreteSyntax filename in
100103 (* put the comment- and string data back into the unmarshalled parsetree *)
101- |> Napkin_ast_conversion. replaceStringLiteralStructure stringData
102- (* normalize the ast to conform to the napkin printer *)
103- |> Napkin_ast_conversion. normalizeReasonArityStructure ~for Printer:true
104- |> Napkin_ast_conversion. structure
105- in
106- (* pretty print to res *)
107- Napkin_printer. printImplementation
108- ~width: defaultPrintWidth
109- ~comments: comments
110- ast
104+ let parseResult = {
105+ parseResult with
106+ parsetree =
107+ parseResult.parsetree |> Napkin_ast_conversion. replaceStringLiteralStructure stringData;
108+ comments = comments;
109+ } in
110+ (* pretty print to res *)
111+ Napkin_printer. printImplementation
112+ ~width: defaultPrintWidth
113+ ~comments: parseResult.comments
114+ parseResult.parsetree
115+ in
116+ Sys. remove tempFilename;
117+ result
111118[@@ raises Sys_error ]
112119
113120(* print the given file named input to from "language" to res, general interface exposed by the compiler *)
0 commit comments