KCL: Fix cryptic error when using duplicate edges in fillet call (#5755)

Fixes https://github.com/KittyCAD/modeling-app/issues/4307

Now if you try to fillet the same edge twice in a single fillet command,
the error message is clearer, and the source range will highlight
the specific edges in the array which are duplicated.

Same goes for chamfer.

Note: although the Rust KCL interpreter sends back an array of SourceRange
for each KCL error, the frontend only puts the first one into CodeMirror
diagnostics. We should fix that: https://github.com/KittyCAD/modeling-app/issues/5754
This commit is contained in:
Adam Chalmers
2025-03-12 11:24:27 -05:00
committed by GitHub
parent f8e53c6577
commit 865bf8ae7a
7 changed files with 125 additions and 49 deletions

View File

@ -159,6 +159,49 @@ impl Args {
})
}
/// Get a labelled keyword arg, check it's an array, and return all items in the array
/// plus their source range.
pub(crate) fn kw_arg_array_and_source<'a, T>(&'a self, label: &str) -> Result<Vec<(T, SourceRange)>, KclError>
where
T: FromKclValue<'a>,
{
let Some(arg) = self.kw_args.labeled.get(label) else {
let err = KclError::Semantic(KclErrorDetails {
source_ranges: vec![self.source_range],
message: format!("This function requires a keyword argument '{label}'"),
});
return Err(err);
};
let Some(array) = arg.value.as_array() else {
let err = KclError::Semantic(KclErrorDetails {
source_ranges: vec![arg.source_range],
message: format!(
"Expected an array of {} but found {}",
type_name::<T>(),
arg.value.human_friendly_type()
),
});
return Err(err);
};
array
.iter()
.map(|item| {
let source = SourceRange::from(item);
let val = FromKclValue::from_kcl_val(item).ok_or_else(|| {
KclError::Semantic(KclErrorDetails {
source_ranges: arg.source_ranges(),
message: format!(
"Expected a {} but found {}",
type_name::<T>(),
arg.value.human_friendly_type()
),
})
})?;
Ok((val, source))
})
.collect::<Result<Vec<_>, _>>()
}
/// Get the unlabeled keyword argument. If not set, returns None.
pub(crate) fn unlabeled_kw_arg_unconverted(&self) -> Option<&Arg> {
self.kw_args