use crate::diagnostics::{Diagnostic, Diagnostics, Error};
use crate::grammar::*;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
pub fn validate_attributes(attributable: &(impl Attributable + AsAttributables), diagnostics: &mut Diagnostics) {
let attributes = attributable.attributes();
validate_repeated_attributes(&attributes, diagnostics);
for attribute in attributes {
let concrete_type = attributable.concrete_attributable();
attribute.kind.validate_on(concrete_type, attribute.span(), diagnostics);
}
}
pub fn validate_repeated_attributes(attributes: &[&Attribute], diagnostics: &mut Diagnostics) {
let mut first_attribute_occurrence = HashMap::new();
for attribute in attributes {
if attribute.kind.is_repeatable() {
continue;
}
let directive = attribute.kind.directive();
let span = attribute.span();
match first_attribute_occurrence.entry(directive) {
Occupied(entry) => {
Diagnostic::new(Error::AttributeIsNotRepeatable {
attribute: directive.to_owned(),
})
.set_span(span)
.add_note("attribute was previously used here", Some(entry.get()))
.push_into(diagnostics);
}
Vacant(entry) => {
entry.insert(span.clone());
}
}
}
}