Skip to content

Commit 344f5a8

Browse files
committed
config warnings
1 parent ac0fc88 commit 344f5a8

File tree

4 files changed

+151
-8
lines changed

4 files changed

+151
-8
lines changed

rewatch/Cargo.lock

Lines changed: 25 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rewatch/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ num_cpus = "1.17.0"
2424
regex = "1.7.1"
2525
serde = { version = "1.0.152", features = ["derive"] }
2626
serde_json = { version = "1.0.93" }
27+
serde_ignored = "0.1.11"
2728
sysinfo = "0.29.10"
2829
tempfile = "3.10.1"
2930

rewatch/src/build.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ pub fn incremental_build(
370370
println!("{}", &compile_warnings);
371371
}
372372
if initial_build {
373-
log_deprecations(build_state);
373+
log_config_warnings(build_state);
374374
}
375375
if helpers::contains_ascii_characters(&compile_errors) {
376376
println!("{}", &compile_errors);
@@ -399,7 +399,7 @@ pub fn incremental_build(
399399
println!("{}", &compile_warnings);
400400
}
401401
if initial_build {
402-
log_deprecations(build_state);
402+
log_config_warnings(build_state);
403403
}
404404

405405
// Write per-package compiler metadata to `lib/bs/compiler-info.json` (idempotent)
@@ -409,7 +409,7 @@ pub fn incremental_build(
409409
}
410410
}
411411

412-
fn log_deprecations(build_state: &BuildCommandState) {
412+
fn log_config_warnings(build_state: &BuildCommandState) {
413413
build_state.packages.iter().for_each(|(_, package)| {
414414
// Only warn for local dependencies, not external packages
415415
if package.is_local_dep {
@@ -426,6 +426,18 @@ fn log_deprecations(build_state: &BuildCommandState) {
426426
}
427427
},
428428
);
429+
430+
package
431+
.config
432+
.get_unsupported_fields()
433+
.iter()
434+
.for_each(|field| log_unsupported_config_field(&package.name, field));
435+
436+
package
437+
.config
438+
.get_unknown_fields()
439+
.iter()
440+
.for_each(|field| log_unknown_config_field(&package.name, field));
429441
}
430442
});
431443
}
@@ -438,6 +450,20 @@ fn log_deprecated_config_field(package_name: &str, field_name: &str, new_field_n
438450
println!("\n{}", style(warning).yellow());
439451
}
440452

453+
fn log_unsupported_config_field(package_name: &str, field_name: &str) {
454+
let warning = format!(
455+
"The field '{field_name}' found in the package config of '{package_name}' is not supported by ReScript's new build system (rewatch)."
456+
);
457+
println!("\n{}", style(warning).yellow());
458+
}
459+
460+
fn log_unknown_config_field(package_name: &str, field_name: &str) {
461+
let warning = format!(
462+
"Unknown field '{field_name}' found in the package config of '{package_name}'. This option will be ignored."
463+
);
464+
println!("\n{}", style(warning).yellow());
465+
}
466+
441467
// write build.ninja files in the packages after a non-incremental build
442468
// this is necessary to bust the editor tooling cache. The editor tooling
443469
// is watching this file.

