Skip to content

Make proc macro support parameter attributes #441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 13 commits into from
20 changes: 5 additions & 15 deletions docs/book/content/types/objects/complex_fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,21 +127,11 @@ struct Person {}

#[juniper::object]
impl Person {
#[graphql(
arguments(
arg1(
// Set a default value which will be injected if not present.
// The default can be any valid Rust expression, including a function call, etc.
default = true,
// Set a description.
description = "The first argument..."
),
arg2(
default = 0,
)
)
)]
fn field1(&self, arg1: bool, arg2: i32) -> String {
fn field1(
&self,
#[graphql(default = true, description = "The first argument...")] arg1: bool,
#[graphql(default = 0)] arg2: i32,
) -> String {
format!("{} {}", arg1, arg2)
}
}
Expand Down
28 changes: 28 additions & 0 deletions juniper/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
# master

### New way to customize arguments

See [#441](https://github.com/graphql-rust/juniper/pull/441).

You can now customize arguments by annotating them with `#[graphql(...)]` directly. Example:

```rust
#[juniper::object]
impl Query {
fn some_field_with_a_description(
#[graphql(
name = newNameForArg,
description = "My argument description",
default = false,
)]
arg: bool
) -> bool {
// ...
}
}
```

The old style `#[graphql(arguments(...))]` is no longer supported.

Note that this requires Rust 1.39.

### Other changes

- Correctly handle raw identifiers in field and argument names.

# [[0.14.1] 2019-10-24](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.14.1)
Expand Down
1 change: 1 addition & 0 deletions juniper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ uuid = { version = "0.7", optional = true }
[dev-dependencies]
bencher = "0.1.2"
serde_json = { version = "1.0.2" }
assert-json-diff = "1.0.1"
10 changes: 4 additions & 6 deletions juniper/src/executor_tests/introspection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,11 @@ impl Root {
Sample::One
}

#[graphql(arguments(
first(description = "The first number",),
second(description = "The second number", default = 123,),
))]

/// A sample scalar field on the object
fn sample_scalar(first: i32, second: i32) -> Scalar {
fn sample_scalar(
#[graphql(description = "The first number")] first: i32,
#[graphql(description = "The second number", default = 123)] second: i32,
) -> Scalar {
Scalar(first + second)
}
}
Expand Down
109 changes: 65 additions & 44 deletions juniper/src/executor_tests/variables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,9 @@ impl TestType {
format!("{:?}", input)
}

