@@ -5,8 +5,11 @@ var format_usage = `Usage: rescript format <options> [files]
55\`rescript format\` formats the current directory
66` ;
77var child_process = require ( "child_process" ) ;
8+ var util = require ( "node:util" ) ;
9+ var asyncExecFile = util . promisify ( child_process . execFile ) ;
810var path = require ( "path" ) ;
911var fs = require ( "fs" ) ;
12+ var asyncFs = fs . promises ;
1013/**
1114 * @type {arg.stringref }
1215 */
@@ -17,6 +20,11 @@ var stdin = { val: undefined };
1720 */
1821var format = { val : undefined } ;
1922
23+ /**
24+ * @type {arg.boolref }
25+ */
26+ var check = { val : undefined } ;
27+
2028/**
2129 * @type {arg.specs }
2230 */
@@ -27,12 +35,16 @@ var specs = [
2735 `[.res|.resi|.ml|.mli] Read the code from stdin and print
2836the formatted code to stdout in ReScript syntax` ,
2937 ] ,
30- // ml|mli
3138 [
3239 "-all" ,
3340 { kind : "Unit" , data : { kind : "Unit_set" , data : format } } ,
3441 "Format the whole project " ,
3542 ] ,
43+ [
44+ "-check" ,
45+ { kind : "Unit" , data : { kind : "Unit_set" , data : check } } ,
46+ "Check formatting only" ,
47+ ] ,
3648] ;
3749var formattedStdExtensions = [ ".res" , ".resi" , ".ml" , ".mli" ] ;
3850var formattedFileExtensions = [ ".res" , ".resi" ] ;
@@ -55,12 +67,55 @@ async function readStdin() {
5567 return Buffer . concat ( chunks ) . toString ( "utf8" ) ;
5668}
5769
70+ /**
71+ * @param {string[] } files
72+ * @param {string } bsc_exe
73+ * @param {(x: string) => boolean } isSupportedFile
74+ * @param {boolean } checkFormatting
75+ */
76+ async function formatFiles ( files , bsc_exe , isSupportedFile , checkFormatting ) {
77+ var incorrectlyFormattedFiles = 0 ;
78+ try {
79+ const _promises = await Promise . all (
80+ files . map ( async file => {
81+ if ( isSupportedFile ( file ) ) {
82+ const flags = checkFormatting
83+ ? [ "-format" , file ]
84+ : [ "-o" , file , "-format" , file ] ;
85+ const { stdout } = await asyncExecFile ( bsc_exe , flags ) ;
86+ if ( check . val ) {
87+ const original = await asyncFs . readFile ( file , "utf-8" ) ;
88+ if ( original != stdout ) {
89+ console . error ( "[format check]" , file ) ;
90+ incorrectlyFormattedFiles ++ ;
91+ }
92+ }
93+ }
94+ return null ;
95+ } )
96+ ) ;
97+ } catch ( err ) {
98+ console . error ( err ) ;
99+ process . exit ( 2 ) ;
100+ }
101+ if ( incorrectlyFormattedFiles > 0 ) {
102+ if ( incorrectlyFormattedFiles == 1 ) {
103+ console . error ( "The file listed above needs formatting" ) ;
104+ } else {
105+ console . error (
106+ `The ${ incorrectlyFormattedFiles } files listed above need formatting`
107+ ) ;
108+ }
109+ process . exit ( 3 ) ;
110+ }
111+ }
112+
58113/**
59114 * @param {string[] } argv
60115 * @param {string } rescript_exe
61116 * @param {string } bsc_exe
62117 */
63- function main ( argv , rescript_exe , bsc_exe ) {
118+ async function main ( argv , rescript_exe , bsc_exe ) {
64119 var isSupportedFile = hasExtension ( formattedFileExtensions ) ;
65120 var isSupportedStd = hasExtension ( formattedStdExtensions ) ;
66121
@@ -95,26 +150,12 @@ function main(argv, rescript_exe, bsc_exe) {
95150 process . exit ( 2 ) ;
96151 }
97152 files = output . stdout . split ( "\n" ) . map ( x => x . trim ( ) ) ;
98- var hasError = false ;
99- for ( let arg of files ) {
100- if ( isSupportedFile ( arg ) ) {
101- // console.log(`processing ${arg}`);
102- child_process . execFile (
103- bsc_exe ,
104- [ "-o" , arg , "-format" , arg ] ,
105- ( error , _stdout , stderr ) => {
106- if ( error !== null ) {
107- console . error ( stderr ) ;
108- hasError = true ;
109- }
110- }
111- ) ;
112- }
113- }
114- if ( hasError ) {
153+ await formatFiles ( files , bsc_exe , isSupportedFile , check . val ) ;
154+ } else if ( use_stdin ) {
155+ if ( check . val ) {
156+ console . error ( "format -stdin cannot be used with -check flag" ) ;
115157 process . exit ( 2 ) ;
116158 }
117- } else if ( use_stdin ) {
118159 if ( isSupportedStd ( use_stdin ) ) {
119160 var crypto = require ( "crypto" ) ;
120161 var os = require ( "os" ) ;
@@ -144,7 +185,7 @@ function main(argv, rescript_exe, bsc_exe) {
144185 ) ;
145186 } ) ( ) ;
146187 } else {
147- console . error ( `Unsupported exetnsion ${ use_stdin } ` ) ;
188+ console . error ( `Unsupported extension ${ use_stdin } ` ) ;
148189 console . error ( `Supported extensions: ${ formattedStdExtensions } ` ) ;
149190 process . exit ( 2 ) ;
150191 }
@@ -163,24 +204,7 @@ function main(argv, rescript_exe, bsc_exe) {
163204 process . exit ( 2 ) ;
164205 }
165206 }
166- var hasError = false ;
167- files . forEach ( file => {
168- var write = isSupportedFile ( file ) ;
169- var flags = write ? [ "-o" , file , "-format" , file ] : [ "-format" , file ] ;
170- child_process . execFile ( bsc_exe , flags , ( error , stdout , stderr ) => {
171- if ( error === null ) {
172- if ( ! write ) {
173- process . stdout . write ( stdout ) ;
174- }
175- } else {
176- console . error ( stderr ) ;
177- hasError = true ;
178- }
179- } ) ;
180- } ) ;
181- if ( hasError ) {
182- process . exit ( 2 ) ;
183- }
207+ await formatFiles ( files , bsc_exe , isSupportedFile , check . val ) ;
184208 }
185209 } catch ( e ) {
186210 if ( e instanceof arg . ArgError ) {
0 commit comments