Skip to content

Commit

Permalink
show referencing and referenced objects in error message
Browse files Browse the repository at this point in the history
  • Loading branch information
nathan-folsom committed Dec 30, 2023
1 parent 6d23649 commit 5ad1fdc
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 26 deletions.
77 changes: 63 additions & 14 deletions crates/fj-core/src/validate/references.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -18,19 +19,27 @@ impl<T: Eq + PartialEq + Hash, U> ReferenceCounter<T, U> {
.or_insert(vec![found]);
}

pub fn has_multiple(&self) -> bool {
self.0.iter().any(|(_, references)| references.len() > 1)
pub fn get_multiples(&self) -> Vec<MultipleReferences<T, U>> {
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());
});
)*
};
}
Expand All @@ -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<Region, Face>,
},
/// [`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<Face, Shell>,
},
/// [`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<HalfEdge, Cycle>,
},
/// [`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<Cycle, Region>,
},
}

pub struct MultipleReferences<T, U> {
referenced: Handle<T>,
references: Vec<Handle<U>>,
}

use std::fmt::Debug;

impl<T: Debug, U: Debug> Debug for MultipleReferences<T, U> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{:?} referenced by {:?}",
self.referenced, self.references
)
}
}

impl<T, U> Clone for MultipleReferences<T, U> {
fn clone(&self) -> Self {
Self {
referenced: self.referenced.clone(),
references: self.references.to_vec(),
}
}
}
8 changes: 4 additions & 4 deletions crates/fj-core/src/validate/sketch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ impl SketchValidationError {

validate_references!(
errors, SketchValidationError;
referenced_edges, ReferenceCountError::HalfEdge;
referenced_cycles, ReferenceCountError::Cycle;
referenced_edges, HalfEdge;
referenced_cycles, Cycle;
);
}
}
Expand Down Expand Up @@ -88,7 +88,7 @@ mod tests {
assert_contains_err!(
invalid_sketch,
ValidationError::Sketch(SketchValidationError::MultipleReferences(
ReferenceCountError::Cycle
ReferenceCountError::Cycle { references: _ }
))
);

Expand Down Expand Up @@ -133,7 +133,7 @@ mod tests {
assert_contains_err!(
invalid_sketch,
ValidationError::Sketch(SketchValidationError::MultipleReferences(
ReferenceCountError::HalfEdge
ReferenceCountError::HalfEdge { references: _ }
))
);

Expand Down
16 changes: 8 additions & 8 deletions crates/fj-core/src/validate/solid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
);
}
}
Expand Down Expand Up @@ -228,7 +228,7 @@ mod tests {
assert_contains_err!(
invalid_solid,
ValidationError::Solid(SolidValidationError::MultipleReferences(
ReferenceCountError::Face
ReferenceCountError::Face { references: _ }
))
);

Expand Down Expand Up @@ -279,7 +279,7 @@ mod tests {
assert_contains_err!(
invalid_solid,
ValidationError::Solid(SolidValidationError::MultipleReferences(
ReferenceCountError::Region
ReferenceCountError::Region { references: _ }
))
);

Expand Down Expand Up @@ -327,7 +327,7 @@ mod tests {
assert_contains_err!(
invalid_solid,
ValidationError::Solid(SolidValidationError::MultipleReferences(
ReferenceCountError::Cycle
ReferenceCountError::Cycle { references: _ }
))
);

Expand Down Expand Up @@ -368,7 +368,7 @@ mod tests {
assert_contains_err!(
invalid_solid,
ValidationError::Solid(SolidValidationError::MultipleReferences(
ReferenceCountError::HalfEdge
ReferenceCountError::HalfEdge { references: _ }
))
);

Expand Down

0 comments on commit 5ad1fdc

Please sign in to comment.