1use proc_macro::TokenStream;
2use syn::{DeriveInput, Generics, Result, parse_quote};
3
4mod attributes;
5mod css_feature;
6mod darling_ext;
7mod declaration_metadata;
8mod feature_metadata;
9mod field_view;
10mod into_cursor;
11mod node_with_metadata;
12mod parse;
13mod peek;
14mod semantic_eq;
15mod to_cursors;
16mod to_span;
17mod visitable;
18mod visitor;
19mod where_collector;
20
21use field_view::FieldsExt;
22use where_collector::WhereCollector;
23
24fn ensure_lifetime_a(generics: &Generics) -> Generics {
25 let mut g = generics.clone();
26 if generics.lifetimes().all(|l| l.lifetime.ident != "a") {
27 g.params.insert(0, parse_quote!('a));
28 }
29 g
30}
31
32#[cfg(test)]
33mod test;
34
35fn run<F>(stream: TokenStream, f: F) -> TokenStream
36where
37 F: FnOnce(DeriveInput) -> Result<proc_macro2::TokenStream>,
38{
39 let input = syn::parse::<DeriveInput>(stream).unwrap_or_else(|e| panic!("{e}"));
40 f(input).unwrap_or_else(|e| e.into_compile_error()).into()
41}
42
43#[proc_macro_derive(ToCursors, attributes(to_cursors))]
44pub fn derive_to_cursors(stream: TokenStream) -> TokenStream {
45 run(stream, to_cursors::derive)
46}
47
48#[proc_macro_derive(Parse, attributes(parse, atom))]
49pub fn derive_parse(stream: TokenStream) -> TokenStream {
50 run(stream, parse::derive)
51}
52
53#[proc_macro_derive(Peek, attributes(peek, atom))]
54pub fn derive_peek(stream: TokenStream) -> TokenStream {
55 run(stream, peek::derive)
56}
57
58#[proc_macro_derive(IntoCursor)]
59pub fn derive_into_cursor(stream: TokenStream) -> TokenStream {
60 run(stream, into_cursor::derive)
61}
62
63#[proc_macro_derive(ToSpan)]
64pub fn derive_into_span(stream: TokenStream) -> TokenStream {
65 run(stream, to_span::derive)
66}
67
68#[proc_macro_derive(Visitable, attributes(visit, queryable))]
69pub fn derive_visitable(stream: TokenStream) -> TokenStream {
70 run(stream, visitable::derive)
71}
72
73#[proc_macro_derive(FeatureMetadata, attributes(feature_metadata))]
74pub fn derive_feature_metadata(stream: TokenStream) -> TokenStream {
75 run(stream, feature_metadata::derive)
76}
77
78#[proc_macro_derive(NodeWithMetadata, attributes(metadata))]
79pub fn derive_node_with_metadata(stream: TokenStream) -> TokenStream {
80 run(stream, node_with_metadata::derive)
81}
82
83#[proc_macro_derive(ToCSSFeature, attributes(css_feature))]
84pub fn derive_css_feature(stream: TokenStream) -> TokenStream {
85 run(stream, css_feature::derive)
86}
87
88#[proc_macro_derive(DeclarationMetadata, attributes(declaration_metadata))]
89pub fn derive_declaration_metadata(stream: TokenStream) -> TokenStream {
90 run(stream, declaration_metadata::derive)
91}
92
93#[proc_macro_derive(SemanticEq, attributes(semantic_eq))]
94pub fn derive_semantic_eq(stream: TokenStream) -> TokenStream {
95 run(stream, semantic_eq::derive)
96}
97
98#[proc_macro_attribute]
99pub fn visitor(_attr: TokenStream, item: TokenStream) -> TokenStream {
100 let item = syn::parse_macro_input!(item as syn::ItemImpl);
101 visitor::expand(item).unwrap_or_else(|e| e.into_compile_error()).into()
102}