syncdoc_core/
parse.rs

1//! Declarative parsing types using unsynn
2
3use unsynn::*;
4
5/// Parses tokens until `C` is found on the current token tree level.
6pub type VerbatimUntil<C> = Many<Cons<Except<C>, AngleTokenTree>>;
7
8keyword! {
9    /// The "path" keyword
10    pub KPath = "path";
11    /// The "name" keyword
12    pub KName = "name";
13    /// The "cfg_attr" keyword
14    pub KCfgAttr = "cfg_attr";
15    /// The "fn" keyword
16    pub KFn = "fn";
17    /// The "pub" keyword
18    pub KPub = "pub";
19    /// The "async" keyword
20    pub KAsync = "async";
21    /// The "unsafe" keyword
22    pub KUnsafe = "unsafe";
23    /// The "extern" keyword
24    pub KExtern = "extern";
25    /// The "const" keyword
26    pub KConst = "const";
27    /// The "where" keyword
28    pub KWhere = "where";
29    /// The "impl" keyword
30    pub KImpl = "impl";
31    /// The "for" keyword
32    pub KFor = "for";
33    /// The "mod" keyword
34    pub KMod = "mod";
35    /// The "trait" keyword
36    pub KTrait = "trait";
37    /// The "crate" keyword
38    pub KCrate = "crate";
39    /// The "super" keyword
40    pub KSuper = "super";
41    /// The "self" keyword
42    pub KSelf = "self";
43    /// The "mut" keyword
44    pub KMut = "mut";
45    /// The "enum" keyword
46    pub KEnum = "enum";
47    /// The "struct" keyword
48    pub KStruct = "struct";
49    /// The "type" keyword
50    pub KType = "type";
51    /// The "static" keyword
52    pub KStatic = "static";
53}
54
55operator! {
56    /// The "=" operator
57    pub Eq = "=";
58    /// The "&" operator
59    pub And = "&";
60}
61
62unsynn! {
63    /// Parses either a `TokenTree` or `<...>` grouping
64    #[derive(Clone)]
65    pub struct AngleTokenTree(
66        pub Either<Cons<Lt, Vec<Cons<Except<Gt>, AngleTokenTree>>, Gt>, TokenTree>,
67    );
68
69    /// Declarative syncdoc arguments structure
70    pub struct SyncDocInner {
71        /// Comma-delimited list of arguments
72        pub args: Option<CommaDelimitedVec<SyncDocArg>>,
73    }
74
75    /// Single syncdoc argument
76    pub enum SyncDocArg {
77        /// path = "docs"
78        Path(PathArg),
79        /// name = "custom"
80        Name(NameArg),
81        /// cfg_attr = "doc"
82        CfgAttr(CfgAttrArg),
83    }
84
85    /// Path argument: path = "docs"
86    pub struct PathArg {
87        pub _path: KPath,
88        pub _eq: Eq,
89        pub value: LiteralString,
90    }
91
92    /// Name argument: name = "custom"
93    pub struct NameArg {
94        pub _name: KName,
95        pub _eq: Eq,
96        pub value: LiteralString,
97    }
98
99    /// Name argument: name = "custom"
100    pub struct CfgAttrArg {
101        pub _cfg_attr: KCfgAttr,
102        pub _eq: Eq,
103        pub value: LiteralString,
104    }
105
106    /// Complete function signature
107    pub struct FnSig {
108        /// Optional attributes (#[...])
109        pub attributes: Option<Many<Attribute>>,
110        /// Optional visibility (pub, pub(crate), etc.)
111        pub visibility: Option<Visibility>,
112        /// Optional const modifier
113        pub const_kw: Option<KConst>,
114        /// Optional async modifier
115        pub async_kw: Option<KAsync>,
116        /// Optional unsafe modifier
117        pub unsafe_kw: Option<KUnsafe>,
118        /// Optional extern with optional ABI
119        pub extern_kw: Option<ExternSpec>,
120        /// The "fn" keyword
121        pub _fn: KFn,
122        /// Function name
123        pub name: Ident,
124        /// Optional generic parameters
125        pub generics: Option<Generics>,
126        /// Parameters in parentheses
127        pub params: ParenthesisGroupContaining<Option<CommaDelimitedVec<FnParam>>>,
128        /// Optional return type
129        pub return_type: Option<ReturnType>,
130        /// Optional where clause
131        pub where_clause: Option<WhereClauses>,
132        pub body: BraceGroup,
133    }
134
135    /// (Outer) Attribute like #[derive(Debug)]
136    #[derive(Clone)]
137    pub struct Attribute {
138        /// Hash symbol
139        pub _hash: Pound,
140        /// Attribute content
141        pub content: BracketGroup,
142    }
143
144    /// Inner attribute like #![forbid(unsafe_code)]
145    #[derive(Clone)]
146    pub struct InnerAttribute {
147        /// Hash symbol
148        pub _hash: Pound,
149        /// Bang symbol
150        pub _bang: Bang,
151        /// Attribute content
152        pub content: BracketGroup,
153    }
154
155    /// Either an inner or outer attribute
156    pub enum AnyAttribute {
157        Inner(InnerAttribute),
158        Outer(Attribute),
159    }
160
161    /// Extern specification with optional ABI
162    pub enum ExternSpec {
163        /// "extern" with ABI string like extern "C"
164        WithAbi(ExternWithAbi),
165        /// Just "extern"
166        Bare(KExtern),
167    }
168
169    /// Extern with ABI string
170    pub struct ExternWithAbi {
171        /// The "extern" keyword
172        pub _extern: KExtern,
173        /// The ABI string
174        pub abi: LiteralString,
175    }
176
177    /// Simple visibility parsing
178    pub enum Visibility {
179        /// "pub(crate)", "pub(super)", etc.
180        Restricted(RestrictedVis),
181        /// Just "pub"
182        Public(KPub),
183    }
184
185    /// Restricted visibility like pub(crate)
186    pub struct RestrictedVis {
187        /// The "pub" keyword
188        pub _pub: KPub,
189        /// The parentheses with content
190        pub restriction: ParenthesisGroup,
191    }
192
193    /// Simple generics (treat as opaque for now)
194    pub struct Generics {
195        /// Opening
196        pub _lt: Lt,
197        /// Everything until closing > (opaque)
198        pub content: Many<Cons<Except<Gt>, TokenTree>>,
199        /// Closing >
200        pub _gt: Gt,
201    }
202
203    /// Return type: -> Type
204    pub struct ReturnType {
205        /// Arrow
206        pub _arrow: RArrow,
207        /// Everything until brace (opaque)
208        pub return_type: VerbatimUntil<BraceGroup>,
209    }
210
211    /// Represents a single predicate within a `where` clause.
212    #[derive(Clone)]
213    pub struct WhereClause {
214        /// The type or lifetime being constrained (e.g., `T` or `'a`).
215        pub _pred: VerbatimUntil<Colon>,
216        /// The colon separating the constrained item and its bounds.
217        pub _colon: Colon,
218        /// The bounds applied to the type or lifetime (e.g., `Trait` or `'b`).
219        pub bounds: VerbatimUntil<Either<Comma, Semicolon, BraceGroup>>,
220    }
221
222    /// Where clauses: where T: Trait, U: Send
223    #[derive(Clone)]
224    pub struct WhereClauses {
225        /// The `where` keyword.
226        pub _kw_where: KWhere,
227        /// The comma-delimited list of where clause predicates.
228        pub clauses: CommaDelimitedVec<WhereClausePredicate>,
229    }
230
231    /// Single where clause predicate: T: Trait
232    #[derive(Clone)]
233    pub struct WhereClausePredicate {
234        /// The type being constrained (e.g., `T`)
235        pub pred: VerbatimUntil<Colon>,
236        /// The colon
237        pub _colon: Colon,
238        /// The bounds (e.g., `Trait`)
239        pub bounds: VerbatimUntil<Either<Comma, BraceGroup>>,
240    }
241
242    /// Top-level item that can appear in a module
243    pub enum ModuleItem {
244        /// A function definition
245        Function(FnSig),
246        /// An impl block
247        ImplBlock(ImplBlockSig),
248        /// A module definition
249        Module(ModuleSig),
250        /// A trait definition
251        Trait(TraitSig),
252        /// An enum definition
253        Enum(EnumSig),
254        /// A struct definition
255        Struct(StructSig),
256        /// A type alias
257        TypeAlias(TypeAliasSig),
258        /// A constant
259        Const(ConstSig),
260        /// A static
261        Static(StaticSig),
262        /// Any other item (use, extern crate, etc.)
263        Other(TokenTree),
264    }
265
266    /// impl Type { ... } block
267    pub struct ImplBlockSig {
268        /// Optional attributes
269        pub attributes: Option<Many<Attribute>>,
270        /// "impl" keyword
271        pub _impl: KImpl,
272        /// Optional generic parameters
273        pub generics: Option<Generics>,
274        /// Type being implemented (opaque for now)
275        pub target_type: Many<Cons<Except<Either<KFor, BraceGroup>>, TokenTree>>,
276        /// Optional "for Trait" part
277        pub for_trait: Option<Cons<KFor, Many<Cons<Except<BraceGroup>, TokenTree>>>>,
278        /// Optional where clause
279        pub where_clause: Option<WhereClauses>,
280        /// Block body
281        pub body: BraceGroup,
282    }
283
284    /// mod name { ... } block
285    pub struct ModuleSig {
286        /// Optional attributes
287        pub attributes: Option<Many<Attribute>>,
288        /// Optional visibility
289        pub visibility: Option<Visibility>,
290        /// "mod" keyword
291        pub _mod: KMod,
292        /// Module name
293        pub name: Ident,
294        /// Module body
295        pub body: BraceGroup,
296    }
297
298    /// trait Name { ... } block
299    pub struct TraitSig {
300        /// Optional attributes
301        pub attributes: Option<Many<Attribute>>,
302        /// Optional visibility
303        pub visibility: Option<Visibility>,
304        /// Optional unsafe
305        pub unsafe_kw: Option<KUnsafe>,
306        /// "trait" keyword
307        pub _trait: KTrait,
308        /// Trait name
309        pub name: Ident,
310        /// Optional generic parameters
311        pub generics: Option<Generics>,
312        /// Optional trait bounds
313        pub bounds: Option<Cons<Colon, Many<Cons<Except<Either<KWhere, BraceGroup>>, TokenTree>>>>,
314        /// Optional where clause
315        pub where_clause: Option<WhereClauses>,
316        /// Trait body
317        pub body: BraceGroup,
318    }
319
320    /// enum Name { ... } block
321    pub struct EnumSig {
322        /// Optional attributes
323        pub attributes: Option<Many<Attribute>>,
324        /// Optional visibility
325        pub visibility: Option<Visibility>,
326        /// "enum" keyword
327        pub _enum: KEnum,
328        /// Enum name
329        pub name: Ident,
330        /// Optional generic parameters
331        pub generics: Option<Generics>,
332        /// Optional where clause
333        pub where_clause: Option<WhereClauses>,
334        /// Enum body
335        pub body: BraceGroup,
336    }
337
338    /// struct Name { ... } or struct Name;
339    pub struct StructSig {
340        /// Optional attributes
341        pub attributes: Option<Many<Attribute>>,
342        /// Optional visibility
343        pub visibility: Option<Visibility>,
344        /// "struct" keyword
345        pub _struct: KStruct,
346        /// Struct name
347        pub name: Ident,
348        /// Optional generic parameters
349        pub generics: Option<Generics>,
350        /// Optional where clause
351        pub where_clause: Option<WhereClauses>,
352        /// Struct body (could be brace group, tuple, or unit)
353        pub body: StructBody,
354    }
355
356    /// Struct body variants
357    pub enum StructBody {
358        /// Named fields: { field: Type }
359        Named(BraceGroup),
360        /// Tuple fields: (Type, Type)
361        Tuple(Cons<ParenthesisGroup, Semicolon>),
362        /// Unit struct: ;
363        Unit(Semicolon),
364    }
365
366    /// Named struct field: pub name: Type
367    pub struct StructField {
368        /// Optional attributes
369        pub attributes: Option<Many<Attribute>>,
370        /// Optional visibility
371        pub visibility: Option<Visibility>,
372        /// Field name
373        pub name: Ident,
374        /// Colon
375        pub _colon: Colon,
376        /// Field type (everything until comma or brace closing)
377        pub field_type: VerbatimUntil<Either<Comma, BraceGroup>>,
378    }
379
380    /// type Alias = Type;
381    pub struct TypeAliasSig {
382        /// Optional attributes
383        pub attributes: Option<Many<Attribute>>,
384        /// Optional visibility
385        pub visibility: Option<Visibility>,
386        /// "type" keyword
387        pub _type: KType,
388        /// Alias name
389        pub name: Ident,
390        /// Optional generic parameters
391        pub generics: Option<Generics>,
392        /// Equals sign
393        pub _eq: Eq,
394        /// Target type (everything until semicolon)
395        pub target: VerbatimUntil<Semicolon>,
396        /// Semicolon
397        pub _semi: Semicolon,
398    }
399
400    /// const NAME: Type = value;
401    pub struct ConstSig {
402        /// Optional attributes
403        pub attributes: Option<Many<Attribute>>,
404        /// Optional visibility
405        pub visibility: Option<Visibility>,
406        /// "const" keyword
407        pub _const: KConst,
408        /// Constant name
409        pub name: Ident,
410        /// Colon
411        pub _colon: Colon,
412        /// Type (everything until equals)
413        pub const_type: VerbatimUntil<Eq>,
414        /// Equals sign
415        pub _eq: Eq,
416        /// Value (everything until semicolon)
417        pub value: VerbatimUntil<Semicolon>,
418        /// Semicolon
419        pub _semi: Semicolon,
420    }
421
422    /// static NAME: Type = value;
423    pub struct StaticSig {
424        /// Optional attributes
425        pub attributes: Option<Many<Attribute>>,
426        /// Optional visibility
427        pub visibility: Option<Visibility>,
428        /// Optional mut keyword
429        pub mut_kw: Option<KMut>,
430        /// "static" keyword
431        pub _static: KStatic,
432        /// Static name
433        pub name: Ident,
434        /// Colon
435        pub _colon: Colon,
436        /// Type (everything until equals)
437        pub static_type: VerbatimUntil<Eq>,
438        /// Equals sign
439        pub _eq: Eq,
440        /// Value (everything until semicolon)
441        pub value: VerbatimUntil<Semicolon>,
442        /// Semicolon
443        pub _semi: Semicolon,
444    }
445
446    /// Single enum variant
447    pub struct EnumVariant {
448        /// Optional attributes
449        pub attributes: Option<Many<Attribute>>,
450        /// Variant name
451        pub name: Ident,
452        /// Optional variant data (fields or discriminant)
453        pub data: Option<EnumVariantData>,
454    }
455
456    /// Enum variant data
457    pub enum EnumVariantData {
458        /// Tuple variant: (Type, Type)
459        Tuple(ParenthesisGroup),
460        /// Struct variant: { field: Type }
461        Struct(BraceGroup),
462        /// Discriminant: = value
463        Discriminant(Cons<Eq, VerbatimUntil<Either<Comma, BraceGroup>>>),
464    }
465
466    /// A complete module/file content
467    pub struct ModuleContent {
468        /// Inner attributes at the top of the module (#![...])
469        pub inner_attrs: Option<Many<InnerAttribute>>,
470        /// All items in the module
471        pub items: Many<ModuleItem>,
472    }
473
474    /// Function parameter: name: Type or self variants
475    pub enum FnParam {
476        /// self parameter
477        SelfParam(SelfParam),
478        /// Regular parameter: name: Type
479        Named(NamedParam),
480        /// Pattern parameter: (a, b): (i32, i32)
481        Pattern(PatternParam),
482    }
483
484    /// self, &self, &mut self, mut self
485    pub enum SelfParam {
486        /// self
487        Value(KSelf),
488        /// &self
489        Ref(Cons<And, KSelf>),
490        /// &mut self
491        RefMut(Cons<And, Cons<KMut, KSelf>>),
492        /// mut self
493        Mut(Cons<KMut, KSelf>),
494    }
495
496    /// name: Type parameter
497    pub struct NamedParam {
498        /// Optional mut keyword
499        pub mut_kw: Option<KMut>,
500        /// Parameter name
501        pub name: Ident,
502        /// Colon
503        pub _colon: Colon,
504        /// Parameter type (opaque for now)
505        pub param_type: VerbatimUntil<Comma>,
506    }
507
508    /// Pattern parameter like (a, b): (i32, i32) or mut (x, y): Point
509    pub struct PatternParam {
510        /// Optional mut keyword
511        pub mut_kw: Option<KMut>,
512        /// Pattern (everything before colon, could be tuple, struct pattern, etc.)
513        pub pattern: Pattern,
514        /// Colon
515        pub _colon: Colon,
516        /// Parameter type
517        pub param_type: VerbatimUntil<Either<Comma, ParenthesisGroup>>,
518    }
519
520   /// Different types of patterns
521    pub enum Pattern {
522        /// Simple identifier: value
523        Ident(Ident),
524        /// Tuple pattern: (a, b, c)
525        Tuple(TuplePattern),
526        /// Other patterns (fallback)
527        Other(VerbatimUntil<Colon>),
528    }
529
530    /// Tuple destructuring pattern: (a, b, c)
531    pub struct TuplePattern {
532        /// Parentheses containing comma-separated identifiers
533        pub fields: ParenthesisGroupContaining<Option<CommaDelimitedVec<PatternField>>>,
534    }
535
536    /// Field in a pattern
537    pub enum PatternField {
538        /// Simple identifier
539        Ident(Ident),
540        /// Nested pattern (recursive)
541        Nested(Pattern),
542    }
543}
544
545// Implement ToTokens for quote! compatibility
546impl quote::ToTokens for FnSig {
547    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
548        // Add attributes
549        if let Some(attrs) = &self.attributes {
550            for attr in &attrs.0 {
551                unsynn::ToTokens::to_tokens(attr, tokens);
552            }
553        }
554
555        // Add visibility
556        if let Some(vis) = &self.visibility {
557            quote::ToTokens::to_tokens(vis, tokens);
558        }
559
560        // Add const keyword
561        if let Some(const_kw) = &self.const_kw {
562            unsynn::ToTokens::to_tokens(const_kw, tokens);
563        }
564
565        // Add async keyword
566        if let Some(async_kw) = &self.async_kw {
567            unsynn::ToTokens::to_tokens(async_kw, tokens);
568        }
569
570        // Add unsafe keyword
571        if let Some(unsafe_kw) = &self.unsafe_kw {
572            unsynn::ToTokens::to_tokens(unsafe_kw, tokens);
573        }
574
575        // Add extern specification
576        if let Some(extern_kw) = &self.extern_kw {
577            unsynn::ToTokens::to_tokens(extern_kw, tokens);
578        }
579
580        // Add fn keyword and the rest
581        unsynn::ToTokens::to_tokens(&self._fn, tokens);
582        quote::ToTokens::to_tokens(&self.name, tokens);
583
584        if let Some(generics) = &self.generics {
585            unsynn::ToTokens::to_tokens(generics, tokens);
586        }
587
588        unsynn::ToTokens::to_tokens(&self.params, tokens);
589
590        if let Some(ret_type) = &self.return_type {
591            unsynn::ToTokens::to_tokens(ret_type, tokens);
592        }
593
594        if let Some(where_clause) = &self.where_clause {
595            unsynn::ToTokens::to_tokens(where_clause, tokens);
596        }
597
598        unsynn::ToTokens::to_tokens(&self.body, tokens);
599    }
600}
601
602impl quote::ToTokens for FnParam {
603    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
604        match self {
605            FnParam::SelfParam(self_param) => quote::ToTokens::to_tokens(self_param, tokens),
606            FnParam::Named(named) => quote::ToTokens::to_tokens(named, tokens),
607            FnParam::Pattern(pattern) => quote::ToTokens::to_tokens(pattern, tokens),
608        }
609    }
610}
611
612impl quote::ToTokens for SelfParam {
613    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
614        match self {
615            SelfParam::Value(self_kw) => unsynn::ToTokens::to_tokens(self_kw, tokens),
616            SelfParam::Ref(ref_self) => unsynn::ToTokens::to_tokens(ref_self, tokens),
617            SelfParam::RefMut(ref_mut_self) => unsynn::ToTokens::to_tokens(ref_mut_self, tokens),
618            SelfParam::Mut(mut_self) => unsynn::ToTokens::to_tokens(mut_self, tokens),
619        }
620    }
621}
622
623impl quote::ToTokens for NamedParam {
624    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
625        if let Some(mut_kw) = &self.mut_kw {
626            unsynn::ToTokens::to_tokens(mut_kw, tokens);
627        }
628        quote::ToTokens::to_tokens(&self.name, tokens);
629        unsynn::ToTokens::to_tokens(&self._colon, tokens);
630        unsynn::ToTokens::to_tokens(&self.param_type, tokens);
631    }
632}
633
634impl quote::ToTokens for PatternParam {
635    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
636        if let Some(mut_kw) = &self.mut_kw {
637            unsynn::ToTokens::to_tokens(mut_kw, tokens);
638        }
639        unsynn::ToTokens::to_tokens(&self.pattern, tokens);
640        unsynn::ToTokens::to_tokens(&self._colon, tokens);
641        unsynn::ToTokens::to_tokens(&self.param_type, tokens);
642    }
643}
644
645impl quote::ToTokens for Pattern {
646    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
647        match self {
648            Pattern::Tuple(tuple) => quote::ToTokens::to_tokens(tuple, tokens),
649            Pattern::Ident(ident) => quote::ToTokens::to_tokens(ident, tokens),
650            Pattern::Other(other) => unsynn::ToTokens::to_tokens(other, tokens),
651        }
652    }
653}
654
655impl quote::ToTokens for TuplePattern {
656    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
657        unsynn::ToTokens::to_tokens(&self.fields, tokens);
658    }
659}
660
661impl quote::ToTokens for PatternField {
662    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
663        match self {
664            PatternField::Ident(ident) => quote::ToTokens::to_tokens(ident, tokens),
665            PatternField::Nested(pattern) => quote::ToTokens::to_tokens(pattern, tokens),
666        }
667    }
668}
669
670impl quote::ToTokens for Visibility {
671    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
672        match self {
673            Visibility::Public(pub_kw) => unsynn::ToTokens::to_tokens(pub_kw, tokens),
674            Visibility::Restricted(restricted) => unsynn::ToTokens::to_tokens(restricted, tokens),
675        }
676    }
677}
678
679impl quote::ToTokens for ExternSpec {
680    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
681        match self {
682            ExternSpec::WithAbi(with_abi) => unsynn::ToTokens::to_tokens(with_abi, tokens),
683            ExternSpec::Bare(extern_kw) => unsynn::ToTokens::to_tokens(extern_kw, tokens),
684        }
685    }
686}
687
688impl quote::ToTokens for ReturnType {
689    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
690        unsynn::ToTokens::to_tokens(&self._arrow, tokens);
691        unsynn::ToTokens::to_tokens(&self.return_type, tokens);
692    }
693}
694
695impl quote::ToTokens for Generics {
696    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
697        unsynn::ToTokens::to_tokens(&self._lt, tokens);
698        unsynn::ToTokens::to_tokens(&self.content, tokens);
699        unsynn::ToTokens::to_tokens(&self._gt, tokens);
700    }
701}
702
703impl quote::ToTokens for WhereClause {
704    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
705        unsynn::ToTokens::to_tokens(&self._pred, tokens);
706        unsynn::ToTokens::to_tokens(&self._colon, tokens);
707        unsynn::ToTokens::to_tokens(&self.bounds, tokens);
708    }
709}
710
711impl quote::ToTokens for WhereClauses {
712    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
713        unsynn::ToTokens::to_tokens(&self._kw_where, tokens);
714        unsynn::ToTokens::to_tokens(&self.clauses, tokens);
715    }
716}
717
718impl quote::ToTokens for Attribute {
719    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
720        unsynn::ToTokens::to_tokens(&self._hash, tokens);
721        unsynn::ToTokens::to_tokens(&self.content, tokens);
722    }
723}
724
725impl quote::ToTokens for InnerAttribute {
726    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
727        unsynn::ToTokens::to_tokens(&self._hash, tokens);
728        unsynn::ToTokens::to_tokens(&self._bang, tokens);
729        unsynn::ToTokens::to_tokens(&self.content, tokens);
730    }
731}
732
733impl quote::ToTokens for AnyAttribute {
734    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
735        match self {
736            AnyAttribute::Inner(inner) => quote::ToTokens::to_tokens(inner, tokens),
737            AnyAttribute::Outer(outer) => quote::ToTokens::to_tokens(outer, tokens),
738        }
739    }
740}
741
742impl quote::ToTokens for RestrictedVis {
743    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
744        unsynn::ToTokens::to_tokens(&self._pub, tokens);
745        unsynn::ToTokens::to_tokens(&self.restriction, tokens);
746    }
747}
748
749impl quote::ToTokens for ExternWithAbi {
750    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
751        unsynn::ToTokens::to_tokens(&self._extern, tokens);
752        unsynn::ToTokens::to_tokens(&self.abi, tokens);
753    }
754}
755
756impl quote::ToTokens for ModuleItem {
757    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
758        match self {
759            ModuleItem::Function(func) => quote::ToTokens::to_tokens(func, tokens),
760            ModuleItem::ImplBlock(impl_block) => quote::ToTokens::to_tokens(impl_block, tokens),
761            ModuleItem::Module(module) => quote::ToTokens::to_tokens(module, tokens),
762            ModuleItem::Trait(trait_def) => quote::ToTokens::to_tokens(trait_def, tokens),
763            ModuleItem::Enum(enum_sig) => quote::ToTokens::to_tokens(enum_sig, tokens),
764            ModuleItem::Struct(struct_sig) => quote::ToTokens::to_tokens(struct_sig, tokens),
765            ModuleItem::TypeAlias(type_alias) => quote::ToTokens::to_tokens(type_alias, tokens),
766            ModuleItem::Const(const_sig) => quote::ToTokens::to_tokens(const_sig, tokens),
767            ModuleItem::Static(static_sig) => quote::ToTokens::to_tokens(static_sig, tokens),
768            ModuleItem::Other(token_tree) => unsynn::ToTokens::to_tokens(token_tree, tokens),
769        }
770    }
771}
772
773impl quote::ToTokens for ImplBlockSig {
774    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
775        if let Some(attrs) = &self.attributes {
776            for attr in &attrs.0 {
777                unsynn::ToTokens::to_tokens(attr, tokens);
778            }
779        }
780        unsynn::ToTokens::to_tokens(&self._impl, tokens);
781        if let Some(generics) = &self.generics {
782            unsynn::ToTokens::to_tokens(generics, tokens);
783        }
784        unsynn::ToTokens::to_tokens(&self.target_type, tokens);
785        if let Some(for_trait) = &self.for_trait {
786            unsynn::ToTokens::to_tokens(for_trait, tokens);
787        }
788        if let Some(where_clause) = &self.where_clause {
789            unsynn::ToTokens::to_tokens(where_clause, tokens);
790        }
791        unsynn::ToTokens::to_tokens(&self.body, tokens);
792    }
793}
794
795impl quote::ToTokens for ModuleSig {
796    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
797        if let Some(attrs) = &self.attributes {
798            for attr in &attrs.0 {
799                unsynn::ToTokens::to_tokens(attr, tokens);
800            }
801        }
802        if let Some(vis) = &self.visibility {
803            quote::ToTokens::to_tokens(vis, tokens);
804        }
805        unsynn::ToTokens::to_tokens(&self._mod, tokens);
806        quote::ToTokens::to_tokens(&self.name, tokens);
807        unsynn::ToTokens::to_tokens(&self.body, tokens);
808    }
809}
810
811impl quote::ToTokens for TraitSig {
812    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
813        if let Some(attrs) = &self.attributes {
814            for attr in &attrs.0 {
815                unsynn::ToTokens::to_tokens(attr, tokens);
816            }
817        }
818        if let Some(vis) = &self.visibility {
819            quote::ToTokens::to_tokens(vis, tokens);
820        }
821        if let Some(unsafe_kw) = &self.unsafe_kw {
822            unsynn::ToTokens::to_tokens(unsafe_kw, tokens);
823        }
824        unsynn::ToTokens::to_tokens(&self._trait, tokens);
825        quote::ToTokens::to_tokens(&self.name, tokens);
826        if let Some(generics) = &self.generics {
827            unsynn::ToTokens::to_tokens(generics, tokens);
828        }
829        if let Some(bounds) = &self.bounds {
830            unsynn::ToTokens::to_tokens(bounds, tokens);
831        }
832        if let Some(where_clause) = &self.where_clause {
833            unsynn::ToTokens::to_tokens(where_clause, tokens);
834        }
835        unsynn::ToTokens::to_tokens(&self.body, tokens);
836    }
837}
838
839impl quote::ToTokens for ModuleContent {
840    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
841        // Output inner attributes first
842        if let Some(inner_attrs) = &self.inner_attrs {
843            for attr_delimited in &inner_attrs.0 {
844                quote::ToTokens::to_tokens(&attr_delimited.value, tokens);
845            }
846        }
847        unsynn::ToTokens::to_tokens(&self.items, tokens);
848    }
849}
850
851impl quote::ToTokens for EnumSig {
852    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
853        if let Some(attrs) = &self.attributes {
854            for attr in &attrs.0 {
855                unsynn::ToTokens::to_tokens(attr, tokens);
856            }
857        }
858        if let Some(vis) = &self.visibility {
859            quote::ToTokens::to_tokens(vis, tokens);
860        }
861        unsynn::ToTokens::to_tokens(&self._enum, tokens);
862        quote::ToTokens::to_tokens(&self.name, tokens);
863        if let Some(generics) = &self.generics {
864            unsynn::ToTokens::to_tokens(generics, tokens);
865        }
866        if let Some(where_clause) = &self.where_clause {
867            unsynn::ToTokens::to_tokens(where_clause, tokens);
868        }
869        unsynn::ToTokens::to_tokens(&self.body, tokens);
870    }
871}
872
873impl quote::ToTokens for StructSig {
874    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
875        if let Some(attrs) = &self.attributes {
876            for attr in &attrs.0 {
877                unsynn::ToTokens::to_tokens(attr, tokens);
878            }
879        }
880        if let Some(vis) = &self.visibility {
881            quote::ToTokens::to_tokens(vis, tokens);
882        }
883        unsynn::ToTokens::to_tokens(&self._struct, tokens);
884        quote::ToTokens::to_tokens(&self.name, tokens);
885        if let Some(generics) = &self.generics {
886            unsynn::ToTokens::to_tokens(generics, tokens);
887        }
888        if let Some(where_clause) = &self.where_clause {
889            unsynn::ToTokens::to_tokens(where_clause, tokens);
890        }
891        quote::ToTokens::to_tokens(&self.body, tokens);
892    }
893}
894
895impl quote::ToTokens for StructBody {
896    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
897        match self {
898            StructBody::Named(brace) => unsynn::ToTokens::to_tokens(brace, tokens),
899            StructBody::Tuple(tuple) => unsynn::ToTokens::to_tokens(tuple, tokens),
900            StructBody::Unit(semi) => unsynn::ToTokens::to_tokens(semi, tokens),
901        }
902    }
903}
904
905impl quote::ToTokens for StructField {
906    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
907        if let Some(attrs) = &self.attributes {
908            for attr in &attrs.0 {
909                unsynn::ToTokens::to_tokens(attr, tokens);
910            }
911        }
912        if let Some(vis) = &self.visibility {
913            quote::ToTokens::to_tokens(vis, tokens);
914        }
915        quote::ToTokens::to_tokens(&self.name, tokens);
916        unsynn::ToTokens::to_tokens(&self._colon, tokens);
917        unsynn::ToTokens::to_tokens(&self.field_type, tokens);
918    }
919}
920
921impl quote::ToTokens for TypeAliasSig {
922    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
923        if let Some(attrs) = &self.attributes {
924            for attr in &attrs.0 {
925                unsynn::ToTokens::to_tokens(attr, tokens);
926            }
927        }
928        if let Some(vis) = &self.visibility {
929            quote::ToTokens::to_tokens(vis, tokens);
930        }
931        unsynn::ToTokens::to_tokens(&self._type, tokens);
932        quote::ToTokens::to_tokens(&self.name, tokens);
933        if let Some(generics) = &self.generics {
934            unsynn::ToTokens::to_tokens(generics, tokens);
935        }
936        unsynn::ToTokens::to_tokens(&self._eq, tokens);
937        unsynn::ToTokens::to_tokens(&self.target, tokens);
938        unsynn::ToTokens::to_tokens(&self._semi, tokens);
939    }
940}
941
942impl quote::ToTokens for ConstSig {
943    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
944        if let Some(attrs) = &self.attributes {
945            for attr in &attrs.0 {
946                unsynn::ToTokens::to_tokens(attr, tokens);
947            }
948        }
949        if let Some(vis) = &self.visibility {
950            quote::ToTokens::to_tokens(vis, tokens);
951        }
952        unsynn::ToTokens::to_tokens(&self._const, tokens);
953        quote::ToTokens::to_tokens(&self.name, tokens);
954        unsynn::ToTokens::to_tokens(&self._colon, tokens);
955        unsynn::ToTokens::to_tokens(&self.const_type, tokens);
956        unsynn::ToTokens::to_tokens(&self._eq, tokens);
957        unsynn::ToTokens::to_tokens(&self.value, tokens);
958        unsynn::ToTokens::to_tokens(&self._semi, tokens);
959    }
960}
961
962impl quote::ToTokens for StaticSig {
963    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
964        if let Some(attrs) = &self.attributes {
965            for attr in &attrs.0 {
966                unsynn::ToTokens::to_tokens(attr, tokens);
967            }
968        }
969        if let Some(vis) = &self.visibility {
970            quote::ToTokens::to_tokens(vis, tokens);
971        }
972        if let Some(mut_kw) = &self.mut_kw {
973            unsynn::ToTokens::to_tokens(mut_kw, tokens);
974        }
975        unsynn::ToTokens::to_tokens(&self._static, tokens);
976        quote::ToTokens::to_tokens(&self.name, tokens);
977        unsynn::ToTokens::to_tokens(&self._colon, tokens);
978        unsynn::ToTokens::to_tokens(&self.static_type, tokens);
979        unsynn::ToTokens::to_tokens(&self._eq, tokens);
980        unsynn::ToTokens::to_tokens(&self.value, tokens);
981        unsynn::ToTokens::to_tokens(&self._semi, tokens);
982    }
983}
984
985impl quote::ToTokens for EnumVariant {
986    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
987        if let Some(attrs) = &self.attributes {
988            for attr in &attrs.0 {
989                unsynn::ToTokens::to_tokens(attr, tokens);
990            }
991        }
992        quote::ToTokens::to_tokens(&self.name, tokens);
993        if let Some(data) = &self.data {
994            quote::ToTokens::to_tokens(data, tokens);
995        }
996    }
997}
998
999impl quote::ToTokens for EnumVariantData {
1000    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
1001        match self {
1002            EnumVariantData::Tuple(paren) => unsynn::ToTokens::to_tokens(paren, tokens),
1003            EnumVariantData::Struct(brace) => unsynn::ToTokens::to_tokens(brace, tokens),
1004            EnumVariantData::Discriminant(disc) => unsynn::ToTokens::to_tokens(disc, tokens),
1005        }
1006    }
1007}
1008
1009#[cfg(test)]
1010mod tests;