rewatch/src/config.rs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ pub struct Config {
308308
#[serde(skip)]
309309
deprecation_warnings: Vec<DeprecationWarning>,
310310

311+
// Holds unknown fields we encountered while parsing
312+
#[serde(skip, default)]
313+
unknown_fields: Vec<String>,
314+
311315
#[serde(default = "default_path")]
312316
pub path: PathBuf,
313317
}
@@ -435,9 +439,14 @@ impl Config {
435439

436440
/// Try to convert a bsconfig from a string to a bsconfig struct
437441
pub fn new_from_json_string(config_str: &str) -> Result<Self> {
438-
let mut config = serde_json::from_str::<Config>(config_str)?;
442+
let mut deserializer = serde_json::Deserializer::from_str(config_str);
443+
let mut unknown_fields = Vec::new();
444+
let mut config: Config = serde_ignored::deserialize(&mut deserializer, |path| {
445+
unknown_fields.push(path.to_string());
446+
})?;
439447

440448
config.handle_deprecations()?;
449+
config.unknown_fields = unknown_fields;
441450

442451
Ok(config)
443452
}
@@ -662,6 +671,52 @@ impl Config {
662671
&self.deprecation_warnings
663672
}
664673

674+
pub fn get_unknown_fields(&self) -> Vec<String> {
675+
self.unknown_fields
676+
.iter()
677+
.filter(|field| !self.is_unsupported_field(field))
678+
.cloned()
679+
.collect()
680+
}
681+
682+
pub fn get_unsupported_fields(&self) -> Vec<String> {
683+
let mut fields = self
684+
.unknown_fields
685+
.iter()
686+
.filter(|field| self.is_unsupported_field(field))
687+
.cloned()
688+
.collect::<Vec<_>>();
689+
690+
if self.gentype_config.is_some() {
691+
fields.push("gentypeconfig".to_string());
692+
}
693+
694+
fields
695+
}
696+
697+
fn is_unsupported_field(&self, field: &str) -> bool {
698+
const UNSUPPORTED_TOP_LEVEL_FIELDS: &[&str] = &[
699+
"version",
700+
"ignored-dirs",
701+
"generators",
702+
"cut-generators",
703+
"pp-flags",
704+
"js-post-build",
705+
"entries",
706+
"use-stdlib",
707+
"external-stdlib",
708+
"bs-external-includes",
709+
"reanalyze",
710+
];
711+
712+
let top_level = field
713+
.split(|c| c == '.' || c == '[')
714+
.next()
715+
.unwrap_or(field);
716+
717+
UNSUPPORTED_TOP_LEVEL_FIELDS.contains(&top_level)
718+
}
719+
665720
fn handle_deprecations(&mut self) -> Result<()> {
666721
if self.dependencies.is_some() && self.bs_dependencies.is_some() {
667722
bail!("dependencies and bs-dependencies are mutually exclusive. Please use 'dependencies'.");
@@ -729,6 +784,7 @@ pub mod tests {
729784
deprecation_warnings: vec![],
730785
experimental_features: None,
731786
allowed_dependents: args.allowed_dependents,
787+
unknown_fields: vec![],
732788
path: args.path,
733789
}
734790
}
@@ -1023,6 +1079,45 @@ pub mod tests {
10231079
assert!(config.get_deprecations().is_empty());
10241080
}
10251081

1082+
#[test]
1083+
fn test_unknown_fields_are_collected() {
1084+
let json = r#"
1085+
{
1086+
"name": "testrepo",
1087+
"sources": {
1088+
"dir": "src",
1089+
"subdirs": true
1090+
},
1091+
"some-new-field": true
1092+
}
1093+
"#;
1094+
1095+
let config = Config::new_from_json_string(json).expect("a valid json string");
1096+
assert_eq!(config.get_unknown_fields(), vec!["some-new-field".to_string()]);
1097+
assert!(config.get_unsupported_fields().is_empty());
1098+
}
1099+
1100+
#[test]
1101+
fn test_unsupported_fields_are_collected() {
1102+
let json = r#"
1103+
{
1104+
"name": "testrepo",
1105+
"sources": {
1106+
"dir": "src",
1107+
"subdirs": true
1108+
},
1109+
"ignored-dirs": ["scripts"]
1110+
}
1111+
"#;
1112+
1113+
let config = Config::new_from_json_string(json).expect("a valid json string");
1114+
assert_eq!(
1115+
config.get_unsupported_fields(),
1116+
vec!["ignored-dirs".to_string()]
1117+
);
1118+
assert!(config.get_unknown_fields().is_empty());
1119+
}
1120+
10261121
#[test]
10271122
fn test_compiler_flags() {
10281123
let json = r#"

0 commit comments

Comments
 (0)