From 5ad1fdca5d09caf57afa5d30867562747c58814a Mon Sep 17 00:00:00 2001 From: Nathan Folsom Date: Fri, 29 Dec 2023 16:15:00 -0800 Subject: [PATCH] show referencing and referenced objects in error message --- crates/fj-core/src/validate/references.rs | 77 ++++++++++++++++++----- crates/fj-core/src/validate/sketch.rs | 8 +-- crates/fj-core/src/validate/solid.rs | 16 ++--- 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/crates/fj-core/src/validate/references.rs b/crates/fj-core/src/validate/references.rs index 2277034fdb..52a95c8889 100644 --- a/crates/fj-core/src/validate/references.rs +++ b/crates/fj-core/src/validate/references.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use std::hash::Hash; +use crate::objects::{Cycle, Face, HalfEdge, Region, Shell}; use crate::storage::Handle; #[derive(Default)] @@ -18,19 +19,27 @@ impl ReferenceCounter { .or_insert(vec![found]); } - pub fn has_multiple(&self) -> bool { - self.0.iter().any(|(_, references)| references.len() > 1) + pub fn get_multiples(&self) -> Vec> { + self.0 + .iter() + .filter(|(_, references)| references.len() > 1) + .map(|(referenced, references)| MultipleReferences { + referenced: referenced.clone(), + references: references.to_vec(), + }) + .collect() } } /// Find errors and convert to [`crate::validate::ValidationError`] #[macro_export] macro_rules! validate_references { - ($errors:ident, $error_ty:ty;$($counter:ident, $err:expr;)*) => { + ($errors:ident, $error_ty:ty;$($counter:ident, $err:ident;)*) => { $( - if $counter.has_multiple() { - $errors.push(Into::<$error_ty>::into($err).into()); - } + $counter.get_multiples().iter().for_each(|multiple| { + let reference_error = ReferenceCountError::$err { references: multiple.clone() }; + $errors.push(Into::<$error_ty>::into(reference_error).into()); + }); )* }; } @@ -40,15 +49,55 @@ macro_rules! validate_references { #[derive(Clone, Debug, thiserror::Error)] pub enum ReferenceCountError { /// [`crate::objects::Region`] referenced by more than one [`crate::objects::Face`] - #[error("[`Region`] referenced by more than one [`Face`]")] - Region, + #[error( + "[`Region`] referenced by more than one [`Face`]\n{references:#?}" + )] + Region { + references: MultipleReferences, + }, /// [`crate::objects::Face`] referenced by more than one [`crate::objects::Shell`] - #[error("[`Face`] referenced by more than one [`Shell`]")] - Face, + #[error("[`Face`] referenced by more than one [`Shell`]\n{references:#?}")] + Face { + references: MultipleReferences, + }, /// [`crate::objects::HalfEdge`] referenced by more than one [`crate::objects::Cycle`] - #[error("[`HalfEdge`] referenced by more than one [`Cycle`]")] - HalfEdge, + #[error( + "[`HalfEdge`] referenced by more than one [`Cycle`]\n{references:#?}" + )] + HalfEdge { + references: MultipleReferences, + }, /// [`crate::objects::Cycle`] referenced by more than one [`crate::objects::Region`] - #[error("[`Cycle`] referenced by more than one [`Region`]")] - Cycle, + #[error( + "[`Cycle`] referenced by more than one [`Region`]\n{references:#?}" + )] + Cycle { + references: MultipleReferences, + }, +} + +pub struct MultipleReferences { + referenced: Handle, + references: Vec>, +} + +use std::fmt::Debug; + +impl Debug for MultipleReferences { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{:?} referenced by {:?}", + self.referenced, self.references + ) + } +} + +impl Clone for MultipleReferences { + fn clone(&self) -> Self { + Self { + referenced: self.referenced.clone(), + references: self.references.to_vec(), + } + } } diff --git a/crates/fj-core/src/validate/sketch.rs b/crates/fj-core/src/validate/sketch.rs index ca44803eaf..a7872cdf7b 100644 --- a/crates/fj-core/src/validate/sketch.rs +++ b/crates/fj-core/src/validate/sketch.rs @@ -51,8 +51,8 @@ impl SketchValidationError { validate_references!( errors, SketchValidationError; - referenced_edges, ReferenceCountError::HalfEdge; - referenced_cycles, ReferenceCountError::Cycle; + referenced_edges, HalfEdge; + referenced_cycles, Cycle; ); } } @@ -88,7 +88,7 @@ mod tests { assert_contains_err!( invalid_sketch, ValidationError::Sketch(SketchValidationError::MultipleReferences( - ReferenceCountError::Cycle + ReferenceCountError::Cycle { references: _ } )) ); @@ -133,7 +133,7 @@ mod tests { assert_contains_err!( invalid_sketch, ValidationError::Sketch(SketchValidationError::MultipleReferences( - ReferenceCountError::HalfEdge + ReferenceCountError::HalfEdge { references: _ } )) ); diff --git a/crates/fj-core/src/validate/solid.rs b/crates/fj-core/src/validate/solid.rs index 93f130e7ca..cf5e9a48c3 100644 --- a/crates/fj-core/src/validate/solid.rs +++ b/crates/fj-core/src/validate/solid.rs @@ -164,10 +164,10 @@ impl SolidValidationError { validate_references!( errors, SolidValidationError; - referenced_regions, ReferenceCountError::Region; - referenced_faces, ReferenceCountError::Face; - referenced_edges, ReferenceCountError::HalfEdge; - referenced_cycles, ReferenceCountError::Cycle; + referenced_regions, Region; + referenced_faces, Face; + referenced_edges, HalfEdge; + referenced_cycles, Cycle; ); } } @@ -228,7 +228,7 @@ mod tests { assert_contains_err!( invalid_solid, ValidationError::Solid(SolidValidationError::MultipleReferences( - ReferenceCountError::Face + ReferenceCountError::Face { references: _ } )) ); @@ -279,7 +279,7 @@ mod tests { assert_contains_err!( invalid_solid, ValidationError::Solid(SolidValidationError::MultipleReferences( - ReferenceCountError::Region + ReferenceCountError::Region { references: _ } )) ); @@ -327,7 +327,7 @@ mod tests { assert_contains_err!( invalid_solid, ValidationError::Solid(SolidValidationError::MultipleReferences( - ReferenceCountError::Cycle + ReferenceCountError::Cycle { references: _ } )) ); @@ -368,7 +368,7 @@ mod tests { assert_contains_err!( invalid_solid, ValidationError::Solid(SolidValidationError::MultipleReferences( - ReferenceCountError::HalfEdge + ReferenceCountError::HalfEdge { references: _ } )) );