Skip to content

Commit

Permalink
Codegen reimplementation for GraphQL unions (#666)
Browse files Browse the repository at this point in the history
- reimplement #[derive(GraphQLUnion)] macro to support:
    - both structs and enums
    - generics in type definition
    - multiple #[graphql] attributes
    - external resolver functions
- remove From trait impls generation for enum variants

- reimplement #[graphql_union] macro to support:
    - traits
    - generics in trait definition
    - multiple attributes
    - external resolver functions
    - GraphQLType implemetation for a raw trait object
    - GraphQLTypeAsync implemetation (#549)

- add marker::GraphQLUnion trait

- rewrite "2.5 Unions" section in Book (Juniper user documentation)

- rewrite `codegen` and `codegen_fail` integration tests for GraphQL unions

Additionally:
- re-export `futures` crate in `juniper` for convenient reuse in the generated code without requiring library user to provide `futures` crate by himself (#663)
- use unit type () as default context for EmptyMutation and EmptySubscriptions
- relax Sized trait bound on some GraphQLType and GraphQLTypeAsync definitions, implementations and usages
  • Loading branch information
tyranron authored Jun 4, 2020
1 parent 31d0888 commit ddc1488
Show file tree
Hide file tree
Showing 99 changed files with 5,656 additions and 1,530 deletions.
435 changes: 347 additions & 88 deletions docs/book/content/types/unions.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions docs/book/tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ build = "build.rs"
juniper = { path = "../../../juniper" }
juniper_iron = { path = "../../../juniper_iron" }
juniper_subscriptions = { path = "../../../juniper_subscriptions" }

derive_more = "0.99.7"
futures = "0.3"
tokio = { version = "0.2", features = ["rt-core", "blocking", "stream", "rt-util"] }
iron = "0.5.0"
Expand Down
6 changes: 6 additions & 0 deletions integration_tests/codegen_fail/fail/union/attr_wrong_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use juniper::graphql_union;

#[graphql_union]
enum Character {}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: #[graphql_union] attribute is applicable to trait definitions only
--> $DIR/attr_wrong_item.rs:3:1
|
3 | #[graphql_union]
| ^^^^^^^^^^^^^^^^
|
= note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
12 changes: 0 additions & 12 deletions integration_tests/codegen_fail/fail/union/derive_enum_field.rs

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions integration_tests/codegen_fail/fail/union/derive_no_fields.rs

This file was deleted.

This file was deleted.

10 changes: 0 additions & 10 deletions integration_tests/codegen_fail/fail/union/derive_same_type.stderr

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use juniper::GraphQLUnion;

#[derive(GraphQLUnion)]
union Character { id: i32 }

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: GraphQL union can only be derived for enums and structs
--> $DIR/derive_wrong_item.rs:4:1
|
4 | union Character { id: i32 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use juniper::{GraphQLObject, GraphQLUnion};

#[derive(GraphQLUnion)]
#[graphql(on Human = resolve_fn1)]
enum Character {
#[graphql(with = resolve_fn2)]
A(Human),
}

#[derive(GraphQLObject)]
pub struct Human {
id: String,
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: GraphQL union variant `Human` already has external resolver function `resolve_fn1` declared on the enum
--> $DIR/enum_external_resolver_fn_conflicts_with_variant_external_resolver_fn.rs:6:15
|
6 | #[graphql(with = resolve_fn2)]
| ^^^^
|
= note: https://spec.graphql.org/June2018/#sec-Unions
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use juniper::{GraphQLObject, GraphQLUnion};

#[derive(GraphQLUnion)]
enum __Character {
A(Human),
}

#[derive(GraphQLObject)]
pub struct Human {
id: String,
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: All types and directives defined within a schema must not have a name which begins with `__` (two underscores), as this is used exclusively by GraphQL’s introspection system.
--> $DIR/enum_name_double_underscored.rs:4:6
|
4 | enum __Character {
| ^^^^^^^^^^^
|
= note: https://spec.graphql.org/June2018/#sec-Schema
6 changes: 6 additions & 0 deletions integration_tests/codegen_fail/fail/union/enum_no_fields.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use juniper::GraphQLUnion;

#[derive(GraphQLUnion)]
enum Character {}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: GraphQL union expects at least one union variant
--> $DIR/enum_no_fields.rs:4:1
|
4 | enum Character {}
| ^^^^^^^^^^^^^^^^^
|
= note: https://spec.graphql.org/June2018/#sec-Unions
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use juniper::{GraphQLEnum, GraphQLUnion};

#[derive(GraphQLEnum)]
pub enum Test {
A,
B,
}

#[derive(GraphQLUnion)]
enum Character {
Test(Test),
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
error[E0277]: the trait bound `Test: juniper::types::marker::GraphQLObjectType<juniper::value::scalar::DefaultScalarValue>` is not satisfied
--> $DIR/enum_non_object_variant.rs:9:10
|
9 | #[derive(GraphQLUnion)]
| ^^^^^^^^^^^^ the trait `juniper::types::marker::GraphQLObjectType<juniper::value::scalar::DefaultScalarValue>` is not implemented for `Test`
|
= note: required by `juniper::types::marker::GraphQLObjectType::mark`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `Test: juniper::types::marker::GraphQLObjectType<__S>` is not satisfied
--> $DIR/enum_non_object_variant.rs:9:10
|
9 | #[derive(GraphQLUnion)]
| ^^^^^^^^^^^^ the trait `juniper::types::marker::GraphQLObjectType<__S>` is not implemented for `Test`
|
= note: required by `juniper::types::marker::GraphQLObjectType::mark`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use juniper::GraphQLUnion;

#[derive(GraphQLUnion)]
enum Character {
A(u8),
B(u8),
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: GraphQL union must have a different type for each union variant
--> $DIR/enum_same_type_pretty.rs:4:1
|
4 | / enum Character {
5 | | A(u8),
6 | | B(u8),
7 | | }
| |_^
|
= note: https://spec.graphql.org/June2018/#sec-Unions
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#[derive(juniper::GraphQLUnion)]
use juniper::GraphQLUnion;

#[derive(GraphQLUnion)]
enum Character {
A(std::string::String),
B(String),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error[E0119]: conflicting implementations of trait `<Character as juniper::types::marker::GraphQLUnion>::mark::_::{{closure}}#0::MutuallyExclusive` for type `std::string::String`:
--> $DIR/enum_same_type_ugly.rs:3:10
|
3 | #[derive(GraphQLUnion)]
| ^^^^^^^^^^^^
| |
| first implementation here
| conflicting implementation for `std::string::String`
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use juniper::{GraphQLObject, GraphQLUnion};

#[derive(GraphQLUnion)]
enum Character1 {
A { human: Human },
}

#[derive(GraphQLUnion)]
enum Character2 {
A(Human, u8),
}

#[derive(GraphQLObject)]
pub struct Human {
id: String,
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: GraphQL union enum allows only unnamed variants with a single field, e.g. `Some(T)`
--> $DIR/enum_wrong_variant_field.rs:5:5
|
5 | A { human: Human },
| ^
|
= note: https://spec.graphql.org/June2018/#sec-Unions

error: GraphQL union enum allows only unnamed variants with a single field, e.g. `Some(T)`
--> $DIR/enum_wrong_variant_field.rs:10:6
|
10 | A(Human, u8),
| ^^^^^^^^^^^
|
= note: https://spec.graphql.org/June2018/#sec-Unions
23 changes: 0 additions & 23 deletions integration_tests/codegen_fail/fail/union/impl_enum_field.rs

This file was deleted.

This file was deleted.

10 changes: 0 additions & 10 deletions integration_tests/codegen_fail/fail/union/impl_no_fields.rs

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use juniper::{GraphQLObject, GraphQLUnion};

#[derive(GraphQLUnion)]
#[graphql(on Human = __Character::a)]
struct __Character;

impl __Character {
fn a(&self, _: &()) -> Option<&Human> {
None
}
}

#[derive(GraphQLObject)]
pub struct Human {
id: String,
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: All types and directives defined within a schema must not have a name which begins with `__` (two underscores), as this is used exclusively by GraphQL’s introspection system.
--> $DIR/struct_name_double_underscored.rs:5:8
|
5 | struct __Character;
| ^^^^^^^^^^^
|
= note: https://spec.graphql.org/June2018/#sec-Schema
6 changes: 6 additions & 0 deletions integration_tests/codegen_fail/fail/union/struct_no_fields.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use juniper::GraphQLUnion;

#[derive(GraphQLUnion)]
struct Character;

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error: GraphQL union expects at least one union variant
--> $DIR/struct_no_fields.rs:4:1
|
4 | struct Character;
| ^^^^^^^^^^^^^^^^^
|
= note: https://spec.graphql.org/June2018/#sec-Unions
Loading

0 comments on commit ddc1488

Please sign in to comment.