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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use proc_macro2::TokenStream;
use super::ArgumentParameter;
use crate::{schema::InputValue, FieldArgument, FieldType, Ident, TypeIndex, TypePath};
#[derive(Debug)]
pub struct FieldSelector {
pub rust_field_name: Ident,
pub query_field_name: String,
pub field_type: FieldType,
pub type_lock: Ident,
pub argument_structs_path: Ident,
pub required_args: Vec<FieldArgument>,
pub selection_builder: TypePath,
}
impl FieldSelector {
pub fn for_field(
name: &str,
field_type: FieldType,
type_lock: Ident,
argument_structs_path: Ident,
required_args: Vec<InputValue>,
selection_builder: TypePath,
type_index: &TypeIndex,
) -> FieldSelector {
FieldSelector {
rust_field_name: Ident::for_field(name),
query_field_name: name.to_string(),
field_type,
type_lock,
argument_structs_path,
required_args: required_args
.iter()
.map(|v| FieldArgument::from_input_value(v, type_index))
.collect(),
selection_builder,
}
}
}
impl quote::ToTokens for FieldSelector {
fn to_tokens(&self, tokens: &mut TokenStream) {
use quote::{quote, TokenStreamExt};
let rust_field_name = &self.rust_field_name;
let mut argument_defs = Vec::with_capacity(self.required_args.len());
for arg in &self.required_args {
argument_defs.push(
ArgumentParameter::new(arg.name.clone(), arg.argument_type.clone())
.to_tokens(TypePath::empty())
.unwrap(),
);
}
let argument_vals: Vec<_> = self
.required_args
.iter()
.map(|a| {
let name = &a.name;
quote! { ::cynic::serde_json::to_value(&#name) }
})
.collect();
let argument_strings: Vec<_> = self
.required_args
.iter()
.map(|a| proc_macro2::Literal::string(&a.gql_name.to_string()))
.collect();
let argument_gql_types: Vec<_> = self
.required_args
.iter()
.map(|a| a.gql_type.clone())
.collect();
let selection_builder = &self.selection_builder;
tokens.append_all(quote! {
pub fn #rust_field_name(
#(#argument_defs, )*
) -> #selection_builder {
#selection_builder::new(vec![
#(
::cynic::Argument::new(
#argument_strings,
#argument_gql_types,
#argument_vals
),
)*
])
}
})
}
}