@@ -3,7 +3,7 @@ use proc_macro::TokenStream;
3
3
use quote:: quote;
4
4
5
5
/// Generate code for the juniper::impl_object macro.
6
- pub fn build_impl_object ( args : TokenStream , body : TokenStream ) -> TokenStream {
6
+ pub fn build_impl_object ( args : TokenStream , body : TokenStream , is_internal : bool ) -> TokenStream {
7
7
let impl_attrs = match syn:: parse :: < util:: ObjectAttributes > ( args) {
8
8
Ok ( attrs) => attrs,
9
9
Err ( e) => {
@@ -27,29 +27,44 @@ pub fn build_impl_object(args: TokenStream, body: TokenStream) -> TokenStream {
27
27
. map ( |segment| segment. ident . to_string ( ) )
28
28
. collect :: < Vec < _ > > ( )
29
29
. join ( "." ) ;
30
- if ! ( name == "GraphQLObject" || name == "juniper.GraphQLObject" ) {
30
+ if !( name == "GraphQLObject" || name == "juniper.GraphQLObject" ) {
31
31
panic ! ( "The impl block must implement the 'GraphQLObject' trait" ) ;
32
32
}
33
33
}
34
34
None => {
35
- panic ! ( "The impl block must implement the 'GraphQLObject' trait" ) ;
35
+ // panic!("The impl block must implement the 'GraphQLObject' trait");
36
36
}
37
37
}
38
38
39
- let type_name = match & * _impl. self_ty {
40
- syn:: Type :: Path ( ref type_path) => type_path
41
- . path
42
- . segments
43
- . iter ( )
44
- . last ( )
45
- . unwrap ( )
46
- . ident
47
- . to_string ( ) ,
48
- _ => {
49
- panic ! ( "Invalid impl target: expected a path" ) ;
50
- }
39
+ let name = match impl_attrs. name . as_ref ( ) {
40
+ Some ( type_name) => type_name. clone ( ) ,
41
+ None => match & * _impl. self_ty {
42
+ syn:: Type :: Path ( ref type_path) => type_path
43
+ . path
44
+ . segments
45
+ . iter ( )
46
+ . last ( )
47
+ . unwrap ( )
48
+ . ident
49
+ . to_string ( ) ,
50
+ syn:: Type :: Reference ( ref reference) => match & * reference. elem {
51
+ syn:: Type :: Path ( ref type_path) => type_path
52
+ . path
53
+ . segments
54
+ . iter ( )
55
+ . last ( )
56
+ . unwrap ( )
57
+ . ident
58
+ . to_string ( ) ,
59
+ _ => {
60
+ panic ! ( "Could not determine a name for the object type: specify one with #[juniper::impl_object(name = \" SomeName\" )" ) ;
61
+ }
62
+ } ,
63
+ _ => {
64
+ panic ! ( "Could not determine a name for the object type: specify one with #[juniper::impl_object(name = \" SomeName\" )" ) ;
65
+ }
66
+ } ,
51
67
} ;
52
- let name = impl_attrs. name . unwrap_or ( type_name) ;
53
68
54
69
let target_type = * _impl. self_ty . clone ( ) ;
55
70
@@ -65,15 +80,15 @@ pub fn build_impl_object(args: TokenStream, body: TokenStream) -> TokenStream {
65
80
66
81
for item in & mut _impl. items {
67
82
match item {
68
- syn:: ImplItem :: Type ( _ty) => {
69
- if _ty. ident == "Context" {
70
- definition. context = Some ( _ty. ty . clone ( ) ) ;
71
- } else if _ty. ident == "Scalar" {
72
- definition. scalar = Some ( _ty. ty . clone ( ) ) ;
73
- } else {
74
- panic ! ( "Invalid 'type {} = _' specification. only 'Context' and 'Scalar' are allowed." ) ;
75
- }
76
- }
83
+ // syn::ImplItem::Type(_ty) => {
84
+ // if _ty.ident == "Context" {
85
+ // definition.context = Some(_ty.ty.clone());
86
+ // } else if _ty.ident == "Scalar" {
87
+ // definition.scalar = Some(_ty.ty.clone());
88
+ // } else {
89
+ // panic!("Invalid 'type {} = _' specification. only 'Context' and 'Scalar' are allowed.");
90
+ // }
91
+ // }
77
92
syn:: ImplItem :: Method ( method) => {
78
93
let _type = match & method. sig . decl . output {
79
94
syn:: ReturnType :: Type ( _, ref t) => ( * * t) . clone ( ) ,
@@ -87,49 +102,52 @@ pub fn build_impl_object(args: TokenStream, body: TokenStream) -> TokenStream {
87
102
88
103
let attrs = util:: FieldAttributes :: from_attrs ( & method. attrs ) ;
89
104
// Remove graphql attribute from final output.
90
- method
91
- . attrs
92
- . retain ( |item| util:: path_eq_single ( & item. path , "graphql" ) == false ) ;
105
+ // method
106
+ // .attrs
107
+ // .retain(|item| util::path_eq_single(&item.path, "graphql") == false);
93
108
94
109
let mut args = Vec :: new ( ) ;
95
- let mut resolve_args = Vec :: new ( ) ;
110
+ let mut resolve_parts = Vec :: new ( ) ;
96
111
97
- for arg in & method. sig . decl . inputs {
112
+ for arg in & mut method. sig . decl . inputs {
98
113
match arg {
99
- syn:: FnArg :: SelfRef ( _) => {
114
+ _self @ syn:: FnArg :: SelfRef ( _) => {
100
115
// Can be ignored.
101
- resolve_args. push ( quote ! ( self ) ) ;
116
+ // "self" will already be in scope.
117
+ // resolve_args.push(quote!(self));
102
118
}
103
119
syn:: FnArg :: SelfValue ( _) => {
104
120
panic ! (
105
- "Invalid method receiver in {}: self is not allowed, did you mean '&self'?" ,
121
+ "Invalid method receiver {}( self, ...): did you mean '&self'?" ,
106
122
method. sig. ident
107
123
) ;
108
124
}
109
125
syn:: FnArg :: Captured ( ref captured) => {
110
- let arg_name = match & captured. pat {
111
- syn:: Pat :: Ident ( ref pat_ident) => pat_ident. ident . to_string ( ) ,
126
+ let arg_ident = match & captured. pat {
127
+ syn:: Pat :: Ident ( ref pat_ident) => & pat_ident. ident ,
112
128
_ => {
113
129
panic ! ( "Invalid token for function argument" ) ;
114
130
}
115
131
} ;
132
+ let arg_name = arg_ident. to_string ( ) ;
116
133
117
134
// Check if the argument refers to the Executor or the context.
118
135
if util:: type_is_identifier_ref ( & captured. ty , "Executor" ) {
119
- resolve_args . push ( quote ! ( executor) ) ;
136
+ resolve_parts . push ( quote ! ( let #arg_ident = executor; ) ) ;
120
137
} else if definition
121
138
. context
122
139
. as_ref ( )
123
140
. map ( |ctx| util:: type_is_ref_of ( & captured. ty , ctx) )
124
141
. unwrap_or ( false )
125
142
{
126
- resolve_args . push ( quote ! ( executor. context( ) ) ) ;
143
+ resolve_parts . push ( quote ! ( let #arg_ident = executor. context( ) ; ) ) ;
127
144
} else {
145
+ let arg_ident = & captured. pat ;
128
146
let ty = & captured. ty ;
129
- resolve_args . push ( quote ! (
130
- args
147
+ resolve_parts . push ( quote ! (
148
+ let #arg_ident = args
131
149
. get:: <#ty>( #arg_name)
132
- . expect( "Argument missing - validation must have failed" )
150
+ . expect( "Argument missing - validation must have failed" ) ;
133
151
) ) ;
134
152
args. push ( util:: GraphQLTypeDefinitionFieldArg {
135
153
name : arg_name,
@@ -142,14 +160,15 @@ pub fn build_impl_object(args: TokenStream, body: TokenStream) -> TokenStream {
142
160
}
143
161
}
144
162
145
- let method_ident = & method. sig . ident ;
163
+ let body = & method. block ;
146
164
let resolver_code = quote ! (
147
- #target_type :: #method_ident ( #( #resolve_args ) , * )
165
+ #( #resolve_parts ) *
166
+ #body
148
167
) ;
149
168
150
169
let name = attrs
151
170
. name
152
- . unwrap_or ( util:: to_camel_case ( & method_ident . to_string ( ) ) ) ;
171
+ . unwrap_or ( util:: to_camel_case ( & method . sig . ident . to_string ( ) ) ) ;
153
172
154
173
definition. fields . push ( util:: GraphQLTypeDefinitionField {
155
174
name,
@@ -165,11 +184,6 @@ pub fn build_impl_object(args: TokenStream, body: TokenStream) -> TokenStream {
165
184
}
166
185
}
167
186
}
168
-
169
- let graphql_type_impl = definition. into_tokens ( ) ;
170
- let body = quote ! (
171
- #_impl
172
- #graphql_type_impl
173
- ) ;
174
- body. into ( )
187
+ let juniper_crate_name = if is_internal { "crate" } else { "juniper" } ;
188
+ definition. into_tokens ( juniper_crate_name) . into ( )
175
189
}
0 commit comments