mirror of
https://github.com/storytold/cadcraft.git
synced 2026-10-24 10:56:51 -06:00
This commit is contained in:
@@ -806,7 +806,20 @@ fn run_delconstraint(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
};
|
||||
let n = s.doc()?.constraints.iter().filter(|c| doomed(c)).count();
|
||||
if n > 0 {
|
||||
s.doc_mut()?.constraints.retain(|c| !doomed(c));
|
||||
let mut d = s.doc()?.clone();
|
||||
let broken_before: Vec<String> = cs::parameter_table(&d).into_iter().filter(|r| r.error.is_some()).map(|r| r.name).collect();
|
||||
let removed: Vec<String> = d.constraints.iter().filter(|c| doomed(c)).map(|c| c.name.clone()).collect();
|
||||
d.constraints.retain(|c| !doomed(c));
|
||||
// Reject when a surviving expression would lose a dimension it refers to (same guard as `parameters delete`).
|
||||
if let Some(row) = cs::parameter_table(&d).into_iter().find(|r| r.error.is_some() && !broken_before.contains(&r.name)) {
|
||||
let mut refs = Vec::new();
|
||||
if let Ok(e) = cs::expr::parse(&row.expr) {
|
||||
cs::expr::names(&e, &mut refs);
|
||||
}
|
||||
let used = removed.iter().find(|n| refs.contains(*n)).or(removed.first()).cloned().unwrap_or_default();
|
||||
return Err(EngineError::Other(format!("`{used}` is used by `{}`", row.name)));
|
||||
}
|
||||
*s.doc_mut()? = d;
|
||||
}
|
||||
Ok(json!({ "removed": n, "message": format!("{n} constraint(s) removed") }))
|
||||
}
|
||||
|
||||
@@ -190,3 +190,23 @@ fn hostile_constraint_params_never_panic() {
|
||||
assert!(s.running.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delconstraint_rejects_referenced_dimension() {
|
||||
let mut s = Session::new();
|
||||
let a = line(&mut s, [0.0, 0.0], [10.0, 0.0]);
|
||||
let b = line(&mut s, [0.0, 5.0], [4.0, 5.0]);
|
||||
s.execute("dimconstraint", &json!({ "type": "horizontal", "h1": a, "expr": "8" })).unwrap();
|
||||
s.execute("dimconstraint", &json!({ "type": "horizontal", "h1": b, "expr": "d1/2" })).unwrap();
|
||||
let before = s.doc().unwrap().clone();
|
||||
let first = s.doc().unwrap().constraints[0].id;
|
||||
let e = s.execute("delconstraint", &json!({ "ids": [first] })).unwrap_err().to_string();
|
||||
assert!(e.contains("`d1` is used by `d2`"), "{e}");
|
||||
assert_eq!(*s.doc().unwrap(), before);
|
||||
assert!(s.execute("delconstraint", &json!({ "handles": [a] })).is_err());
|
||||
assert_eq!(*s.doc().unwrap(), before);
|
||||
// Selecting both dimensions removes both; the dependent one may go with its source.
|
||||
let ids: Vec<u32> = s.doc().unwrap().constraints.iter().map(|c| c.id).collect();
|
||||
s.execute("delconstraint", &json!({ "ids": ids })).unwrap();
|
||||
assert!(s.doc().unwrap().constraints.is_empty());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user