Skip to content

Commit 5b2c5bd

Browse files
authored
Fix compile status with help command (rescript-lang#6439)
* Fx compile status with help command * Update changelog * Update tests * Improve cli consistency * Finish cli help consistency improvements * Update changelog * Fix build help
1 parent ab0e9e8 commit 5b2c5bd

File tree

9 files changed

+367
-72
lines changed

9 files changed

+367
-72
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
- Fix printing of exotic JSX names https://github.com/rescript-lang/rescript-compiler/pull/6451
2929
- Fix locations when code with `await` fails to compile (all locations would point to the internal function `unsafe_await`) https://github.com/rescript-lang/rescript-compiler/pull/6452
3030
- Fix renaming fields (with @as) in inline records doesn't work when destructuring https://github.com/rescript-lang/rescript-compiler/pull/6456
31+
- Fix `rc.4` regressions:
32+
- Don't show compilation time when calling `rescript build -help` command. https://github.com/rescript-lang/rescript-compiler/pull/6439
3133

3234
#### :house: Internal
3335

@@ -37,6 +39,7 @@
3739

3840
- Add [`Deno`](https://deno.land/api?s=Deno) to reserved names, so that modules named `Deno` don't clash with the globally exposed `Deno` object. https://github.com/rescript-lang/rescript-compiler/pull/6428
3941
- Disable ESLint/TSLint on gentype outputs properly. https://github.com/rescript-lang/rescript-compiler/pull/6442
42+
- Improve `rescript` CLI to use `stdout`/`stderr` appropriately for help command's message. https://github.com/rescript-lang/rescript-compiler/pull/6439
4043

4144
# 11.0.0-rc.4
4245

jscomp/bsb/bsb_arg.ml

+4-4
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ let stop_raise ~usage ~(error : error) (speclist : t) =
7979
Ext_buffer.output_buffer stdout b;
8080
exit 0
8181
| Unknown s ->
82-
b +> "unknown option: '";
82+
b +> "Unknown option \"";
8383
b +> s;
84-
b +> "'.\n"
84+
b +> "\".\n"
8585
| Missing s ->
86-
b +> "option '";
86+
b +> "Option \"";
8787
b +> s;
88-
b +> "' needs an argument.\n");
88+
b +> "\" needs an argument.\n");
8989
usage_b b ~usage speclist;
9090
bad_arg (Ext_buffer.contents b)
9191

jscomp/bsb_exe/rescript_main.ml

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ let clean_usage =
9090
let build_usage =
9191
"Usage: rescript build <options> -- <ninja_options>\n\n\
9292
`rescript build` builds the project with dependencies\n\n\
93-
`rescript -- -h` for Ninja options (internal usage only; unstable)\n"
93+
`rescript build -- -h` for Ninja options (internal usage only; unstable)\n"
9494

