Skip to content

Commit 60735f8

Browse files
committed
Remove use of juniper::graphql_object!
Fixes #55 This isn't complete yet. This patch currently removes support for having descriptions on field arguments. That is because getting those to work [requires funky stuff][funky] in the juniper proc macro invocation. While it could totally be made to work I would rather wait since it requires a bit of refactoring and since it should work seamlessly once [RFC 2564](rust-lang/rust#60406) is stable, which seems to happen in 1.39. [funky]: https://docs.rs/juniper_codegen/0.13.2/juniper_codegen/attr.object.html#customization-documentation-renaming-
1 parent 7a0fc43 commit 60735f8

File tree

3 files changed

+102
-25
lines changed

3 files changed

+102
-25
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ N/A
2525
### Fixed
2626

2727
- Fix support for special case [`Uuid`](https://crates.io/crates/uuid) and [`Url`](https://crates.io/crates/url) scalars. [#69](https://github.com/davidpdrsn/juniper-from-schema/pull/69)
28+
- Replace use deprecated `juniper::graphql_object` macro with `juniper::object` proc macro.
2829

2930
## [0.3.0] - 2019-06-18
3031

juniper-from-schema-code-gen/src/ast_pass/code_gen_pass.rs

+75-25
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl<'doc> SchemaVisitor<'doc> for CodeGenPass<'doc> {
9696
let field_tokens = obj_type
9797
.fields
9898
.iter()
99-
.map(|field| self.collect_data_for_field_gen(field))
99+
.map(|field| self.collect_data_for_field_gen(field, QuoteFor::ProcMacro))
100100
.collect::<Vec<_>>();
101101

102102
let trait_methods = field_tokens
@@ -154,7 +154,7 @@ impl<'doc> SchemaVisitor<'doc> for CodeGenPass<'doc> {
154154
let description = obj_type
155155
.description
156156
.as_ref()
157-
.map(|d| quote! { description: #d })
157+
.map(|d| quote! { description = #d, })
158158
.unwrap_or_else(empty_token_stream);
159159

160160
let interfaces = if obj_type.implements_interfaces.is_empty() {
@@ -164,17 +164,23 @@ impl<'doc> SchemaVisitor<'doc> for CodeGenPass<'doc> {
164164
let name = ident(name);
165165
quote! { &#name }
166166
});
167-
quote! { interfaces: [#(#interface_names),*] }
167+
quote! { interfaces = [#(#interface_names),*], }
168168
};
169169

170170
let context_type = &self.context_type;
171171

172+
let macro_args = vec![
173+
quote! { Context = #context_type, },
174+
description,
175+
quote! { scalar = juniper::DefaultScalarValue, },
176+
interfaces,
177+
];
178+
172179
let code = quote! {
173-
juniper::graphql_object!(#struct_name: #context_type |&self| {
174-
#description
180+
#[juniper::object( #(#macro_args)* )]
181+
impl #struct_name {
175182
#(#fields)*
176-
#interfaces
177-
});
183+
}
178184
};
179185
self.extend(code)
180186
}
@@ -231,7 +237,7 @@ impl<'doc> SchemaVisitor<'doc> for CodeGenPass<'doc> {
231237
let field_tokens: Vec<FieldTokens> = interface
232238
.fields
233239
.iter()
234-
.map(|field| self.collect_data_for_field_gen(field))
240+
.map(|field| self.collect_data_for_field_gen(field, QuoteFor::Macro))
235241
.collect::<Vec<_>>();
236242

237243
let field_token_streams = field_tokens
@@ -256,7 +262,7 @@ impl<'doc> SchemaVisitor<'doc> for CodeGenPass<'doc> {
256262
}
257263
});
258264

259-
let all_args = to_field_args_list(&args);
265+
let all_args = to_field_args_list(&args, QuoteFor::Macro);
260266

261267
let error_type = &self.error_type;
262268

@@ -680,10 +686,14 @@ impl<'doc> CodeGenPass<'doc> {
680686
}
681687
}
682688

683-
fn collect_data_for_field_gen(&mut self, field: &'doc Field) -> FieldTokens<'doc> {
689+
fn collect_data_for_field_gen(
690+
&mut self,
691+
field: &'doc Field,
692+
quote_for: QuoteFor,
693+
) -> FieldTokens<'doc> {
684694
self.error_if_has_unsupported_directive(&field);
685695

686-
let deprecation = self.quote_deprecations(&field.directives);
696+
let deprecation = self.quote_deprecations(&field.directives, quote_for);
687697

688698
let name = ident(&field.name);
689699

@@ -711,6 +721,16 @@ impl<'doc> CodeGenPass<'doc> {
711721
.map(|arg| {
712722
let name = ident(&arg.name);
713723
let arg_type = &arg.macro_type;
724+
725+
if arg.description.is_some() && quote_for == QuoteFor::ProcMacro {
726+
// TODO: support descriptions field arguments.
727+
// That is currently annoying in juniper when using the `#[object]` proc macro
728+
// https://docs.rs/juniper_codegen/0.13.2/juniper_codegen/attr.object.html#customization-documentation-renaming-
729+
return quote! {
730+
#name: #arg_type
731+
};
732+
}
733+
714734
let description = doc_tokens(&arg.description);
715735
quote! {
716736
#description
@@ -772,7 +792,7 @@ impl<'doc> CodeGenPass<'doc> {
772792
let name = to_enum_name(&graphql_name);
773793
let description = doc_tokens(&enum_value.description);
774794

775-
let deprecation = self.quote_deprecations(&enum_value.directives);
795+
let deprecation = self.quote_deprecations(&enum_value.directives, QuoteFor::Macro);
776796

777797
quote! {
778798
#[allow(missing_docs)]
@@ -783,7 +803,7 @@ impl<'doc> CodeGenPass<'doc> {
783803
}
784804
}
785805

786-
fn quote_deprecations(&mut self, directives: &[Directive]) -> TokenStream {
806+
fn quote_deprecations(&mut self, directives: &[Directive], quote_for: QuoteFor) -> TokenStream {
787807
for directive in directives {
788808
if directive.name == "deprecated" {
789809
let mut arguments = BTreeMap::new();
@@ -800,18 +820,27 @@ impl<'doc> CodeGenPass<'doc> {
800820

801821
if let Some(value) = arguments.get(&"reason".to_string()) {
802822
let tokens = match value {
803-
Value::String(reason) => quote! { #[deprecated(note = #reason)] },
823+
Value::String(reason) => match quote_for {
824+
QuoteFor::Macro => quote! { #[deprecated(note = #reason)] },
825+
QuoteFor::ProcMacro => quote! { deprecated = #reason, },
826+
},
804827
_ => {
805828
self.emit_non_fatal_error(
806829
directive.position,
807830
ErrorKind::InvalidArgumentsToDeprecateDirective,
808831
);
809-
quote! { #[deprecated] }
832+
match quote_for {
833+
QuoteFor::Macro => quote! { #[deprecated] },
834+
QuoteFor::ProcMacro => quote! { deprecated, },
835+
}
810836
}
811837
};
812838
return tokens;
813839
} else {
814-
return quote! { #[deprecated] };
840+
return match quote_for {
841+
QuoteFor::Macro => quote! { #[deprecated] },
842+
QuoteFor::ProcMacro => quote! { deprecated, },
843+
};
815844
}
816845
}
817846
}
@@ -1059,14 +1088,18 @@ fn gen_field(
10591088
.map(ToString::to_string)
10601089
.unwrap_or_else(String::new);
10611090

1062-
let all_args = to_field_args_list(args);
1091+
let all_args = to_field_args_list(args, QuoteFor::ProcMacro);
10631092

10641093
let deprecation = &field.deprecation;
10651094

1095+
let macro_args = vec![
1096+
quote! { description = #description },
1097+
quote! { #deprecation },
1098+
];
1099+
10661100
quote! {
1067-
#[doc = #description]
1068-
#deprecation
1069-
field #field_name(#all_args) -> std::result::Result<#field_type, #error_type> {
1101+
#[graphql( #(#macro_args),* )]
1102+
fn #field_name(#all_args) -> std::result::Result<#field_type, #error_type> {
10701103
#body
10711104
}
10721105
}
@@ -1098,11 +1131,28 @@ fn gen_field_body(
10981131
}
10991132
}
11001133

1101-
fn to_field_args_list(args: &[TokenStream]) -> TokenStream {
1102-
if args.is_empty() {
1103-
quote! { &executor }
1104-
} else {
1105-
quote! { &executor, #(#args),* }
1134+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1135+
enum QuoteFor {
1136+
Macro,
1137+
ProcMacro,
1138+
}
1139+
1140+
fn to_field_args_list(args: &[TokenStream], quote_for: QuoteFor) -> TokenStream {
1141+
match quote_for {
1142+
QuoteFor::ProcMacro => {
1143+
if args.is_empty() {
1144+
quote! { &self, executor: &Executor }
1145+
} else {
1146+
quote! { &self, executor: &Executor, #(#args),* }
1147+
}
1148+
}
1149+
QuoteFor::Macro => {
1150+
if args.is_empty() {
1151+
quote! { &executor }
1152+
} else {
1153+
quote! { &executor, #(#args),* }
1154+
}
1155+
}
11061156
}
11071157
}
11081158

juniper-from-schema/tests/foo.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#![allow(dead_code, unused_variables, unused_must_use, unused_imports)]
2+
use juniper::{EmptyMutation, Executor, FieldResult, Variables};
3+
use juniper_from_schema::{graphql_schema, graphql_schema_from_file};
4+
5+
pub struct Context;
6+
impl juniper::Context for Context {}
7+
8+
fn main() {}
9+
10+
graphql_schema! {
11+
schema {
12+
query: Query
13+
}
14+
15+
type Query {
16+
url: String! @juniper(ownership: "owned")
17+
}
18+
}
19+
20+
pub struct Query;
21+
22+
impl QueryFields for Query {
23+
fn field_url(&self, _: &Executor<'_, Context>) -> FieldResult<String> {
24+
Ok("".to_string())
25+
}
26+
}

0 commit comments

Comments
 (0)