#[graphql(
arguments(
input(
default = "Hello World".to_string(),
)
)
)]
fn field_with_default_argument_value(input: String) -> String {
fn field_with_default_argument_value(
#[graphql(default = "Hello World".to_string())] input: String,
) -> String {
format!("{:?}", input)
}

Expand Down Expand Up @@ -158,7 +153,10 @@ fn inline_complex_input() {
|result: &Object<DefaultScalarValue>| {
assert_eq!(
result.get_field_value("fieldWithObjectInput"),
Some(&Value::scalar(r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#)));
Some(&Value::scalar(
r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#
))
);
},
);
}
Expand All @@ -170,7 +168,10 @@ fn inline_parse_single_value_to_list() {
|result: &Object<DefaultScalarValue>| {
assert_eq!(
result.get_field_value("fieldWithObjectInput"),
Some(&Value::scalar(r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#)));
Some(&Value::scalar(
r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#
))
);
},
);
}
Expand All @@ -182,7 +183,10 @@ fn inline_runs_from_input_value_on_scalar() {
|result: &Object<DefaultScalarValue>| {
assert_eq!(
result.get_field_value("fieldWithObjectInput"),
Some(&Value::scalar(r#"Some(TestInputObject { a: None, b: None, c: "baz", d: Some(TestComplexScalar) })"#)));
Some(&Value::scalar(
r#"Some(TestInputObject { a: None, b: None, c: "baz", d: Some(TestComplexScalar) })"#
))
);
},
);
}
Expand All @@ -208,7 +212,10 @@ fn variable_complex_input() {
|result: &Object<DefaultScalarValue>| {
assert_eq!(
result.get_field_value("fieldWithObjectInput"),
Some(&Value::scalar(r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#)));
Some(&Value::scalar(
r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#
))
);
},
);
}
Expand All @@ -234,7 +241,10 @@ fn variable_parse_single_value_to_list() {
|result: &Object<DefaultScalarValue>| {
assert_eq!(
result.get_field_value("fieldWithObjectInput"),
Some(&Value::scalar(r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#)));
Some(&Value::scalar(
r#"Some(TestInputObject { a: Some("foo"), b: Some([Some("bar")]), c: "baz", d: None })"#
))
);
},
);
}
Expand All @@ -259,7 +269,10 @@ fn variable_runs_from_input_value_on_scalar() {
|result: &Object<DefaultScalarValue>| {
assert_eq!(
result.get_field_value("fieldWithObjectInput"),
Some(&Value::scalar(r#"Some(TestInputObject { a: None, b: None, c: "baz", d: Some(TestComplexScalar) })"#)));
Some(&Value::scalar(
r#"Some(TestInputObject { a: None, b: None, c: "baz", d: Some(TestComplexScalar) })"#
))
);
},
);
}
Expand Down Expand Up @@ -306,12 +319,13 @@ fn variable_error_on_incorrect_type() {

let error = crate::execute(query, None, &schema, &vars, &()).unwrap_err();

assert_eq!(error, ValidationError(vec![
RuleError::new(
assert_eq!(
error,
ValidationError(vec![RuleError::new(
r#"Variable "$input" got invalid value. Expected "TestInputObject", found not an object."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
),])
);
}

#[test]
Expand Down Expand Up @@ -366,16 +380,19 @@ fn variable_multiple_errors_with_nesting() {

let error = crate::execute(query, None, &schema, &vars, &()).unwrap_err();

assert_eq!(error, ValidationError(vec![
RuleError::new(
r#"Variable "$input" got invalid value. In field "na": In field "c": Expected "String!", found null."#,
&[SourcePosition::new(8, 0, 8)],
),
RuleError::new(
r#"Variable "$input" got invalid value. In field "nb": Expected "String!", found null."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$input" got invalid value. In field "na": In field "c": Expected "String!", found null."#,
&[SourcePosition::new(8, 0, 8)],
),
RuleError::new(
r#"Variable "$input" got invalid value. In field "nb": Expected "String!", found null."#,
&[SourcePosition::new(8, 0, 8)],
),
])
);
}

#[test]
Expand Down Expand Up @@ -733,12 +750,13 @@ fn does_not_allow_lists_of_non_null_to_contain_null() {

let error = crate::execute(query, None, &schema, &vars, &()).unwrap_err();

assert_eq!(error, ValidationError(vec![
RuleError::new(
assert_eq!(
error,
ValidationError(vec![RuleError::new(
r#"Variable "$input" got invalid value. In element #1: Expected "String!", found null."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
),])
);
}

#[test]
Expand All @@ -759,12 +777,13 @@ fn does_not_allow_non_null_lists_of_non_null_to_contain_null() {

let error = crate::execute(query, None, &schema, &vars, &()).unwrap_err();

assert_eq!(error, ValidationError(vec![
RuleError::new(
assert_eq!(
error,
ValidationError(vec![RuleError::new(
r#"Variable "$input" got invalid value. In element #1: Expected "String!", found null."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
),])
);
}

#[test]
Expand Down Expand Up @@ -820,12 +839,13 @@ fn does_not_allow_invalid_types_to_be_used_as_values() {

let error = crate::execute(query, None, &schema, &vars, &()).unwrap_err();

assert_eq!(error, ValidationError(vec![
RuleError::new(
assert_eq!(
error,
ValidationError(vec![RuleError::new(
r#"Variable "$input" expected value of type "TestType!" which cannot be used as an input type."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
),])
);
}

#[test]
Expand All @@ -842,12 +862,13 @@ fn does_not_allow_unknown_types_to_be_used_as_values() {

let error = crate::execute(query, None, &schema, &vars, &()).unwrap_err();

assert_eq!(error, ValidationError(vec![
RuleError::new(
assert_eq!(
error,
ValidationError(vec![RuleError::new(
r#"Variable "$input" expected value of type "UnknownType!" which cannot be used as an input type."#,
&[SourcePosition::new(8, 0, 8)],
),
]));
),])
);
}

#[test]
Expand Down
6 changes: 4 additions & 2 deletions juniper/src/http/graphiql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ pub fn graphiql_source(graphql_endpoint_url: &str) -> String {
</script>
"#;

format!(r#"
format!(
r#"
<!DOCTYPE html>
<html>
<head>
Expand All @@ -62,5 +63,6 @@ pub fn graphiql_source(graphql_endpoint_url: &str) -> String {
"#,
graphql_url = graphql_endpoint_url,
stylesheet_source = stylesheet_source,
fetcher_source = fetcher_source)
fetcher_source = fetcher_source
)
}
3 changes: 2 additions & 1 deletion juniper/src/integrations/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,8 @@ mod tests {
to_string(&ExecutionError::at_origin(FieldError::new(
"foo error",
Value::Object(obj),
))).unwrap(),
)))
.unwrap(),
r#"{"message":"foo error","locations":[{"line":1,"column":1}],"path":[],"extensions":{"foo":"bar"}}"#
);
}
Expand Down
Loading