blob: 290730aaee132e0a6675ab97a85f634e97679c37 [file] [edit]
use rustc_ast::SyntheticAttr;
use rustc_ast::attr::data_structures::CfgEntry;
use rustc_hir::Attribute;
use rustc_hir::attrs::AttributeKind;
use rustc_span::Span;
use thin_vec::ThinVec;
/// This struct contains the state necessary to convert synthetic attributes to hir attributes
/// The only conversion that really happens here is that multiple synthetic attributes are
/// merged into a single hir attribute, representing their combined state.
/// FIXME: We should make this a nice and extendable system if this is going to be used more often
#[derive(Default)]
pub(crate) struct SyntheticAttrState {
/// Attribute state for `SyntheticAttr::CfgTrace` attributes.
cfg_trace: ThinVec<(CfgEntry, Span)>,
/// Attribute state for `SyntheticAttr::CfgAttrTrace` attributes.
cfg_attr_trace: ThinVec<(CfgEntry, Span)>,
}
impl SyntheticAttrState {
pub(crate) fn accept_synthetic_attr(
&mut self,
attr_span: Span,
lower_span: impl Copy + Fn(Span) -> Span,
synthetic: &SyntheticAttr,
) {
match synthetic {
SyntheticAttr::CfgTrace(cfg) => {
let mut cfg = cfg.clone();
cfg.lower_spans(lower_span);
self.cfg_trace.push((cfg, attr_span));
}
SyntheticAttr::CfgAttrTrace(cfg) => {
let mut cfg = cfg.clone();
cfg.lower_spans(lower_span);
self.cfg_attr_trace.push((cfg, attr_span));
}
}
}
pub(crate) fn finalize_synthetic_attrs(self, attributes: &mut Vec<Attribute>) {
if !self.cfg_trace.is_empty() {
attributes.push(Attribute::Parsed(AttributeKind::CfgTrace(self.cfg_trace)));
}
if !self.cfg_attr_trace.is_empty() {
attributes.push(Attribute::Parsed(AttributeKind::CfgAttrTrace(self.cfg_attr_trace)));
}
}
}