Skip to content

Commit a15116a

Browse files
committed
Fix error handling when rescript.json parsing fails
1 parent cad989f commit a15116a

File tree

6 files changed

+109
-18
lines changed

6 files changed

+109
-18
lines changed

rewatch/src/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::helpers::emojis::*;
1616
use crate::helpers::{self};
1717
use crate::project_context::ProjectContext;
1818
use crate::{config, sourcedirs};
19-
use anyhow::{Result, anyhow};
19+
use anyhow::{Context, Result, anyhow};
2020
use build_types::*;
2121
use console::style;
2222
use indicatif::{ProgressBar, ProgressStyle};
@@ -501,7 +501,7 @@ pub fn build(
501501
plain_output,
502502
warn_error,
503503
)
504-
.map_err(|e| anyhow!("Could not initialize build. Error: {e}"))?;
504+
.with_context(|| "Could not initialize build")?;
505505

506506
match incremental_build(
507507
&mut build_state,

rewatch/src/main.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ fn main() -> Result<()> {
5656
(*build_args.warn_error).clone(),
5757
) {
5858
Err(e) => {
59-
println!("{e}");
59+
println!("{:#}", e);
6060
std::process::exit(1)
6161
}
6262
Ok(_) => {
@@ -76,17 +76,21 @@ fn main() -> Result<()> {
7676
);
7777
}
7878

79-
watcher::start(
79+
match watcher::start(
8080
&watch_args.filter,
8181
show_progress,
8282
&watch_args.folder,
8383
(*watch_args.after_build).clone(),
8484
*watch_args.create_sourcedirs,
8585
plain_output,
8686
(*watch_args.warn_error).clone(),
87-
);
88-
89-
Ok(())
87+
) {
88+
Err(e) => {
89+
println!("{:#}", e);
90+
std::process::exit(1)
91+
}
92+
Ok(_) => Ok(()),
93+
}
9094
}
9195
cli::Command::Clean { folder, dev } => {
9296
let _lock = get_lock(&folder);

rewatch/src/project_context.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::build::packages;
22
use crate::config::Config;
33
use crate::helpers;
44
use ahash::{AHashMap, AHashSet};
5-
use anyhow::Result;
5+
use anyhow::{Context, Result};
66
use anyhow::anyhow;
77
use log::debug;
88
use std::fmt;
@@ -167,8 +167,12 @@ fn is_config_listed_in_workspace(current_config: &Config, workspace_config: &Con
167167
impl ProjectContext {
168168
pub fn new(path: &Path) -> Result<ProjectContext> {
169169
let path = helpers::get_abs_path(path);
170-
let current_config = packages::read_config(&path)
171-
.map_err(|_| anyhow!("Could not read rescript.json at {}", path.to_string_lossy()))?;
170+
let current_config = packages::read_config(&path).with_context(|| {
171+
format!(
172+
"Could not read rescript.json at {}",
173+
path.to_string_lossy()
174+
)
175+
})?;
172176
let nearest_parent_config_path = match path.parent() {
173177
None => Err(anyhow!(
174178
"The current path \"{}\" does not have a parent folder",

rewatch/src/watcher.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::helpers::emojis::*;
88
use crate::lock::LOCKFILE;
99
use crate::queue::FifoQueue;
1010
use crate::queue::*;
11+
use anyhow::{Context, Result};
1112
use futures_timer::Delay;
1213
use notify::event::ModifyKind;
1314
use notify::{Config, Error, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
@@ -78,10 +79,10 @@ async fn async_watch(
7879
plain_output,
7980
warn_error,
8081
}: AsyncWatchArgs<'_>,
81-
) -> notify::Result<()> {
82+
) -> Result<()> {
8283
let mut build_state: build::build_types::BuildCommandState =
8384
build::initialize_build(None, filter, show_progress, path, plain_output, warn_error)
84-
.expect("Can't initialize build");
85+
.with_context(|| "Can't initialize build")?;
8586
let mut needs_compile_type = CompileType::Incremental;
8687
// create a mutex to capture if ctrl-c was pressed
8788
let ctrlc_pressed = Arc::new(Mutex::new(false));
@@ -324,7 +325,7 @@ pub fn start(
324325
create_sourcedirs: bool,
325326
plain_output: bool,
326327
warn_error: Option<String>,
327-
) {
328+
) -> Result<()> {
328329
futures::executor::block_on(async {
329330
let queue = Arc::new(FifoQueue::<Result<Event, Error>>::new());
330331
let producer = queue.clone();
@@ -341,7 +342,7 @@ pub fn start(
341342

342343
let path = Path::new(folder);
343344

344-
if let Err(e) = async_watch(AsyncWatchArgs {
345+
async_watch(AsyncWatchArgs {
345346
q: consumer,
346347
path,
347348
show_progress,
@@ -352,8 +353,5 @@ pub fn start(
352353
warn_error: warn_error.clone(),
353354
})
354355
.await
355-
{
356-
println!("{e:?}")
357-
}
358356
})
359357
}

rewatch/tests/experimental.sh

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,88 @@ fi
3838
mv rescript.json.bak rescript.json
3939

4040
success "experimental-features emits -enable-experimental twice as string list"
41+
42+
bold "Test: build surfaces experimental-features list parse error"
43+
44+
cp rescript.json rescript.json.bak
45+
46+
node -e '
47+
const fs = require("fs");
48+
const j = JSON.parse(fs.readFileSync("rescript.json", "utf8"));
49+
j["experimental-features"] = ["LetUnwrap"];
50+
fs.writeFileSync("rescript.json", JSON.stringify(j, null, 2));
51+
'
52+
53+
out=$(rewatch build 2>&1)
54+
status=$?
55+
56+
mv rescript.json.bak rescript.json
57+
rm -f lib/rescript.lock
58+
59+
if [ $status -eq 0 ]; then
60+
error "Expected build to fail for experimental-features list input"
61+
echo "$out"
62+
exit 1
63+
fi
64+
65+
echo "$out" | grep -q "Could not read rescript.json"
66+
if [ $? -ne 0 ]; then
67+
error "Missing rescript.json path context in build error"
68+
echo "$out"
69+
exit 1
70+
fi
71+
72+
echo "$out" | grep -qi "invalid type"
73+
if [ $? -ne 0 ]; then
74+
error "Missing detailed parse error in build output"
75+
echo "$out"
76+
exit 1
77+
fi
78+
79+
success "Experimental-features list produces detailed build error"
80+
81+
bold "Test: watch reports invalid experimental-features without panicking"
82+
83+
cp rescript.json rescript.json.bak
84+
85+
node -e '
86+
const fs = require("fs");
87+
const cfg = JSON.parse(fs.readFileSync("rescript.json", "utf8"));
88+
cfg["experimental-features"] = ["LetUnwrap"];
89+
fs.writeFileSync("rescript.json", JSON.stringify(cfg, null, 2));
90+
'
91+
92+
out=$(rewatch watch 2>&1)
93+
status=$?
94+
95+
mv rescript.json.bak rescript.json
96+
rm -f lib/rescript.lock
97+
98+
if [ $status -eq 0 ]; then
99+
error "Expected watch to fail for invalid experimental-features list"
100+
echo "$out"
101+
exit 1
102+
fi
103+
104+
echo "$out" | grep -q "Could not read rescript.json"
105+
if [ $? -ne 0 ]; then
106+
error "Missing rescript.json path context in watch error"
107+
echo "$out"
108+
exit 1
109+
fi
110+
111+
echo "$out" | grep -qi "invalid type"
112+
if [ $? -ne 0 ]; then
113+
error "Missing detailed parse error for experimental-features list"
114+
echo "$out"
115+
exit 1
116+
fi
117+
118+
echo "$out" | grep -q "panicked"
119+
if [ $? -eq 0 ]; then
120+
error "Watcher should not panic when config is invalid"
121+
echo "$out"
122+
exit 1
123+
fi
124+
125+
success "Invalid experimental-features list handled without panic"

rewatch/tests/snapshots/clean-rebuild.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ Use 'dev-dependencies' instead.
1111
The field 'bsc-flags' found in the package config of '@testrepo/deprecated-config' is deprecated and will be removed in a future version.
1212
Use 'compiler-flags' instead.
1313

14-
The field 'ignored-dirs' found in the package config of '@testrepo/deprecated-config' is not supported by ReScript's new build system (rewatch).
14+
The field 'ignored-dirs' found in the package config of '@testrepo/deprecated-config' is not supported by ReScript 12's new build system.
1515

1616
Unknown field 'some-new-field' found in the package config of '@testrepo/deprecated-config'. This option will be ignored.

0 commit comments

Comments
 (0)