#[allow(unused_imports)]
use std::iter::FromIterator;
#[allow(unused_imports)]
use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use proc_macro_error::{emit_error, abort};
use quote::quote;
use syn::{
visit_mut::{self, VisitMut},
};
use crate::utils::unwrap_or_error;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum IdentMode {
Use,
Other,
}
pub trait VisitMutExt {
fn process_attrs(&mut self, _attrs: &mut Vec<syn::Attribute>) -> syn::Result<()> {
Ok(())
}
fn process_ident(&mut self, _ident: &mut syn::Ident, _mode: IdentMode) -> syn::Result<()> {
Ok(())
}
fn process_attribute(&mut self, _node: &mut syn::Attribute) -> syn::Result<()> {
Ok(())
}
fn process_expr(&mut self, _node: &mut syn::Expr) -> syn::Result<()> {
Ok(())
}
fn process_file(&mut self, _node: &mut syn::File) -> syn::Result<()> {
Ok(())
}
fn process_item(&mut self, _node: &mut syn::Item) -> syn::Result<()> {
Ok(())
}
fn process_item_impl(&mut self, _node: &mut syn::ItemImpl) -> syn::Result<()> {
Ok(())
}
fn process_item_trait(&mut self, _node: &mut syn::ItemTrait) -> syn::Result<()> {
Ok(())
}
fn process_item_fn(&mut self, _node: &mut syn::ItemFn) -> syn::Result<()> {
Ok(())
}
fn process_macro(&mut self, _node: &mut syn::Macro) -> syn::Result<()> {
Ok(())
}
fn process_path_segment(&mut self, _node: &mut syn::PathSegment) -> syn::Result<()> {
Ok(())
}
fn process_type_param(&mut self, _node: &mut syn::TypeParam) -> syn::Result<()> {
Ok(())
}
fn process_use_tree(&mut self, _node: &mut syn::UseTree) -> syn::Result<()> {
Ok(())
}
fn after_process_item(&mut self, _node: &mut syn::Item) -> syn::Result<()> {
Ok(())
}
}
pub struct Visitor<T> {
pub inner: T,
}
impl<T> Visitor<T> {
pub fn new(inner: T) -> Self {
Self { inner }
}
pub fn process(&mut self, item: TokenStream2) -> TokenStream2
where
Self: VisitMutExt,
{
let mut syntax_tree: syn::File = unwrap_or_error!(syn::parse(item.into()));
self.visit_file_mut(&mut syntax_tree);
let ts = quote!(#syntax_tree);
ts
}
}
macro_rules! impl_fn {
(@expr $value:expr, value) => {
$value
};
(@expr $value:expr, (_, value)) => {
&mut $value.1
};
(@func $self:expr, $node:ident, $proc:ident(node $(.$path:ident)? as Some($expr:tt) $(, $mode:expr)?) ) => {
if let Some(value) = impl_fn!(@arg $node $(.$path)?) {
match $self.$proc( impl_fn!(@expr value, $expr) $(, $mode)? ) {
Ok(_) => {},
Err(e) => {
emit_error!(e)
}
};
};
};
(@func $self:expr, $node:ident, $proc:ident(node $(.$path:ident)? $(, $mode:expr)?) ) => {
match $self.$proc( impl_fn!(@arg $node $(.$path)?) $(, $mode)? ) {
Ok(_) => {},
Err(e) => {
emit_error!(e)
}
};
};
(@funcs $self:expr, $node:ident, { $($proc:ident $params:tt ;)+ } ) => {
$(
impl_fn!(@func $self, $node, $proc $params);
)+
};
(@arg $node:ident $(.$path:ident)+) => {
&mut $node $(.$path)+
};
(@arg $node:ident) => {
$node
};
($name:ident, $ty:ty, ) => {
fn $name(&mut self, node: &mut $ty) {
visit_mut::$name(self, node);
}
};
($name:ident, $ty:ty, $before:tt) => {
fn $name(&mut self, node: &mut $ty) {
impl_fn!(@funcs self, node, $before);
visit_mut::$name(self, node);
}
};
($name:ident, $ty:ty, $before:tt, $after:tt) => {
fn $name(&mut self, node: &mut $ty) {
impl_fn!(@funcs self, node, $before);
visit_mut::$name(self, node);
impl_fn!(@funcs self, node, $after);
}
};
}
#[rustfmt::skip]
impl<T> VisitMut for Visitor<T> where Self: VisitMutExt,
{
impl_fn!(visit_abi_mut, syn::Abi, );
impl_fn!(visit_angle_bracketed_generic_arguments_mut,
syn::AngleBracketedGenericArguments,
);
impl_fn!(visit_arm_mut, syn::Arm, { process_attrs(node.attrs); });
impl_fn!(visit_attr_style_mut, syn::AttrStyle, );
impl_fn!(visit_attribute_mut, syn::Attribute, { process_attribute(node); });
impl_fn!(visit_bare_fn_arg_mut, syn::BareFnArg, { process_attrs(node.attrs); });
impl_fn!(visit_bin_op_mut, syn::BinOp, );
impl_fn!(visit_binding_mut, syn::Binding, { process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_block_mut, syn::Block, );
impl_fn!(visit_bound_lifetimes_mut, syn::BoundLifetimes, );
impl_fn!(visit_const_param_mut, syn::ConstParam, { process_attrs(node.attrs); });
impl_fn!(visit_constraint_mut, syn::Constraint, );
impl_fn!(visit_data_mut, syn::Data, );
impl_fn!(visit_data_enum_mut, syn::DataEnum, );
impl_fn!(visit_data_struct_mut, syn::DataStruct, );
impl_fn!(visit_data_union_mut, syn::DataUnion, );
impl_fn!(visit_derive_input_mut, syn::DeriveInput, { process_attrs(node.attrs); });
impl_fn!(visit_expr_mut, syn::Expr, { process_expr(node); });
impl_fn!(visit_expr_array_mut, syn::ExprArray, { process_attrs(node.attrs); });
impl_fn!(visit_expr_assign_mut, syn::ExprAssign, { process_attrs(node.attrs); });
impl_fn!(visit_expr_assign_op_mut, syn::ExprAssignOp, { process_attrs(node.attrs); });
impl_fn!(visit_expr_async_mut, syn::ExprAsync, { process_attrs(node.attrs); });
impl_fn!(visit_expr_await_mut, syn::ExprAwait, { process_attrs(node.attrs); });
impl_fn!(visit_expr_binary_mut, syn::ExprBinary, { process_attrs(node.attrs); });
impl_fn!(visit_expr_block_mut, syn::ExprBlock, { process_attrs(node.attrs); });
impl_fn!(visit_expr_box_mut, syn::ExprBox, { process_attrs(node.attrs); });
impl_fn!(visit_expr_break_mut, syn::ExprBreak, { process_attrs(node.attrs); });
impl_fn!(visit_expr_call_mut, syn::ExprCall, { process_attrs(node.attrs); });
impl_fn!(visit_expr_cast_mut, syn::ExprCast, { process_attrs(node.attrs); });
impl_fn!(visit_expr_closure_mut, syn::ExprClosure, { process_attrs(node.attrs); });
impl_fn!(visit_expr_continue_mut, syn::ExprContinue, { process_attrs(node.attrs); });
impl_fn!(visit_expr_field_mut, syn::ExprField, { process_attrs(node.attrs); });
impl_fn!(visit_expr_for_loop_mut, syn::ExprForLoop, { process_attrs(node.attrs); });
impl_fn!(visit_expr_group_mut, syn::ExprGroup, { process_attrs(node.attrs); });
impl_fn!(visit_expr_if_mut, syn::ExprIf, { process_attrs(node.attrs); });
impl_fn!(visit_expr_index_mut, syn::ExprIndex, { process_attrs(node.attrs); });
impl_fn!(visit_expr_let_mut, syn::ExprLet, { process_attrs(node.attrs); });
impl_fn!(visit_expr_lit_mut, syn::ExprLit, { process_attrs(node.attrs); });
impl_fn!(visit_expr_loop_mut, syn::ExprLoop, { process_attrs(node.attrs); });
impl_fn!(visit_expr_macro_mut, syn::ExprMacro, { process_attrs(node.attrs); });
impl_fn!(visit_expr_match_mut, syn::ExprMatch, { process_attrs(node.attrs); });
impl_fn!(visit_expr_method_call_mut, syn::ExprMethodCall, { process_attrs(node.attrs); });
impl_fn!(visit_expr_paren_mut, syn::ExprParen, { process_attrs(node.attrs); });
impl_fn!(visit_expr_path_mut, syn::ExprPath, { process_attrs(node.attrs); });
impl_fn!(visit_expr_range_mut, syn::ExprRange, { process_attrs(node.attrs); });
impl_fn!(visit_expr_reference_mut, syn::ExprReference, { process_attrs(node.attrs); });
impl_fn!(visit_expr_repeat_mut, syn::ExprRepeat, { process_attrs(node.attrs); });
impl_fn!(visit_expr_return_mut, syn::ExprReturn, { process_attrs(node.attrs); });
impl_fn!(visit_expr_struct_mut, syn::ExprStruct, { process_attrs(node.attrs); });
impl_fn!(visit_expr_try_mut, syn::ExprTry, { process_attrs(node.attrs); });
impl_fn!(visit_expr_try_block_mut, syn::ExprTryBlock, { process_attrs(node.attrs); });
impl_fn!(visit_expr_tuple_mut, syn::ExprTuple, { process_attrs(node.attrs); });
impl_fn!(visit_expr_type_mut, syn::ExprType, { process_attrs(node.attrs); });
impl_fn!(visit_expr_unary_mut, syn::ExprUnary, { process_attrs(node.attrs); });
impl_fn!(visit_expr_unsafe_mut, syn::ExprUnsafe, { process_attrs(node.attrs); });
impl_fn!(visit_expr_while_mut, syn::ExprWhile, { process_attrs(node.attrs); });
impl_fn!(visit_expr_yield_mut, syn::ExprYield, { process_attrs(node.attrs); });
impl_fn!(visit_field_mut, syn::Field, { process_attrs(node.attrs); });
impl_fn!(visit_field_pat_mut, syn::FieldPat, { process_attrs(node.attrs); });
impl_fn!(visit_field_value_mut, syn::FieldValue, { process_attrs(node.attrs); });
impl_fn!(visit_fields_mut, syn::Fields, );
impl_fn!(visit_fields_named_mut, syn::FieldsNamed, );
impl_fn!(visit_fields_unnamed_mut, syn::FieldsUnnamed, );
impl_fn!(visit_file_mut, syn::File, { process_attrs(node.attrs); process_file(node); });
impl_fn!(visit_fn_arg_mut, syn::FnArg, );
impl_fn!(visit_foreign_item_mut, syn::ForeignItem, );
impl_fn!(visit_foreign_item_fn_mut, syn::ForeignItemFn, { process_attrs(node.attrs); });
impl_fn!(visit_foreign_item_macro_mut, syn::ForeignItemMacro, { process_attrs(node.attrs); });
impl_fn!(visit_foreign_item_static_mut, syn::ForeignItemStatic, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_foreign_item_type_mut, syn::ForeignItemType, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_generic_argument_mut, syn::GenericArgument, );
impl_fn!(visit_generic_method_argument_mut,
syn::GenericMethodArgument,
);
impl_fn!(visit_generic_param_mut, syn::GenericParam, );
impl_fn!(visit_generics_mut, syn::Generics, );
impl_fn!(visit_ident_mut, syn::Ident, );
impl_fn!(visit_impl_item_mut, syn::ImplItem, );
impl_fn!(visit_impl_item_const_mut, syn::ImplItemConst, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_impl_item_macro_mut, syn::ImplItemMacro, { process_attrs(node.attrs); });
impl_fn!(visit_impl_item_method_mut, syn::ImplItemMethod, { process_attrs(node.attrs); });
impl_fn!(visit_impl_item_type_mut, syn::ImplItemType, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_index_mut, syn::Index, );
impl_fn!(visit_item_mut, syn::Item, { process_item(node); }, { after_process_item(node); });
impl_fn!(visit_item_const_mut, syn::ItemConst, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_enum_mut, syn::ItemEnum, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_extern_crate_mut, syn::ItemExternCrate, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); process_ident(node.rename as Some((_, value)), IdentMode::Other); });
impl_fn!(visit_item_fn_mut, syn::ItemFn, { process_attrs(node.attrs); process_item_fn(node); });
impl_fn!(visit_item_foreign_mod_mut, syn::ItemForeignMod, { process_attrs(node.attrs); });
impl_fn!(visit_item_impl_mut, syn::ItemImpl, { process_attrs(node.attrs); process_item_impl(node); });
impl_fn!(visit_item_macro_mut, syn::ItemMacro, { process_attrs(node.attrs); process_ident(node.ident as Some(value), IdentMode::Other); });
impl_fn!(visit_item_macro2_mut, syn::ItemMacro2, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_mod_mut, syn::ItemMod, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_static_mut, syn::ItemStatic, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_struct_mut, syn::ItemStruct, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_trait_mut, syn::ItemTrait, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); process_item_trait(node); });
impl_fn!(visit_item_trait_alias_mut, syn::ItemTraitAlias, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_type_mut, syn::ItemType, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_union_mut, syn::ItemUnion, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_item_use_mut, syn::ItemUse, { process_attrs(node.attrs); });
impl_fn!(visit_label_mut, syn::Label, );
impl_fn!(visit_lifetime_mut, syn::Lifetime, );
impl_fn!(visit_lifetime_def_mut, syn::LifetimeDef, { process_attrs(node.attrs); });
impl_fn!(visit_lit_mut, syn::Lit, );
impl_fn!(visit_lit_bool_mut, syn::LitBool, );
impl_fn!(visit_lit_byte_mut, syn::LitByte, );
impl_fn!(visit_lit_byte_str_mut, syn::LitByteStr, );
impl_fn!(visit_lit_char_mut, syn::LitChar, );
impl_fn!(visit_lit_float_mut, syn::LitFloat, );
impl_fn!(visit_lit_int_mut, syn::LitInt, );
impl_fn!(visit_lit_str_mut, syn::LitStr, );
impl_fn!(visit_local_mut, syn::Local, { process_attrs(node.attrs); });
impl_fn!(visit_macro_mut, syn::Macro, { process_macro(node); });
impl_fn!(visit_macro_delimiter_mut, syn::MacroDelimiter, );
impl_fn!(visit_member_mut, syn::Member, );
impl_fn!(visit_meta_mut, syn::Meta, );
impl_fn!(visit_meta_list_mut, syn::MetaList, );
impl_fn!(visit_meta_name_value_mut, syn::MetaNameValue, );
impl_fn!(visit_method_turbofish_mut, syn::MethodTurbofish, );
impl_fn!(visit_nested_meta_mut, syn::NestedMeta, );
impl_fn!(visit_parenthesized_generic_arguments_mut,
syn::ParenthesizedGenericArguments,
);
impl_fn!(visit_pat_mut, syn::Pat, );
impl_fn!(visit_pat_box_mut, syn::PatBox, { process_attrs(node.attrs); });
impl_fn!(visit_pat_ident_mut, syn::PatIdent, { process_attrs(node.attrs); });
impl_fn!(visit_pat_lit_mut, syn::PatLit, { process_attrs(node.attrs); });
impl_fn!(visit_pat_macro_mut, syn::PatMacro, { process_attrs(node.attrs); });
impl_fn!(visit_pat_or_mut, syn::PatOr, { process_attrs(node.attrs); });
impl_fn!(visit_pat_path_mut, syn::PatPath, { process_attrs(node.attrs); });
impl_fn!(visit_pat_range_mut, syn::PatRange, { process_attrs(node.attrs); });
impl_fn!(visit_pat_reference_mut, syn::PatReference, { process_attrs(node.attrs); });
impl_fn!(visit_pat_rest_mut, syn::PatRest, { process_attrs(node.attrs); });
impl_fn!(visit_pat_slice_mut, syn::PatSlice, { process_attrs(node.attrs); });
impl_fn!(visit_pat_struct_mut, syn::PatStruct, { process_attrs(node.attrs); });
impl_fn!(visit_pat_tuple_mut, syn::PatTuple, { process_attrs(node.attrs); });
impl_fn!(visit_pat_tuple_struct_mut, syn::PatTupleStruct, { process_attrs(node.attrs); });
impl_fn!(visit_pat_type_mut, syn::PatType, { process_attrs(node.attrs); });
impl_fn!(visit_pat_wild_mut, syn::PatWild, { process_attrs(node.attrs); });
impl_fn!(visit_path_mut, syn::Path, );
impl_fn!(visit_path_arguments_mut, syn::PathArguments, );
impl_fn!(visit_path_segment_mut, syn::PathSegment, { process_path_segment(node); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_predicate_eq_mut, syn::PredicateEq, );
impl_fn!(visit_predicate_lifetime_mut, syn::PredicateLifetime, );
impl_fn!(visit_predicate_type_mut, syn::PredicateType, );
impl_fn!(visit_qself_mut, syn::QSelf, );
impl_fn!(visit_range_limits_mut, syn::RangeLimits, );
impl_fn!(visit_receiver_mut, syn::Receiver, { process_attrs(node.attrs); });
impl_fn!(visit_return_type_mut, syn::ReturnType, );
impl_fn!(visit_signature_mut, syn::Signature, { process_ident(node.ident, IdentMode::Other); } );
impl_fn!(visit_span_mut, Span, );
impl_fn!(visit_stmt_mut, syn::Stmt, );
impl_fn!(visit_trait_bound_mut, syn::TraitBound, );
impl_fn!(visit_trait_bound_modifier_mut,syn::TraitBoundModifier,);
impl_fn!(visit_trait_item_mut, syn::TraitItem, );
impl_fn!(visit_trait_item_const_mut, syn::TraitItemConst, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_trait_item_macro_mut, syn::TraitItemMacro, { process_attrs(node.attrs); });
impl_fn!(visit_trait_item_method_mut, syn::TraitItemMethod, { process_attrs(node.attrs); });
impl_fn!(visit_trait_item_type_mut, syn::TraitItemType, { process_attrs(node.attrs); process_ident(node.ident, IdentMode::Other); });
impl_fn!(visit_type_mut, syn::Type, );
impl_fn!(visit_type_array_mut, syn::TypeArray, );
impl_fn!(visit_type_bare_fn_mut, syn::TypeBareFn, );
impl_fn!(visit_type_group_mut, syn::TypeGroup, );
impl_fn!(visit_type_impl_trait_mut, syn::TypeImplTrait, );
impl_fn!(visit_type_infer_mut, syn::TypeInfer, );
impl_fn!(visit_type_macro_mut, syn::TypeMacro, );
impl_fn!(visit_type_never_mut, syn::TypeNever, );
impl_fn!(visit_type_param_mut, syn::TypeParam, { process_attrs(node.attrs); process_type_param(node); });
impl_fn!(visit_type_param_bound_mut, syn::TypeParamBound, );
impl_fn!(visit_type_paren_mut, syn::TypeParen, );
impl_fn!(visit_type_path_mut, syn::TypePath, );
impl_fn!(visit_type_ptr_mut, syn::TypePtr, );
impl_fn!(visit_type_reference_mut, syn::TypeReference, );
impl_fn!(visit_type_slice_mut, syn::TypeSlice, );
impl_fn!(visit_type_trait_object_mut, syn::TypeTraitObject, );
impl_fn!(visit_type_tuple_mut, syn::TypeTuple, );
impl_fn!(visit_un_op_mut, syn::UnOp, );
impl_fn!(visit_use_glob_mut, syn::UseGlob, );
impl_fn!(visit_use_group_mut, syn::UseGroup, );
impl_fn!(visit_use_name_mut, syn::UseName, { process_ident(node.ident, IdentMode::Use); });
impl_fn!(visit_use_path_mut, syn::UsePath, { process_ident(node.ident, IdentMode::Use); });
impl_fn!(visit_use_rename_mut, syn::UseRename, { process_ident(node.ident, IdentMode::Use); process_ident(node.rename, IdentMode::Use); });
impl_fn!(visit_use_tree_mut, syn::UseTree, { process_use_tree(node); });
impl_fn!(visit_variadic_mut, syn::Variadic, { process_attrs(node.attrs); });
impl_fn!(visit_variant_mut, syn::Variant, { process_attrs(node.attrs); });
impl_fn!(visit_vis_crate_mut, syn::VisCrate, );
impl_fn!(visit_vis_public_mut, syn::VisPublic, );
impl_fn!(visit_vis_restricted_mut, syn::VisRestricted, );
impl_fn!(visit_visibility_mut, syn::Visibility, );
impl_fn!(visit_where_clause_mut, syn::WhereClause, );
impl_fn!(visit_where_predicate_mut, syn::WherePredicate, );
}