Skip to content

Consider using macro to generate ParsedSpans boilerplate #87

@coderabbitai

Description

@coderabbitai

Issue Description

Consider using a macro to generate the repetitive fields, setters, getters, and builder logic for ParsedSpans and its builder.

Consider collapsing all of the repetitive fields, setters, getters and the build/validation logic into one macro_rules! instead of hand‐writing each.

Location

src/parser/cst_builder/spans.rs:17

Code Context

/// are sorted and non-overlapping in debug builds.
#[non_exhaustive]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct ParsedSpans {
    /// `import` statement spans.
    imports: Vec<Span>,

Suggested Implementation

macro_rules! define_parsed_spans {
    ( $( $field:ident ),* $(,)? ) => {
        #[derive(Debug, Default, Clone, PartialEq)]
        pub struct ParsedSpans {
            $( pub(crate) $field: Vec<Span> ),*
        }

        #[derive(Default)]
        pub struct ParsedSpansBuilder {
            $( $field: Vec<Span> ),*
        }

        impl ParsedSpansBuilder {
            $(
                #[must_use]
                pub fn $field(mut self, spans: Vec<Span>) -> Self {
                    self.$field = spans;
                    self
                }
            )*

            #[must_use]
            pub fn build(self) -> ParsedSpans {
                let Self { $( $field ),* } = self;
                let result = validate_span_lists_sorted(&[
                    $( (stringify!($field), &$field) ),*
                ]);
                debug_assert!(result.is_ok(), "{}", result.err().unwrap_or_default());

                ParsedSpans { $( $field ),* }
            }
        }

        impl ParsedSpans {
            #[must_use]
            pub fn builder() -> ParsedSpansBuilder {
                ParsedSpansBuilder::default()
            }

            $(
                #[must_use]
                pub fn $field(&self) -> &[Span] {
                    &self.$field
                }
            )*
        }
    }
}

define_parsed_spans!(
    imports,
    typedefs,
    relations,
    indexes,
    functions,
    transformers,
    rules,
);

Benefits

This preserves your build/validation logic verbatim but removes all of the near-duplicate setter/getter boilerplate.

References

Metadata

Metadata

Assignees

Labels

lowLow criticality issue

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions