mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-25 11:14:46 +00:00
fix(config): combine key error context into one (#16004)
### What does this PR try to resolve? This is a cleanup of annoying multiple "failed to parse key". ``` Caused by: failed to parse key `alias` Caused by: failed to parse key `nested` ``` to ``` Caused by: failed to parse config at path `alias.nested` ``` This also open a door to using annotate-snippets to get the span of a key path. ### How to test and review this PR? This controversial part is we are using the invalid syntax to represent the key path. For example, `alias.nested[2]` refers to ```toml [alias] nested = ["a", "b", "c"] # ^^^ this one ``` r? Muscraft
This commit is contained in:
commit
b41a16c1ee
@ -112,7 +112,7 @@ impl fmt::Display for ConfigKey {
|
||||
}
|
||||
}
|
||||
|
||||
fn escape_key_part<'a>(part: &'a str) -> Cow<'a, str> {
|
||||
pub(super) fn escape_key_part<'a>(part: &'a str) -> Cow<'a, str> {
|
||||
let ok = part.chars().all(|c| {
|
||||
matches!(c,
|
||||
'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_')
|
||||
|
@ -2155,6 +2155,12 @@ impl From<anyhow::Error> for ConfigError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum KeyOrIdx {
|
||||
Key(String),
|
||||
Idx(usize),
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Clone)]
|
||||
pub enum ConfigValue {
|
||||
Integer(i64, Definition),
|
||||
@ -2197,26 +2203,56 @@ impl ConfigValue {
|
||||
}
|
||||
|
||||
fn from_toml(def: Definition, toml: toml::Value) -> CargoResult<ConfigValue> {
|
||||
let mut error_path = Vec::new();
|
||||
Self::from_toml_inner(def, toml, &mut error_path).with_context(|| {
|
||||
let mut it = error_path.iter().rev().peekable();
|
||||
let mut key_path = String::with_capacity(error_path.len() * 3);
|
||||
while let Some(k) = it.next() {
|
||||
match k {
|
||||
KeyOrIdx::Key(s) => key_path.push_str(&key::escape_key_part(&s)),
|
||||
KeyOrIdx::Idx(i) => key_path.push_str(&format!("[{i}]")),
|
||||
}
|
||||
if matches!(it.peek(), Some(KeyOrIdx::Key(_))) {
|
||||
key_path.push('.');
|
||||
}
|
||||
}
|
||||
format!("failed to parse config at `{key_path}`")
|
||||
})
|
||||
}
|
||||
|
||||
fn from_toml_inner(
|
||||
def: Definition,
|
||||
toml: toml::Value,
|
||||
path: &mut Vec<KeyOrIdx>,
|
||||
) -> CargoResult<ConfigValue> {
|
||||
match toml {
|
||||
toml::Value::String(val) => Ok(CV::String(val, def)),
|
||||
toml::Value::Boolean(b) => Ok(CV::Boolean(b, def)),
|
||||
toml::Value::Integer(i) => Ok(CV::Integer(i, def)),
|
||||
toml::Value::Array(val) => Ok(CV::List(
|
||||
val.into_iter()
|
||||
.map(|toml| match toml {
|
||||
.enumerate()
|
||||
.map(|(i, toml)| match toml {
|
||||
toml::Value::String(val) => Ok((val, def.clone())),
|
||||
v => bail!("expected string but found {} in list", v.type_str()),
|
||||
v => {
|
||||
path.push(KeyOrIdx::Idx(i));
|
||||
bail!("expected string but found {} at index {i}", v.type_str())
|
||||
}
|
||||
})
|
||||
.collect::<CargoResult<_>>()?,
|
||||
def,
|
||||
)),
|
||||
toml::Value::Table(val) => Ok(CV::Table(
|
||||
val.into_iter()
|
||||
.map(|(key, value)| {
|
||||
let value = CV::from_toml(def.clone(), value)
|
||||
.with_context(|| format!("failed to parse key `{}`", key))?;
|
||||
Ok((key, value))
|
||||
})
|
||||
.map(
|
||||
|(key, value)| match CV::from_toml_inner(def.clone(), value, path) {
|
||||
Ok(value) => Ok((key, value)),
|
||||
Err(e) => {
|
||||
path.push(KeyOrIdx::Key(key));
|
||||
Err(e)
|
||||
}
|
||||
},
|
||||
)
|
||||
.collect::<CargoResult<_>>()?,
|
||||
def,
|
||||
)),
|
||||
|
@ -47,10 +47,7 @@ Caused by:
|
||||
failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`
|
||||
|
||||
Caused by:
|
||||
failed to parse key `http`
|
||||
|
||||
Caused by:
|
||||
failed to parse key `proxy`
|
||||
failed to parse config at `http.proxy`
|
||||
|
||||
Caused by:
|
||||
found TOML configuration value of unknown type `float`
|
||||
|
@ -87,13 +87,10 @@ Caused by:
|
||||
failed to load TOML configuration from `[ROOT]/foo/.cargo/config.toml`
|
||||
|
||||
Caused by:
|
||||
failed to parse key `alias`
|
||||
failed to parse config at `alias.b-cargo-test[0]`
|
||||
|
||||
Caused by:
|
||||
failed to parse key `b-cargo-test`
|
||||
|
||||
Caused by:
|
||||
expected string but found integer in list
|
||||
expected string but found integer at index 0
|
||||
|
||||
"#]])
|
||||
.run();
|
||||
|
@ -1363,10 +1363,10 @@ Caused by:
|
||||
failed to load TOML configuration from `[ROOT]/.cargo/config.toml`
|
||||
|
||||
Caused by:
|
||||
failed to parse key `foo`
|
||||
failed to parse config at `foo[0]`
|
||||
|
||||
Caused by:
|
||||
expected string but found integer in list
|
||||
expected string but found integer at index 0
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -527,7 +527,7 @@ fn bad_cv_convert() {
|
||||
failed to convert --config argument `a=2019-12-01`
|
||||
|
||||
Caused by:
|
||||
failed to parse key `a`
|
||||
failed to parse config at `a`
|
||||
|
||||
Caused by:
|
||||
found TOML configuration value of unknown type `datetime`
|
||||
|
Loading…
x
Reference in New Issue
Block a user