mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 20:02:16 +00:00
Stepwise open checks every feature under the session's mode
OpenSteps::start evaluated under the default check mode, and finish kept those results under the session's mode: an each_step or off session opened in steps recomputed nothing. start now takes the mode (the app passes its session's), and a mode that changed before finish evaluates the design again under the new one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SdcgEu4Lr3moCCisdZShKz
This commit is contained in:
@@ -1968,7 +1968,8 @@ mod tests {
|
||||
let mut whole = Session::default();
|
||||
let opened = whole.execute("doc.open", &json!({"path": path, "read_only": true})).unwrap();
|
||||
|
||||
let mut steps = OpenSteps::start(&json!({"path": path, "read_only": true})).unwrap().expect("a design is opened in steps");
|
||||
let mut steps =
|
||||
OpenSteps::start(&json!({"path": path, "read_only": true}), Default::default()).unwrap().expect("a design is opened in steps");
|
||||
assert_eq!(steps.path(), path);
|
||||
assert_eq!(steps.progress(), (0, features - 1), "the saved marker is where evaluation stops");
|
||||
let mut imports = 0;
|
||||
@@ -2002,9 +2003,53 @@ mod tests {
|
||||
|
||||
// Other files, and STEP-only options, are opened by `doc.open`.
|
||||
for p in [json!({"path": step}), json!({"path": "part.stl"}), json!({"path": path, "up": "y"}), json!({})] {
|
||||
assert!(OpenSteps::start(&p).unwrap().is_none(), "{p}");
|
||||
assert!(OpenSteps::start(&p, Default::default()).unwrap().is_none(), "{p}");
|
||||
}
|
||||
assert!(OpenSteps::start(&json!({"path": dir.join("missing.sc").to_string_lossy()}), Default::default()).is_err());
|
||||
std::fs::remove_dir_all(dir).unwrap();
|
||||
}
|
||||
|
||||
/// A design opened a feature at a time is evaluated under the session's check mode, as
|
||||
/// `doc.open` is. Started under another mode than the session's (the mode changed meanwhile),
|
||||
/// nothing evaluated under it stands: every feature is evaluated again. The bar's last round
|
||||
/// is one the check refuses on solidcore (kernel case
|
||||
/// fillets/1207-fillet-bar-top-edge-after-boss-arc-round-r0-5), so there the modes differ in
|
||||
/// their errors too.
|
||||
#[test]
|
||||
fn a_design_opened_a_feature_at_a_time_is_checked_under_the_sessions_mode() {
|
||||
use super::open_steps::OpenSteps;
|
||||
use solidcraft_kernel::Validation;
|
||||
let dir = std::env::temp_dir().join(format!("solidcraft-open-steps-mode-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let path = dir.join("steps.sc").to_string_lossy().to_string();
|
||||
let mut s = Session::default();
|
||||
s.set_validation(Validation::Off);
|
||||
s.execute("solid.box", &json!({"length": 100, "width": 30, "height": 10, "corner": [0, -15, 0], "body_name": "Arm"})).unwrap();
|
||||
s.execute("solid.cylinder", &json!({"diameter": 40, "height": 20, "base": [0, 0, 0], "operation": "join", "targets": ["Arm"]})).unwrap();
|
||||
s.execute("solid.fillet", &json!({"edges": [[16, 12, 10]], "radius": 2})).unwrap();
|
||||
s.execute("solid.fillet", &json!({"edges": [[60, -15, 10]], "radius": 0.5})).unwrap();
|
||||
s.execute("file.save", &json!({"path": path, "cache": false})).unwrap();
|
||||
let errors = |s: &Session| s.model.results.iter().filter(|r| r.error.is_some()).count();
|
||||
let open = |mode: Validation| {
|
||||
let mut whole = Session::default();
|
||||
whole.set_validation(mode);
|
||||
whole.execute("doc.open", &json!({"path": path})).unwrap();
|
||||
errors(&whole)
|
||||
};
|
||||
for mode in Validation::ALL {
|
||||
for started in [mode, Validation::EachFeature, Validation::Off] {
|
||||
let mut steps = OpenSteps::start(&json!({"path": path}), started).unwrap().expect("a design is opened in steps");
|
||||
while steps.step() {}
|
||||
let mut stepped = Session::default();
|
||||
stepped.set_validation(mode);
|
||||
steps.finish(&mut stepped).unwrap();
|
||||
assert_eq!(stepped.validation(), mode);
|
||||
assert_eq!(errors(&stepped), open(mode), "started under {started:?}, the session's mode {mode:?}");
|
||||
let again = if started == mode { 0 } else { stepped.doc.features.len() };
|
||||
assert_eq!(stepped.model.last_recomputed, again, "started under {started:?}, the session's mode {mode:?}");
|
||||
assert!(stepped.model.is_current(&stepped.doc));
|
||||
}
|
||||
}
|
||||
assert!(OpenSteps::start(&json!({"path": dir.join("missing.sc").to_string_lossy()})).is_err());
|
||||
std::fs::remove_dir_all(dir).unwrap();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ impl OpenSteps {
|
||||
/// Read the design file `doc.open` would open with parameters `p`, without evaluating it.
|
||||
/// `None` when `p` names a file `doc.open` reads in another way (a CAD, mesh or drawing file,
|
||||
/// or a point cloud), or asks for something only those take: run `doc.open` for it.
|
||||
pub fn start(p: &Value) -> Result<Option<OpenSteps>> {
|
||||
pub fn start(p: &Value, validation: solidcraft_kernel::Validation) -> Result<Option<OpenSteps>> {
|
||||
let Some(path) = p.get("path").and_then(Value::as_str) else { return Ok(None) };
|
||||
let other = solidcraft_io::is_step_path(path)
|
||||
|| solidcraft_io::is_mesh_path(path)
|
||||
@@ -58,7 +58,7 @@ impl OpenSteps {
|
||||
let marker = doc.marker;
|
||||
let stop = marker.unwrap_or(usize::MAX).min(doc.features.len());
|
||||
// A model saved under another check mode holds that mode's results: evaluated again.
|
||||
let adopted = Session::saved_model(&doc, saved.as_ref()).filter(|model| model.validation() == solidcraft_kernel::Validation::default());
|
||||
let adopted = Session::saved_model(&doc, saved.as_ref()).filter(|model| model.validation() == validation);
|
||||
let steps = OpenSteps {
|
||||
path: path.to_string(),
|
||||
read_only,
|
||||
@@ -69,7 +69,7 @@ impl OpenSteps {
|
||||
next: if adopted.is_some() { stop } else { 0 },
|
||||
stop,
|
||||
adopted: adopted.is_some(),
|
||||
model: adopted.unwrap_or_default(),
|
||||
model: adopted.unwrap_or_else(|| under(validation)),
|
||||
};
|
||||
Ok(Some(steps))
|
||||
}
|
||||
@@ -115,8 +115,9 @@ impl OpenSteps {
|
||||
/// yet evaluated are evaluated now.
|
||||
pub fn finish(mut self, s: &mut Session) -> Result<Value> {
|
||||
Arc::make_mut(&mut self.doc).marker = self.marker;
|
||||
// The results so far hold another mode's checks: evaluated again, as `Session::opened` would.
|
||||
if self.model.validation() != s.validation() {
|
||||
self.model.set_validation(s.validation());
|
||||
self.model = under(s.validation());
|
||||
self.adopted = false;
|
||||
}
|
||||
if !self.adopted {
|
||||
@@ -128,3 +129,10 @@ impl OpenSteps {
|
||||
opened_design(s, opened, &self.path, self.read_only, self.disk)
|
||||
}
|
||||
}
|
||||
|
||||
/// A model with no results yet, checking its features under `validation`.
|
||||
fn under(validation: solidcraft_kernel::Validation) -> Model {
|
||||
let mut model = Model::default();
|
||||
model.set_validation(validation);
|
||||
model
|
||||
}
|
||||
|
||||
@@ -766,7 +766,8 @@ fn step_opening(
|
||||
let session = staged.session.as_mut()?;
|
||||
let Some(opening) = staged.opening.as_mut() else {
|
||||
let params = staged.params.clone();
|
||||
match scoped(scope.clone(), || watch(progress.clone(), || solidcraft_engine::OpenSteps::start(¶ms))) {
|
||||
let validation = session.validation();
|
||||
match scoped(scope.clone(), || watch(progress.clone(), || solidcraft_engine::OpenSteps::start(¶ms, validation))) {
|
||||
Ok(Some(opening)) => staged.opening = Some(opening),
|
||||
// Options only `doc.open` takes: it opens the file at once.
|
||||
Ok(None) => {
|
||||
|
||||
Reference in New Issue
Block a user