Skip to content

Commit 4ffd276

Browse files
authored
Allow raw identifier for field arguments in #[graphql_object] macro (#812, #786)
1 parent f3170c7 commit 4ffd276

File tree

3 files changed

+289
-3
lines changed

3 files changed

+289
-3
lines changed

integration_tests/juniper_tests/src/codegen/impl_object.rs

+43
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,46 @@ mod fallible {
9494
}
9595
}
9696
}
97+
98+
mod raw_argument {
99+
use juniper::{
100+
graphql_object, graphql_value, EmptyMutation, EmptySubscription, RootNode, Variables,
101+
};
102+
103+
struct Obj;
104+
105+
#[graphql_object]
106+
impl Obj {
107+
#[graphql(arguments(r#arg(description = "The only argument")))]
108+
fn test(&self, arg: String) -> String {
109+
arg
110+
}
111+
}
112+
113+
#[tokio::test]
114+
async fn named_correctly() {
115+
let doc = r#"{
116+
__type(name: "Obj") {
117+
fields {
118+
args {
119+
name
120+
}
121+
}
122+
}
123+
}"#;
124+
125+
let schema = RootNode::new(
126+
Obj,
127+
EmptyMutation::<()>::new(),
128+
EmptySubscription::<()>::new(),
129+
);
130+
131+
assert_eq!(
132+
juniper::execute(&doc, None, &schema, &Variables::new(), &()).await,
133+
Ok((
134+
graphql_value!({"__type": {"fields": [{"args": [{"name": "arg"}]}]}}),
135+
vec![],
136+
)),
137+
);
138+
}
139+
}

juniper/src/macros/tests/args.rs

+243-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ impl Root {
5858
arg
5959
}
6060

61+
#[graphql(arguments(r#arg(description = "The arg")))]
62+
fn single_arg_descr_raw_idents(arg: i32) -> i32 {
63+
arg
64+
}
65+
6166
#[graphql(arguments(
6267
arg1(description = "The first arg",),
6368
arg2(description = "The second arg")
@@ -66,9 +71,17 @@ impl Root {
6671
arg1 + arg2
6772
}
6873

74+
#[graphql(arguments(
75+
r#arg1(description = "The first arg",),
76+
r#arg2(description = "The second arg")
77+
))]
78+
fn multi_args_descr_raw_idents(arg1: i32, arg2: i32) -> i32 {
79+
arg1 + arg2
80+
}
81+
6982
#[graphql(arguments(
7083
arg1(description = "The first arg",),
71-
arg2(description = "The second arg")
84+
arg2(description = "The second arg",)
7285
))]
7386
fn multi_args_descr_trailing_comma(arg1: i32, arg2: i32) -> i32 {
7487
arg1 + arg2
@@ -106,6 +119,11 @@ impl Root {
106119
arg
107120
}
108121

122+
#[graphql(arguments(r#arg(default = 123, description = "The arg")))]
123+
fn arg_with_default_descr_raw_ident(arg: i32) -> i32 {
124+
arg
125+
}
126+
109127
#[graphql(arguments(
110128
arg1(default = 123, description = "The first arg"),
111129
arg2(default = 456, description = "The second arg")
@@ -114,6 +132,14 @@ impl Root {
114132
arg1 + arg2
115133
}
116134

135+
#[graphql(arguments(
136+
r#arg1(default = 123, description = "The first arg"),
137+
r#arg2(default = 456, description = "The second arg")
138+
))]
139+
fn multi_args_with_default_descr_raw_ident(arg1: i32, arg2: i32) -> i32 {
140+
arg1 + arg2
141+
}
142+
117143
#[graphql(arguments(
118144
arg1(default = 123, description = "The first arg",),
119145
arg2(default = 456, description = "The second arg",)
@@ -122,6 +148,14 @@ impl Root {
122148
arg1 + arg2
123149
}
124150

