use unsynn::*;
pub type VerbatimUntil<C> = Many<Cons<Except<C>, AngleTokenTree>>;
keyword! {
pub KLevel = "level";
pub KName = "name";
pub KFn = "fn";
pub KPub = "pub";
pub KAsync = "async";
pub KUnsafe = "unsafe";
pub KExtern = "extern";
pub KConst = "const";
pub KWhere = "where";
pub KImpl = "impl";
pub KFor = "for";
pub KMod = "mod";
pub KTrait = "trait";
pub KCrate = "crate";
pub KSuper = "super";
pub KSelf = "self";
pub KMut = "mut";
pub KRet = "ret";
pub KDebug = "Debug";
pub KDisplay = "Display";
pub KTarget = "target";
pub KParent = "parent";
}
operator! {
pub Eq = "=";
pub And = "&";
}
unsynn! {
#[derive(Clone)]
pub struct AngleTokenTree(
pub Either<Cons<Lt, Vec<Cons<Except<Gt>, AngleTokenTree>>, Gt>, TokenTree>,
);
pub struct InstrumentInner {
pub args: Option<CommaDelimitedVec<InstrumentArg>>,
}
pub enum InstrumentArg {
Level(LevelArg),
Name(NameArg),
Target(TargetArg),
Parent(ParentArg),
Ret(RetArgs),
}
pub struct LevelArg {
pub _level: KLevel,
pub _eq: Eq,
pub value: LiteralString,
}
pub struct NameArg {
pub _name: KName,
pub _eq: Eq,
pub value: LiteralString,
}
pub struct TargetArg {
pub _target: KTarget,
pub _eq: Eq,
pub value: LiteralString,
}
pub struct ParentArg {
pub _parent: KParent,
pub _eq: Eq,
pub value: VerbatimUntil<Comma>, }
pub struct FnSig {
pub attributes: Option<Many<Attribute>>,
pub visibility: Option<Visibility>,
pub const_kw: Option<KConst>,
pub async_kw: Option<KAsync>,
pub unsafe_kw: Option<KUnsafe>,
pub extern_kw: Option<ExternSpec>,
pub _fn: KFn,
pub name: Ident,
pub generics: Option<Generics>,
pub params: ParenthesisGroupContaining<Option<CommaDelimitedVec<FnParam>>>,
pub return_type: Option<ReturnType>,
pub where_clause: Option<WhereClauses>,
pub body: BraceGroup,
}
pub struct Attribute {
pub _hash: Pound,
pub content: BracketGroup,
}
pub enum ExternSpec {
WithAbi(ExternWithAbi),
Bare(KExtern),
}
pub struct ExternWithAbi {
pub _extern: KExtern,
pub abi: LiteralString,
}
pub enum Visibility {
Restricted(RestrictedVis),
Public(KPub),
}
pub struct RestrictedVis {
pub _pub: KPub,
pub restriction: ParenthesisGroup,
}
pub struct Generics {
pub _lt: Lt,
pub content: Many<Cons<Except<Gt>, TokenTree>>,
pub _gt: Gt,
}
pub struct ReturnType {
pub _arrow: RArrow,
pub return_type: VerbatimUntil<BraceGroup>,
}
#[derive(Clone)]
pub struct WhereClause {
pub _pred: VerbatimUntil<Colon>,
pub _colon: Colon,
pub bounds: VerbatimUntil<Either<Comma, Semicolon, BraceGroup>>,
}
#[derive(Clone)]
pub struct WhereClauses {
pub _kw_where: KWhere,
pub clauses: CommaDelimitedVec<WhereClausePredicate>,
}
#[derive(Clone)]
pub struct WhereClausePredicate {
pub pred: VerbatimUntil<Colon>,
pub _colon: Colon,
pub bounds: VerbatimUntil<Either<Comma, BraceGroup>>,
}
pub enum ModuleItem {
Function(FnSig),
ImplBlock(ImplBlockSig),
Module(ModuleSig),
Trait(TraitSig),
Other(TokenTree),
}
pub struct ImplBlockSig {
pub attributes: Option<Many<Attribute>>,
pub _impl: KImpl,
pub generics: Option<Generics>,
pub target_type: Many<Cons<Except<Either<KFor, BraceGroup>>, TokenTree>>,
pub for_trait: Option<Cons<KFor, Many<Cons<Except<BraceGroup>, TokenTree>>>>,
pub where_clause: Option<WhereClauses>,
pub body: BraceGroup,
}
pub struct ModuleSig {
pub attributes: Option<Many<Attribute>>,
pub visibility: Option<Visibility>,
pub _mod: KMod,
pub name: Ident,
pub body: BraceGroup,
}
pub struct TraitSig {
pub attributes: Option<Many<Attribute>>,
pub visibility: Option<Visibility>,
pub unsafe_kw: Option<KUnsafe>,
pub _trait: KTrait,
pub name: Ident,
pub generics: Option<Generics>,
pub bounds: Option<Cons<Colon, Many<Cons<Except<Either<KWhere, BraceGroup>>, TokenTree>>>>,
pub where_clause: Option<WhereClauses>,
pub body: BraceGroup,
}
pub struct ModuleContent {
pub items: Many<ModuleItem>,
}
pub enum FnParam {
SelfParam(SelfParam),
Named(NamedParam),
Pattern(PatternParam),
}
pub enum SelfParam {
Value(KSelf),
Ref(Cons<And, KSelf>),
RefMut(Cons<And, Cons<KMut, KSelf>>),
Mut(Cons<KMut, KSelf>),
}
pub struct NamedParam {
pub mut_kw: Option<KMut>,
pub name: Ident,
pub _colon: Colon,
pub param_type: VerbatimUntil<Comma>,
}
pub struct PatternParam {
pub mut_kw: Option<KMut>,
pub pattern: Pattern,
pub _colon: Colon,
pub param_type: VerbatimUntil<Either<Comma, ParenthesisGroup>>,
}
pub enum Pattern {
Ident(Ident),
Tuple(TuplePattern),
Other(VerbatimUntil<Colon>),
}
pub struct TuplePattern {
pub fields: ParenthesisGroupContaining<Option<CommaDelimitedVec<PatternField>>>,
}
pub enum PatternField {
Ident(Ident),
Nested(Pattern),
}
pub struct RetArgs {
pub _ret: KRet,
pub args: Option<ParenthesisGroupContaining<Option<CommaDelimitedVec<RetArg>>>>,
}
pub enum RetArg {
Level(LevelArg),
Debug(KDebug), Display(KDisplay), }
#[derive(Clone, Default, PartialEq, Eq)]
pub enum FormatMode {
#[default] Debug,
Display,
}
}
impl RetArgs {
pub fn format_mode(&self) -> FormatMode {
if let Some(args_group) = &self.args {
if let Some(arg_list) = &args_group.content {
for arg in &arg_list.0 {
match &arg.value {
RetArg::Debug(_) => return FormatMode::Debug,
RetArg::Display(_) => return FormatMode::Display,
RetArg::Level(_) => continue,
}
}
}
}
FormatMode::default()
}
pub fn custom_level(&self) -> Option<&LevelArg> {
if let Some(args_group) = &self.args {
if let Some(arg_list) = &args_group.content {
for arg in &arg_list.0 {
if let RetArg::Level(level_arg) = &arg.value {
return Some(level_arg);
}
}
}
}
None
}
}
impl Pattern {
pub(crate) fn extract_identifiers(&self) -> Vec<&Ident> {
match self {
Pattern::Tuple(tuple) => {
if let Some(fields) = &tuple.fields.content {
fields
.0
.iter()
.filter_map(|field| {
if let PatternField::Ident(ident) = &field.value {
Some(ident)
} else {
None
}
})
.collect()
} else {
Vec::new()
}
}
Pattern::Ident(ident) => vec![ident],
_ => Vec::new(),
}
}
}
impl quote::ToTokens for FnSig {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if let Some(attrs) = &self.attributes {
for attr in &attrs.0 {
unsynn::ToTokens::to_tokens(attr, tokens);
}
}
if let Some(vis) = &self.visibility {
quote::ToTokens::to_tokens(vis, tokens);
}
if let Some(const_kw) = &self.const_kw {
unsynn::ToTokens::to_tokens(const_kw, tokens);
}
if let Some(async_kw) = &self.async_kw {
unsynn::ToTokens::to_tokens(async_kw, tokens);
}
if let Some(unsafe_kw) = &self.unsafe_kw {
unsynn::ToTokens::to_tokens(unsafe_kw, tokens);
}
if let Some(extern_kw) = &self.extern_kw {
unsynn::ToTokens::to_tokens(extern_kw, tokens);
}
unsynn::ToTokens::to_tokens(&self._fn, tokens);
quote::ToTokens::to_tokens(&self.name, tokens);
if let Some(generics) = &self.generics {
unsynn::ToTokens::to_tokens(generics, tokens);
}
unsynn::ToTokens::to_tokens(&self.params, tokens);
if let Some(ret_type) = &self.return_type {
unsynn::ToTokens::to_tokens(ret_type, tokens);
}
if let Some(where_clause) = &self.where_clause {
unsynn::ToTokens::to_tokens(where_clause, tokens);
}
unsynn::ToTokens::to_tokens(&self.body, tokens);
}
}
impl quote::ToTokens for FnParam {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match self {
FnParam::SelfParam(self_param) => quote::ToTokens::to_tokens(self_param, tokens),
FnParam::Named(named) => quote::ToTokens::to_tokens(named, tokens),
FnParam::Pattern(pattern) => quote::ToTokens::to_tokens(pattern, tokens),
}
}
}
impl quote::ToTokens for SelfParam {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match self {
SelfParam::Value(self_kw) => unsynn::ToTokens::to_tokens(self_kw, tokens),
SelfParam::Ref(ref_self) => unsynn::ToTokens::to_tokens(ref_self, tokens),
SelfParam::RefMut(ref_mut_self) => unsynn::ToTokens::to_tokens(ref_mut_self, tokens),
SelfParam::Mut(mut_self) => unsynn::ToTokens::to_tokens(mut_self, tokens),
}
}
}
impl quote::ToTokens for NamedParam {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if let Some(mut_kw) = &self.mut_kw {
unsynn::ToTokens::to_tokens(mut_kw, tokens);
}
quote::ToTokens::to_tokens(&self.name, tokens);
unsynn::ToTokens::to_tokens(&self._colon, tokens);
unsynn::ToTokens::to_tokens(&self.param_type, tokens);
}
}
impl quote::ToTokens for PatternParam {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if let Some(mut_kw) = &self.mut_kw {
unsynn::ToTokens::to_tokens(mut_kw, tokens);
}
unsynn::ToTokens::to_tokens(&self.pattern, tokens);
unsynn::ToTokens::to_tokens(&self._colon, tokens);
unsynn::ToTokens::to_tokens(&self.param_type, tokens);
}
}
impl quote::ToTokens for Pattern {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match self {
Pattern::Tuple(tuple) => quote::ToTokens::to_tokens(tuple, tokens),
Pattern::Ident(ident) => quote::ToTokens::to_tokens(ident, tokens),
Pattern::Other(other) => unsynn::ToTokens::to_tokens(other, tokens),
}
}
}
impl quote::ToTokens for TuplePattern {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self.fields, tokens);
}
}
impl quote::ToTokens for PatternField {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match self {
PatternField::Ident(ident) => quote::ToTokens::to_tokens(ident, tokens),
PatternField::Nested(pattern) => quote::ToTokens::to_tokens(pattern, tokens),
}
}
}
impl quote::ToTokens for Visibility {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match self {
Visibility::Public(pub_kw) => unsynn::ToTokens::to_tokens(pub_kw, tokens),
Visibility::Restricted(restricted) => unsynn::ToTokens::to_tokens(restricted, tokens),
}
}
}
impl quote::ToTokens for ExternSpec {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match self {
ExternSpec::WithAbi(with_abi) => unsynn::ToTokens::to_tokens(with_abi, tokens),
ExternSpec::Bare(extern_kw) => unsynn::ToTokens::to_tokens(extern_kw, tokens),
}
}
}
impl quote::ToTokens for ReturnType {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self._arrow, tokens);
unsynn::ToTokens::to_tokens(&self.return_type, tokens);
}
}
impl quote::ToTokens for Generics {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self._lt, tokens);
unsynn::ToTokens::to_tokens(&self.content, tokens);
unsynn::ToTokens::to_tokens(&self._gt, tokens);
}
}
impl quote::ToTokens for WhereClause {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self._pred, tokens);
unsynn::ToTokens::to_tokens(&self._colon, tokens);
unsynn::ToTokens::to_tokens(&self.bounds, tokens);
}
}
impl quote::ToTokens for WhereClauses {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self._kw_where, tokens);
unsynn::ToTokens::to_tokens(&self.clauses, tokens);
}
}
impl quote::ToTokens for Attribute {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self._hash, tokens);
unsynn::ToTokens::to_tokens(&self.content, tokens);
}
}
impl quote::ToTokens for RestrictedVis {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self._pub, tokens);
unsynn::ToTokens::to_tokens(&self.restriction, tokens);
}
}
impl quote::ToTokens for ExternWithAbi {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self._extern, tokens);
unsynn::ToTokens::to_tokens(&self.abi, tokens);
}
}
impl quote::ToTokens for ModuleItem {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
match self {
ModuleItem::Function(func) => quote::ToTokens::to_tokens(func, tokens),
ModuleItem::ImplBlock(impl_block) => quote::ToTokens::to_tokens(impl_block, tokens),
ModuleItem::Module(module) => quote::ToTokens::to_tokens(module, tokens),
ModuleItem::Trait(trait_def) => quote::ToTokens::to_tokens(trait_def, tokens),
ModuleItem::Other(token_tree) => unsynn::ToTokens::to_tokens(token_tree, tokens),
}
}
}
impl quote::ToTokens for ImplBlockSig {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if let Some(attrs) = &self.attributes {
for attr in &attrs.0 {
unsynn::ToTokens::to_tokens(attr, tokens);
}
}
unsynn::ToTokens::to_tokens(&self._impl, tokens);
if let Some(generics) = &self.generics {
unsynn::ToTokens::to_tokens(generics, tokens);
}
unsynn::ToTokens::to_tokens(&self.target_type, tokens);
if let Some(for_trait) = &self.for_trait {
unsynn::ToTokens::to_tokens(for_trait, tokens);
}
if let Some(where_clause) = &self.where_clause {
unsynn::ToTokens::to_tokens(where_clause, tokens);
}
unsynn::ToTokens::to_tokens(&self.body, tokens);
}
}
impl quote::ToTokens for ModuleSig {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if let Some(attrs) = &self.attributes {
for attr in &attrs.0 {
unsynn::ToTokens::to_tokens(attr, tokens);
}
}
if let Some(vis) = &self.visibility {
quote::ToTokens::to_tokens(vis, tokens);
}
unsynn::ToTokens::to_tokens(&self._mod, tokens);
quote::ToTokens::to_tokens(&self.name, tokens);
unsynn::ToTokens::to_tokens(&self.body, tokens);
}
}
impl quote::ToTokens for TraitSig {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
if let Some(attrs) = &self.attributes {
for attr in &attrs.0 {
unsynn::ToTokens::to_tokens(attr, tokens);
}
}
if let Some(vis) = &self.visibility {
quote::ToTokens::to_tokens(vis, tokens);
}
if let Some(unsafe_kw) = &self.unsafe_kw {
unsynn::ToTokens::to_tokens(unsafe_kw, tokens);
}
unsynn::ToTokens::to_tokens(&self._trait, tokens);
quote::ToTokens::to_tokens(&self.name, tokens);
if let Some(generics) = &self.generics {
unsynn::ToTokens::to_tokens(generics, tokens);
}
if let Some(bounds) = &self.bounds {
unsynn::ToTokens::to_tokens(bounds, tokens);
}
if let Some(where_clause) = &self.where_clause {
unsynn::ToTokens::to_tokens(where_clause, tokens);
}
unsynn::ToTokens::to_tokens(&self.body, tokens);
}
}
impl quote::ToTokens for ModuleContent {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
unsynn::ToTokens::to_tokens(&self.items, tokens);
}
}
#[cfg(test)]
mod tests;