1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use)]
#![cfg_attr(clippy, deny(warnings))]
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::parse::{self, Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{GenericParam, Ident, LitStr, Token, TypeParam};
mod config_deserialize;
mod serde_replace;
/// Error message when attempting to flatten multiple fields.
pub(crate) const MULTIPLE_FLATTEN_ERROR: &str =
"At most one instance of #[config(flatten)] is supported";
#[proc_macro_derive(ConfigDeserialize, attributes(config))]
pub fn derive_config_deserialize(input: TokenStream) -> TokenStream {
config_deserialize::derive(input)
}
#[proc_macro_derive(SerdeReplace)]
pub fn derive_serde_replace(input: TokenStream) -> TokenStream {
serde_replace::derive(input)
}
/// Storage for all necessary generics information.
#[derive(Default)]
struct GenericsStreams {
unconstrained: TokenStream2,
constrained: TokenStream2,
phantoms: TokenStream2,
}
/// Create the necessary generics annotations.
///
/// This will create three different token streams, which might look like this:
/// - unconstrained: `T`
/// - constrained: `T: Default + Deserialize<'de>`
/// - phantoms: `T: PhantomData<T>,`
pub(crate) fn generics_streams<T>(params: &Punctuated<GenericParam, T>) -> GenericsStreams {
let mut generics = GenericsStreams::default();
for generic in params {
// NOTE: Lifetimes and const params are not supported.
if let GenericParam::Type(TypeParam { ident, .. }) = generic {
generics.unconstrained.extend(quote!( #ident , ));
generics.constrained.extend(quote! {
#ident : Default + serde::Deserialize<'de> + alacritty_config::SerdeReplace,
});
generics.phantoms.extend(quote! {
#ident : std::marker::PhantomData < #ident >,
});
}
}
generics
}
/// Field attribute.
pub(crate) struct Attr {
ident: String,
param: Option<LitStr>,
}
impl Parse for Attr {
fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
let ident = input.parse::<Ident>()?.to_string();
let param = input.parse::<Token![=]>().and_then(|_| input.parse()).ok();
Ok(Self { ident, param })
}
}
|