use syn::Attribute;
use syn::ForeignItem;
use syn::ImplItem;
use syn::Item;
use syn::TraitItem;
use super::ConditionalAttributes;
pub(in crate::fixes) struct GateSource<'a> {
pub(in crate::fixes) text: &'a str,
pub(in crate::fixes) line_offsets: &'a [usize],
}
pub(in crate::fixes) trait GateTracking {
fn gate_source(&self) -> GateSource<'_>;
fn conditional_attributes_mut(&mut self) -> &mut ConditionalAttributes;
fn push_gates(&mut self, attributes: &[Attribute]) -> usize {
let gates = {
let source = self.gate_source();
ConditionalAttributes::from_attributes(source.text, source.line_offsets, attributes)
};
let conditional_attributes = self.conditional_attributes_mut();
let previous_len = conditional_attributes.len();
conditional_attributes.extend(gates);
previous_len
}
fn restore_gates(&mut self, previous_len: usize) {
self.conditional_attributes_mut().truncate(previous_len);
}
}
pub(in crate::fixes) fn item_gate_attributes(item: &Item) -> &[Attribute] {
match item {
Item::Mod(_) => &[],
other => super::item_attributes(other),
}
}
pub(in crate::fixes) fn impl_item_attributes(impl_item: &ImplItem) -> &[Attribute] {
match impl_item {
ImplItem::Const(node) => &node.attrs,
ImplItem::Fn(node) => &node.attrs,
ImplItem::Macro(node) => &node.attrs,
ImplItem::Type(node) => &node.attrs,
_ => &[],
}
}
pub(in crate::fixes) fn trait_item_attributes(trait_item: &TraitItem) -> &[Attribute] {
match trait_item {
TraitItem::Const(node) => &node.attrs,
TraitItem::Fn(node) => &node.attrs,
TraitItem::Macro(node) => &node.attrs,
TraitItem::Type(node) => &node.attrs,
_ => &[],
}
}
pub(in crate::fixes) fn foreign_item_attributes(foreign_item: &ForeignItem) -> &[Attribute] {
match foreign_item {
ForeignItem::Fn(node) => &node.attrs,
ForeignItem::Macro(node) => &node.attrs,
ForeignItem::Static(node) => &node.attrs,
ForeignItem::Type(node) => &node.attrs,
_ => &[],
}
}
macro_rules! gate_tracking_visit {
() => {
fn visit_item(&mut self, node: &syn::Item) {
let previous_gates = crate::fixes::imports::GateTracking::push_gates(
self,
crate::fixes::imports::item_gate_attributes(node),
);
syn::visit::visit_item(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
fn visit_impl_item(&mut self, node: &syn::ImplItem) {
let previous_gates = crate::fixes::imports::GateTracking::push_gates(
self,
crate::fixes::imports::impl_item_attributes(node),
);
syn::visit::visit_impl_item(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
fn visit_trait_item(&mut self, node: &syn::TraitItem) {
let previous_gates = crate::fixes::imports::GateTracking::push_gates(
self,
crate::fixes::imports::trait_item_attributes(node),
);
syn::visit::visit_trait_item(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
fn visit_foreign_item(&mut self, node: &syn::ForeignItem) {
let previous_gates = crate::fixes::imports::GateTracking::push_gates(
self,
crate::fixes::imports::foreign_item_attributes(node),
);
syn::visit::visit_foreign_item(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
fn visit_stmt(&mut self, node: &syn::Stmt) {
let attributes = match node {
syn::Stmt::Local(local) => local.attrs.as_slice(),
syn::Stmt::Macro(stmt_macro) => stmt_macro.attrs.as_slice(),
syn::Stmt::Expr(..) | syn::Stmt::Item(..) => &[],
};
let previous_gates = crate::fixes::imports::GateTracking::push_gates(self, attributes);
syn::visit::visit_stmt(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
fn visit_expr(&mut self, node: &syn::Expr) {
let previous_gates = crate::fixes::imports::GateTracking::push_gates(
self,
crate::fixes::imports::expr_attributes(node),
);
syn::visit::visit_expr(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
fn visit_field(&mut self, node: &syn::Field) {
let previous_gates = crate::fixes::imports::GateTracking::push_gates(self, &node.attrs);
syn::visit::visit_field(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
fn visit_variant(&mut self, node: &syn::Variant) {
let previous_gates = crate::fixes::imports::GateTracking::push_gates(self, &node.attrs);
syn::visit::visit_variant(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
fn visit_arm(&mut self, node: &syn::Arm) {
let previous_gates = crate::fixes::imports::GateTracking::push_gates(self, &node.attrs);
syn::visit::visit_arm(self, node);
crate::fixes::imports::GateTracking::restore_gates(self, previous_gates);
}
};
}
pub(crate) use gate_tracking_visit;