1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::DeriveInput;
4use syn::parse_quote;
5
6use crate::util::wrap_in_dummy_mod;
7
8pub fn derive(mut item: DeriveInput) -> TokenStream {
9 for ty_param in item.generics.type_params_mut() {
10 ty_param
11 .bounds
12 .push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "QueryId");
_s
})parse_quote!(diesel::query_builder::QueryId));
13 }
14 let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
15 let is_window_function = item.attrs.iter().any(|a| {
16 if a.path().is_ident("diesel") {
17 match a.parse_args_with(
18 syn::punctuated::Punctuated::<syn::Meta, ::syn::token::Commasyn::Token![,]>::parse_terminated,
19 ) {
20 Ok(nested) => nested.iter().any(|n| match n {
21 syn::Meta::NameValue(n) => {
22 n.path.is_ident("diesel_internal_is_window")
23 && #[allow(non_exhaustive_omitted_patterns)] match n.value {
syn::Expr::Lit(syn::ExprLit {
lit: syn::Lit::Bool(syn::LitBool { value: true, .. }), .. }) => true,
_ => false,
}matches!(
24 n.value,
25 syn::Expr::Lit(syn::ExprLit {
26 lit: syn::Lit::Bool(syn::LitBool { value: true, .. }),
27 ..
28 })
29 )
30 }
31 _ => false,
32 }),
33 _ => false,
34 }
35 } else {
36 false
37 }
38 });
39
40 let struct_name = &item.ident;
41 let lifetimes = item.generics.lifetimes();
42
43 let ty_params = item
44 .generics
45 .type_params()
46 .map(|ty_param| &ty_param.ident)
47 .collect::<Vec<_>>();
48
49 let consts = item
50 .generics
51 .const_params()
52 .map(|const_param| &const_param.ident)
53 .collect::<Vec<_>>();
54
55 let query_id_ty_params = ty_params
56 .iter()
57 .map(|ty_param| {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&ty_param, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "QueryId");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "QueryId");
_s
}quote!(<#ty_param as diesel::query_builder::QueryId>::QueryId));
58 let has_static_query_id = ty_params
59 .iter()
60 .map(|ty_param| {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&ty_param, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "QueryId");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "HAS_STATIC_QUERY_ID");
_s
}quote!(<#ty_param as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID));
61 let is_window_function_list = ty_params
62 .iter()
63 .map(|ty_param| {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&ty_param, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "QueryId");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "IS_WINDOW_FUNCTION");
_s
}quote!(<#ty_param as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION));
64 let is_window_function = if is_window_function {
65 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "true");
_s
}quote! { true }
66 } else {
67 {
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut is_window_function_list, i) =
is_window_function_list.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let is_window_function_list =
match is_window_function_list.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&is_window_function_list, &mut _s);
::quote::__private::push_or_or(&mut _s);
}
}
::quote::__private::push_ident(&mut _s, "false");
_s
}quote! { #(#is_window_function_list ||)* false }
68 };
69
70 wrap_in_dummy_mod({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"non_camel_case_types");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "QueryId");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&struct_name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "type");
::quote::__private::push_ident(&mut _s, "QueryId");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&struct_name, &mut _s);
::quote::__private::push_lt(&mut _s);
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut lifetimes, i) = lifetimes.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let lifetimes =
match lifetimes.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&lifetimes, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut query_id_ty_params, i) =
query_id_ty_params.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let query_id_ty_params =
match query_id_ty_params.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&query_id_ty_params, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut consts, i) = consts.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let consts =
match consts.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&consts, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_gt(&mut _s);
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "HAS_STATIC_QUERY_ID");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "bool");
::quote::__private::push_eq(&mut _s);
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut has_static_query_id, i) =
has_static_query_id.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let has_static_query_id =
match has_static_query_id.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&has_static_query_id, &mut _s);
::quote::__private::push_and_and(&mut _s);
}
}
::quote::__private::push_ident(&mut _s, "true");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "const");
::quote::__private::push_ident(&mut _s, "IS_WINDOW_FUNCTION");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "bool");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&is_window_function, &mut _s);
::quote::__private::push_semi(&mut _s);
_s
});
_s
}quote! {
71 #[allow(non_camel_case_types)]
72 impl #impl_generics diesel::query_builder::QueryId for #struct_name #ty_generics
73 #where_clause
74 {
75 type QueryId = #struct_name<#(#lifetimes,)* #(#query_id_ty_params,)* #(#consts,)*>;
76
77 const HAS_STATIC_QUERY_ID: bool = #(#has_static_query_id &&)* true;
78
79 const IS_WINDOW_FUNCTION: bool = #is_window_function;
80 }
81 })
82}