use crate::diagnostics::{Diagnostic, Diagnostics, Error};
use crate::grammar::*;
pub fn validate_members(members: Vec<&impl Member>, diagnostics: &mut Diagnostics) {
tags_have_optional_types(members.clone(), diagnostics);
tags_are_unique(members.clone(), diagnostics);
}
fn tags_are_unique(members: Vec<&impl Member>, diagnostics: &mut Diagnostics) {
let mut sorted_tagged_members = members.into_iter().filter(|m| m.is_tagged()).collect::<Vec<_>>();
sorted_tagged_members.sort_by_key(|member| member.tag().expect("tagged member has no tag!"));
sorted_tagged_members.windows(2).for_each(|window| {
if window[0].tag() == window[1].tag() {
Diagnostic::from_error(Error::CannotHaveDuplicateTag {
identifier: window[1].identifier().to_owned(),
})
.set_span(window[1].span())
.add_note(
format!(
"The tag '{}' is already being used by member '{}'",
window[0].tag().unwrap(),
window[0].identifier(),
),
Some(window[0].span()),
)
.push_into(diagnostics);
};
});
}
fn tags_have_optional_types(members: Vec<&impl Member>, diagnostics: &mut Diagnostics) {
let tagged_members = members.into_iter().filter(|member| member.is_tagged());
for member in tagged_members {
if !member.data_type().is_optional {
Diagnostic::from_error(Error::TaggedMemberMustBeOptional {
identifier: member.identifier().to_owned(),
})
.set_span(member.span())
.push_into(diagnostics);
}
}
}