pub mod comment_link_patcher;
pub mod encoding_patcher;
pub mod type_ref_patcher;
use crate::ast::node::Node;
use crate::compilation_state::CompilationState;
use crate::diagnostics::{Diagnostic, Error};
use crate::grammar::attributes::*;
use crate::grammar::Symbol;
pub unsafe fn patch_ast(compilation_state: &mut CompilationState) {
let attribute_patcher = crate::patch_attributes!("", Allow, Compress, Deprecated, Oneway, SlicedFormat);
compilation_state.apply_unsafe(attribute_patcher);
compilation_state.apply_unsafe(type_ref_patcher::patch_ast);
compilation_state.apply_unsafe(encoding_patcher::patch_ast);
compilation_state.apply_unsafe(comment_link_patcher::patch_ast);
}
#[macro_export]
macro_rules! patch_attributes {
($prefix:literal, $($attribute_type:ty),* $(,)?) => {{
unsafe fn _patch_attributes_impl(compilation_state: &mut CompilationState) {
let diagnostics = &mut compilation_state.diagnostics;
for node in compilation_state.ast.as_mut_slice() {
if let Node::Attribute(attribute_ptr) = node {
let attribute = attribute_ptr.borrow_mut();
if let Some(unparsed) = attribute.downcast::<Unparsed>() {
match unparsed.directive.as_str() {
$(
directive if directive == <$attribute_type>::directive() => {
let parsed = <$attribute_type>::parse_from(unparsed, attribute.span(), diagnostics);
attribute.kind = Box::new(parsed);
}
)*
directive => {
let directive_prefix = directive.split_once("::").map_or("", |(p, _)| p);
if $prefix == directive_prefix {
Diagnostic::new(Error::UnexpectedAttribute {
attribute: directive.to_owned(),
})
.set_span(attribute.span())
.push_into(diagnostics);
}
}
}
}
}
}
}
_patch_attributes_impl
}}
}