9595
let install_target () =
9696
let ( // ) = Filename.concat in
@@ -234,6 +234,6 @@ let () =
234234
start.pos_lnum Ext_json_parse.report_error e;
235235
exit 2
236236
| Bsb_arg.Bad s | Sys_error s ->
237-
Format.fprintf Format.err_formatter "@{<error>Error:@} %s@." s;
237+
Format.fprintf Format.err_formatter "@{<error>Error:@} %s" s;
238238
exit 2
239239
| e -> Ext_pervasives.reraise e
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// @ts-check
2+
3+
const assert = require("assert");
4+
const child_process = require("child_process");
5+
6+
// Shows compile time for `rescript build` command
7+
let out = child_process.spawnSync(`../../../rescript`, ["build"], {
8+
encoding: "utf8",
9+
cwd: __dirname,
10+
});
11+
assert.match(
12+
out.stdout,
13+
new RegExp(`>>>> Start compiling
14+
Dependency Finished
15+
>>>> Finish compiling \\d+ mseconds`)
16+
);
17+
18+
// Shows compile time for `rescript` command
19+
out = child_process.spawnSync(`../../../rescript`, {
20+
encoding: "utf8",
21+
cwd: __dirname,
22+
});
23+
assert.match(
24+
out.stdout,
25+
new RegExp(`>>>> Start compiling
26+
Dependency Finished
27+
>>>> Finish compiling \\d+ mseconds`)
28+
);
29+
30+
// Doesn't show compile time for `rescript build -verbose` command
31+
// Because we can't be sure that -verbose is a valid argument
32+
// And bsb won't fail with a usage message.
33+
// It works this way not only for -verbose, but any other arg, including -h/--help/-help
34+
out = child_process.spawnSync(`../../../rescript`, ["build", "-verbose"], {
35+
encoding: "utf8",
36+
cwd: __dirname,
37+
});
38+
assert.match(
39+
out.stdout,
40+
new RegExp(
41+
`Package stack: test \nDependency Finished\nninja.exe -C lib/bs \n`
42+
)
43+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "test",
3+
"version": "0.1.0",
4+
"sources": []
5+
}

jscomp/build_tests/cli_help/input.js

+243
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
// @ts-check
2+
3+
const assert = require("assert");
4+
const child_process = require("child_process");
5+
6+
const cliHelp =
7+
"Usage: rescript <options> <subcommand>\n" +
8+
"\n" +
9+
"`rescript` is equivalent to `rescript build`\n" +
10+
"\n" +
11+
"Options:\n" +
12+
" -v, -version display version number\n" +
13+
" -h, -help display help\n" +
14+
"\n" +
15+
"Subcommands:\n" +
16+
" build\n" +
17+
" clean\n" +
18+
" format\n" +
19+
" convert\n" +
20+
" dump\n" +
21+
" help\n" +
22+
"\n" +
23+
"Run `rescript <subcommand> -h` for subcommand help. Examples:\n" +
24+
" rescript build -h\n" +
25+
" rescript format -h\n";
26+
27+
const buildHelp =
28+
"Usage: rescript build <options> -- <ninja_options>\n" +
29+
"\n" +
30+
"`rescript build` builds the project with dependencies\n" +
31+
"\n" +
32+
"`rescript build -- -h` for Ninja options (internal usage only; unstable)\n" +
33+
"\n" +
34+
"Options:\n" +
35+
" -w Watch mode\n" +
36+
" -ws [host]:port set up host & port for WebSocket build notifications\n" +
37+
" -verbose Set the output to be verbose\n" +
38+
" -with-deps *deprecated* This is the default behavior now. This option will be removed in a future release\n";
39+
40+
const cleanHelp =
41+
"Usage: rescript clean <options>\n" +
42+
"\n" +
43+
"`rescript clean` cleans build artifacts\n" +
44+
"\n" +
45+
"Options:\n" +
46+
" -verbose Set the output to be verbose\n" +
47+
" -with-deps *deprecated* This is the default behavior now. This option will be removed in a future release\n";
48+
49+
const formatHelp =
50+
"Usage: rescript format <options> [files]\n" +
51+
"\n" +
52+
"`rescript format` formats the current directory\n" +
53+
"\n" +
54+
"Options:\n" +
55+
" -stdin [.res|.resi|.ml|.mli] Read the code from stdin and print\n" +
56+
" the formatted code to stdout in ReScript syntax\n" +
57+
" -all Format the whole project \n" +
58+
" -check Check formatting for file or the whole project. Use `-all` to check the whole project\n";
59+
60+
const convertHelp =
61+
"Usage: rescript convert <options> [files]\n" +
62+
"\n" +
63+
"`rescript convert` converts the current directory\n" +
64+
"\n" +
65+
"**This command removes old OCaml files and creates new ReScript \n" +
66+
"files. Make sure your work is saved first!**\n" +
67+
"\n" +
68+
"Options:\n" +
69+
" -all Convert the whole project\n";
70+
71+
const dumpHelp =
72+
"Usage: rescript dump <options> [target]\n" +
73+
"`rescript dump` dumps the information for the target\n";
74+
75+
// Shows build help with --help arg
76+
let out = child_process.spawnSync(`../../../rescript`, ["build", "--help"], {
77+
encoding: "utf8",
78+
cwd: __dirname,
79+
});
80+
assert.equal(out.stdout, buildHelp);
81+
assert.equal(out.stderr, "");
82+
assert.equal(out.status, 0);
83+
84+
// FIXME: Help works incorrectly in watch mode
85+
out = child_process.spawnSync(`../../../rescript`, ["build", "-w", "--help"], {
86+
encoding: "utf8",
87+
cwd: __dirname,
88+
});
89+
// FIXME: Shouldn't have "Start compiling" for help
90+
assert.equal(out.stdout, ">>>> Start compiling\n" + buildHelp);
91+
// FIXME: Don't run the watcher when showing help
92+
assert.match(
93+
out.stderr,
94+
new RegExp(
95+
"Uncaught Exception Error: ENOENT: no such file or directory, watch 'bsconfig.json'\n"
96+
)
97+
);
98+
// FIXME: Should be 0
99+
assert.equal(out.status, 1);
100+
101+
// Shows build help with -h arg
102+
out = child_process.spawnSync(`../../../rescript`, ["build", "-h"], {
103+
encoding: "utf8",
104+
cwd: __dirname,
105+
});
106+
assert.equal(out.stdout, buildHelp);
107+
assert.equal(out.stderr, "");
108+
assert.equal(out.status, 0);
109+
110+
// Exits with build help with unknown arg
111+
out = child_process.spawnSync(`../../../rescript`, ["build", "-wtf"], {
112+
encoding: "utf8",
113+
cwd: __dirname,
114+
});
115+
assert.equal(out.stdout, "");
116+
assert.equal(out.stderr, 'Error: Unknown option "-wtf".\n' + buildHelp);
117+
assert.equal(out.status, 2);
118+
119+
// Shows cli help with --help arg
120+
out = child_process.spawnSync(`../../../rescript`, ["--help"], {
121+
encoding: "utf8",
122+
cwd: __dirname,
123+
});
124+
assert.equal(out.stdout, cliHelp);
125+
assert.equal(out.stderr, "");
126+
assert.equal(out.status, 0);
127+
128+
// Shows cli help with -h arg
129+
out = child_process.spawnSync(`../../../rescript`, ["-h"], {
130+
encoding: "utf8",
131+
cwd: __dirname,
132+
});
133+
assert.equal(out.stdout, cliHelp);
134+
assert.equal(out.stderr, "");
135+
assert.equal(out.status, 0);
136+
137+
// Shows cli help with help command
138+
out = child_process.spawnSync(`../../../rescript`, ["help"], {
139+
encoding: "utf8",
140+
cwd: __dirname,
141+
});
142+
assert.equal(out.stdout, cliHelp);
143+
assert.equal(out.stderr, "");
144+
assert.equal(out.status, 0);
145+
146+
// Shows cli help with unknown command
147+
out = child_process.spawnSync(`../../../rescript`, ["built"], {
148+
encoding: "utf8",
149+
cwd: __dirname,
150+
});
151+
assert.equal(out.stdout, "");
152+
assert.equal(out.stderr, `Error: Unknown command or flag "built".\n` + cliHelp);
153+
assert.equal(out.status, 2);
154+
155+
// Shows cli help with unknown args
156+
out = child_process.spawnSync(`../../../rescript`, ["-w"], {
157+
encoding: "utf8",
158+
cwd: __dirname,
159+
});
160+
assert.equal(out.stdout, "");
161+
assert.equal(out.stderr, `Error: Unknown command or flag "-w".\n` + cliHelp);
162+
assert.equal(out.status, 2);
163+
164+
// Shows clean help with --help arg
165+
out = child_process.spawnSync(`../../../rescript`, ["clean", "--help"], {
166+
encoding: "utf8",
167+
cwd: __dirname,
168+
});
169+
assert.equal(out.stdout, cleanHelp);
170+
assert.equal(out.stderr, "");
171+
assert.equal(out.status, 0);
172+
173+
// Shows clean help with -h arg
174+
out = child_process.spawnSync(`../../../rescript`, ["clean", "-h"], {
175+
encoding: "utf8",
176+
cwd: __dirname,
177+
});
178+
assert.equal(out.stdout, cleanHelp);
179+
assert.equal(out.stderr, "");
180+
assert.equal(out.status, 0);
181+
182+
// Exits with clean help with unknown arg
183+
out = child_process.spawnSync(`../../../rescript`, ["clean", "-wtf"], {
184+
encoding: "utf8",
185+
cwd: __dirname,
186+
});
187+
assert.equal(out.stdout, "");
188+
assert.equal(out.stderr, 'Error: Unknown option "-wtf".\n' + cleanHelp);
189+
assert.equal(out.status, 2);
190+
191+
// Shows format help with --help arg
192+
out = child_process.spawnSync(`../../../rescript`, ["format", "--help"], {
193+
encoding: "utf8",
194+
cwd: __dirname,
195+
});
196+
assert.equal(out.stdout, formatHelp);
197+
assert.equal(out.stderr, "");
198+
assert.equal(out.status, 0);
199+
200+
// Shows format help with -h arg
201+
out = child_process.spawnSync(`../../../rescript`, ["format", "-h"], {
202+
encoding: "utf8",
203+
cwd: __dirname,
204+
});
205+
assert.equal(out.stdout, formatHelp);
206+
assert.equal(out.stderr, "");
207+
assert.equal(out.status, 0);
208+
209+
// Shows convert help with --help arg
210+
out = child_process.spawnSync(`../../../rescript`, ["convert", "--help"], {
211+
encoding: "utf8",
212+
cwd: __dirname,
213+
});
214+
assert.equal(out.stdout, convertHelp);
215+
assert.equal(out.stderr, "");
216+
assert.equal(out.status, 0);
217+
218+
// Shows convert help with -h arg
219+
out = child_process.spawnSync(`../../../rescript`, ["convert", "-h"], {
220+
encoding: "utf8",
221+
cwd: __dirname,
222+
});
223+
assert.equal(out.stdout, convertHelp);
224+
assert.equal(out.stderr, "");
225+
assert.equal(out.status, 0);
226+
227+
// Shows dump help with --help arg
228+
out = child_process.spawnSync(`../../../rescript`, ["dump", "--help"], {
229+
encoding: "utf8",
230+
cwd: __dirname,
231+
});
232+
assert.equal(out.stdout, dumpHelp);
233+
assert.equal(out.stderr, "");
234+
assert.equal(out.status, 0);
235+
236+
// Shows dump help with -h arg
237+
out = child_process.spawnSync(`../../../rescript`, ["dump", "-h"], {
238+
encoding: "utf8",
239+
cwd: __dirname,
240+
});
241+
assert.equal(out.stdout, dumpHelp);
242+
assert.equal(out.stderr, "");
243+
assert.equal(out.status, 0);

jscomp/ext/bsc_args.ml

+4-4
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,13 @@ let stop_raise ~usage ~(error : error) (speclist : t) =
8686
Ext_buffer.output_buffer stdout b;
8787
exit 0
8888
| Unknown s ->
89-
b +> "unknown option: '";
89+
b +> "Unknown option \"";
9090
b +> s;
91-
b +> "'.\n"
91+
b +> "\".\n"
9292
| Missing s ->
93-
b +> "option '";
93+
b +> "Option \"";
9494
b +> s;
95-
b +> "' needs an argument.\n");
95+
b +> "\" needs an argument.\n");
9696
usage_b b ~usage speclist;
9797
bad_arg (Ext_buffer.contents b)
9898

0 commit comments

Comments
 (0)