151+
#[graphql(arguments(
152+
r#arg1(default = 123, description = "The first arg",),
153+
r#arg2(default = 456, description = "The second arg",)
154+
))]
155+
fn multi_args_with_default_trailing_comma_descr_raw_ident(arg1: i32, arg2: i32) -> i32 {
156+
arg1 + arg2
157+
}
158+
125159
#[graphql(
126160
arguments(
127161
arg1(
@@ -460,6 +494,40 @@ async fn introspect_field_single_arg_descr() {
460494
.await;
461495
}
462496

497+
#[tokio::test]
498+
async fn introspect_field_single_arg_descr_raw_idents() {
499+
run_args_info_query("singleArgDescrRawIdents", |args| {
500+
assert_eq!(args.len(), 1);
501+
502+
assert!(args.contains(&Value::object(
503+
vec![
504+
("name", Value::scalar("arg")),
505+
("description", Value::scalar("The arg")),
506+
("defaultValue", Value::null()),
507+
(
508+
"type",
509+
Value::object(
510+
vec![
511+
("name", Value::null()),
512+
(
513+
"ofType",
514+
Value::object(
515+
vec![("name", Value::scalar("Int"))].into_iter().collect(),
516+
),
517+
),
518+
]
519+
.into_iter()
520+
.collect(),
521+
),
522+
),
523+
]
524+
.into_iter()
525+
.collect(),
526+
)));
527+
})
528+
.await;
529+
}
530+
463531
#[tokio::test]
464532
async fn introspect_field_multi_args_descr() {
465533
run_args_info_query("multiArgsDescr", |args| {
@@ -520,6 +588,66 @@ async fn introspect_field_multi_args_descr() {
520588
.await;
521589
}
522590

591+
#[tokio::test]
592+
async fn introspect_field_multi_args_descr_raw_idents() {
593+
run_args_info_query("multiArgsDescrRawIdents", |args| {
594+
assert_eq!(args.len(), 2);
595+
596+
assert!(args.contains(&Value::object(
597+
vec![
598+
("name", Value::scalar("arg1")),
599+
("description", Value::scalar("The first arg")),
600+
("defaultValue", Value::null()),
601+
(
602+
"type",
603+
Value::object(
604+
vec![
605+
("name", Value::null()),
606+
(
607+
"ofType",
608+
Value::object(
609+
vec![("name", Value::scalar("Int"))].into_iter().collect(),
610+
),
611+
),
612+
]
613+
.into_iter()
614+
.collect(),
615+
),
616+
),
617+
]
618+
.into_iter()
619+
.collect(),
620+
)));
621+
622+
assert!(args.contains(&Value::object(
623+
vec![
624+
("name", Value::scalar("arg2")),
625+
("description", Value::scalar("The second arg")),
626+
("defaultValue", Value::null()),
627+
(
628+
"type",
629+
Value::object(
630+
vec![
631+
("name", Value::null()),
632+
(
633+
"ofType",
634+
Value::object(
635+
vec![("name", Value::scalar("Int"))].into_iter().collect(),
636+
),
637+
),
638+
]
639+
.into_iter()
640+
.collect(),
641+
),
642+
),
643+
]
644+
.into_iter()
645+
.collect(),
646+
)));
647+
})
648+
.await;
649+
}
650+
523651
#[tokio::test]
524652
async fn introspect_field_multi_args_descr_trailing_comma() {
525653
run_args_info_query("multiArgsDescrTrailingComma", |args| {
@@ -786,6 +914,32 @@ async fn introspect_field_arg_with_default_descr() {
786914
.await;
787915
}
788916

917+
#[tokio::test]
918+
async fn introspect_field_arg_with_default_descr_raw_ident() {
919+
run_args_info_query("argWithDefaultDescrRawIdent", |args| {
920+
assert_eq!(args.len(), 1);
921+
922+
assert!(args.contains(&Value::object(
923+
vec![
924+
("name", Value::scalar("arg")),
925+
("description", Value::scalar("The arg")),
926+
("defaultValue", Value::scalar("123")),
927+
(
928+
"type",
929+
Value::object(
930+
vec![("name", Value::scalar("Int")), ("ofType", Value::null())]
931+
.into_iter()
932+
.collect(),
933+
),
934+
),
935+
]
936+
.into_iter()
937+
.collect(),
938+
)));
939+
})
940+
.await;
941+
}
942+
789943
#[tokio::test]
790944
async fn introspect_field_multi_args_with_default_descr() {
791945
run_args_info_query("multiArgsWithDefaultDescr", |args| {
@@ -830,6 +984,50 @@ async fn introspect_field_multi_args_with_default_descr() {
830984
.await;
831985
}
832986

987+
#[tokio::test]
988+
async fn introspect_field_multi_args_with_default_descr_raw_ident() {
989+
run_args_info_query("multiArgsWithDefaultDescrRawIdent", |args| {
990+
assert_eq!(args.len(), 2);
991+
992+
assert!(args.contains(&Value::object(
993+
vec![
994+
("name", Value::scalar("arg1")),
995+
("description", Value::scalar("The first arg")),
996+
("defaultValue", Value::scalar("123")),
997+
(
998+
"type",
999+
Value::object(
1000+
vec![("name", Value::scalar("Int")), ("ofType", Value::null())]
1001+
.into_iter()
1002+
.collect(),
1003+
),
1004+
),
1005+
]
1006+
.into_iter()
1007+
.collect(),
1008+
)));
1009+
1010+
assert!(args.contains(&Value::object(
1011+
vec![
1012+
("name", Value::scalar("arg2")),
1013+
("description", Value::scalar("The second arg")),
1014+
("defaultValue", Value::scalar("456")),
1015+
(
1016+
"type",
1017+
Value::object(
1018+
vec![("name", Value::scalar("Int")), ("ofType", Value::null())]
1019+
.into_iter()
1020+
.collect(),
1021+
),
1022+
),
1023+
]
1024+
.into_iter()
1025+
.collect(),
1026+
)));
1027+
})
1028+
.await;
1029+
}
1030+
8331031
#[tokio::test]
8341032
async fn introspect_field_multi_args_with_default_trailing_comma_descr() {
8351033
run_args_info_query("multiArgsWithDefaultTrailingCommaDescr", |args| {
@@ -874,6 +1072,50 @@ async fn introspect_field_multi_args_with_default_trailing_comma_descr() {
8741072
.await;
8751073
}
8761074

1075+
#[tokio::test]
1076+
async fn introspect_field_multi_args_with_default_trailing_comma_descr_raw_ident() {
1077+
run_args_info_query("multiArgsWithDefaultTrailingCommaDescrRawIdent", |args| {
1078+
assert_eq!(args.len(), 2);
1079+
1080+
assert!(args.contains(&Value::object(
1081+
vec![
1082+
("name", Value::scalar("arg1")),
1083+
("description", Value::scalar("The first arg")),
1084+
("defaultValue", Value::scalar("123")),
1085+
(
1086+
"type",
1087+
Value::object(
1088+
vec![("name", Value::scalar("Int")), ("ofType", Value::null())]
1089+
.into_iter()
1090+
.collect(),
1091+
),
1092+
),
1093+
]
1094+
.into_iter()
1095+
.collect(),
1096+
)));
1097+
1098+
assert!(args.contains(&Value::object(
1099+
vec![
1100+
("name", Value::scalar("arg2")),
1101+
("description", Value::scalar("The second arg")),
1102+
("defaultValue", Value::scalar("456")),
1103+
(
1104+
"type",
1105+
Value::object(
1106+
vec![("name", Value::scalar("Int")), ("ofType", Value::null())]
1107+
.into_iter()
1108+
.collect(),
1109+
),
1110+
),
1111+
]
1112+
.into_iter()
1113+
.collect(),
1114+
)));
1115+
})
1116+
.await;
1117+
}
1118+
8771119
#[tokio::test]
8781120
async fn introspect_field_args_with_complex_default() {
8791121
run_args_info_query("argsWithComplexDefault", |args| {

juniper_codegen/src/util/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ use proc_macro_error::abort;
1111
use quote::quote;
1212
use span_container::SpanContainer;
1313
use syn::{
14+
ext::IdentExt as _,
1415
parse::{Parse, ParseStream},
1516
parse_quote,
1617
punctuated::Punctuated,
1718
spanned::Spanned,
18-
token, Attribute, Lit, Meta, MetaList, MetaNameValue, NestedMeta,
19+
token, Attribute, Ident, Lit, Meta, MetaList, MetaNameValue, NestedMeta,
1920
};
2021

2122
use crate::common::parse::ParseBufferExt as _;
@@ -450,7 +451,7 @@ pub struct FieldAttributeArgument {
450451

451452
impl Parse for FieldAttributeArgument {
452453
fn parse(input: ParseStream) -> syn::Result<Self> {
453-
let name = input.parse()?;
454+
let name = input.parse::<Ident>()?.unraw();
454455

455456
let mut arg = Self {
456457
name,

0 commit comments

Comments
 (0)