mod allow;
mod compress;
mod deprecated;
mod oneway;
mod sliced_format;
pub use allow::*;
pub use compress::*;
pub use deprecated::*;
pub use oneway::*;
pub use sliced_format::*;
use super::Attributables;
use crate::diagnostics::{Diagnostic, Diagnostics, Error};
use crate::slice_file::Span;
use std::ops::Range;
pub trait AttributeKind: std::fmt::Debug {
fn is_repeatable(&self) -> bool;
fn validate_on(&self, applied_on: Attributables, span: &Span, diagnostics: &mut Diagnostics);
fn as_any(&self) -> &dyn std::any::Any;
fn directive(&self) -> &str;
}
macro_rules! implement_attribute_kind_for {
($type:ty, $directive:literal, $is_repeatable:literal) => {
impl $type {
pub fn directive() -> &'static str {
$directive
}
}
impl AttributeKind for $type {
fn is_repeatable(&self) -> bool {
$is_repeatable
}
fn validate_on(&self, applied_on: Attributables, span: &Span, diagnostics: &mut Diagnostics) {
Self::validate_on(&self, applied_on, span, diagnostics);
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn directive(&self) -> &str {
Self::directive()
}
}
};
}
pub(crate) use implement_attribute_kind_for;
#[derive(Debug)]
pub struct Unparsed {
pub directive: String,
pub args: Vec<String>,
}
impl AttributeKind for Unparsed {
fn is_repeatable(&self) -> bool {
true
}
fn validate_on(&self, _: Attributables, _: &Span, _: &mut Diagnostics) {}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn directive(&self) -> &str {
&self.directive
}
}
fn report_invalid_attribute(
attribute: &impl AttributeKind,
span: &Span,
note: Option<&str>,
diagnostics: &mut Diagnostics,
) {
let mut diagnostic = Diagnostic::from_error(Error::InvalidAttribute {
directive: attribute.directive().to_owned(),
})
.set_span(span);
if let Some(note) = note {
diagnostic = diagnostic.add_note(note, None);
}
diagnostic.push_into(diagnostics);
}
fn check_argument_count_is_within(
range: Range<usize>,
arguments: &[String],
directive: &str,
span: &Span,
diagnostics: &mut Diagnostics,
) {
if !range.contains(&arguments.len()) {
Diagnostic::from_error(Error::IncorrectAttributeArgumentCount {
directive: directive.to_owned(),
expected_count: range,
actual_count: arguments.len(),
})
.set_span(span)
.push_into(diagnostics);
}
}