Remove graphql_enum! macro in favor of custom derive
* Extend derive for enums to allow deriving inside the juniper crate itself. Note: this is a rather ugly hack right now, FIXME is in the code * Remove the graphql_enum! macro and replace all internal use with derive * Refactor introspection tests to use derive
This commit is contained in:
parent
b1a62d68e9
commit
f858f416b8
13 changed files with 127 additions and 305 deletions
|
@ -150,9 +150,9 @@ pub type Document<'a> = Vec<Definition<'a>>;
|
||||||
/// Parse an unstructured input value into a Rust data type.
|
/// Parse an unstructured input value into a Rust data type.
|
||||||
///
|
///
|
||||||
/// The conversion _can_ fail, and must in that case return None. Implemented
|
/// The conversion _can_ fail, and must in that case return None. Implemented
|
||||||
/// automatically by the convenience macros `graphql_enum!` and
|
/// automatically by the convenience macro `graphql_scalar!` or by deriving GraphQLEnum.
|
||||||
/// `graphql_scalar!`. Must be implemented manually when manually exposing new
|
///
|
||||||
/// enums or scalars.
|
/// Must be implemented manually when manually exposing new enums or scalars.
|
||||||
pub trait FromInputValue: Sized {
|
pub trait FromInputValue: Sized {
|
||||||
/// Performs the conversion.
|
/// Performs the conversion.
|
||||||
fn from_input_value(v: &InputValue) -> Option<Self>;
|
fn from_input_value(v: &InputValue) -> Option<Self>;
|
||||||
|
|
|
@ -9,7 +9,8 @@ use validation::RuleError;
|
||||||
use parser::SourcePosition;
|
use parser::SourcePosition;
|
||||||
use types::scalars::EmptyMutation;
|
use types::scalars::EmptyMutation;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(GraphQLEnum, Debug)]
|
||||||
|
#[graphql(_internal)]
|
||||||
enum Color {
|
enum Color {
|
||||||
Red,
|
Red,
|
||||||
Green,
|
Green,
|
||||||
|
@ -17,12 +18,6 @@ enum Color {
|
||||||
}
|
}
|
||||||
struct TestType;
|
struct TestType;
|
||||||
|
|
||||||
graphql_enum!(Color {
|
|
||||||
Color::Red => "RED",
|
|
||||||
Color::Green => "GREEN",
|
|
||||||
Color::Blue => "BLUE",
|
|
||||||
});
|
|
||||||
|
|
||||||
graphql_object!(TestType: () |&self| {
|
graphql_object!(TestType: () |&self| {
|
||||||
field to_string(color: Color) -> String {
|
field to_string(color: Color) -> String {
|
||||||
format!("Color::{:?}", color)
|
format!("Color::{:?}", color)
|
||||||
|
|
|
@ -3,6 +3,8 @@ use value::Value;
|
||||||
use schema::model::RootNode;
|
use schema::model::RootNode;
|
||||||
use types::scalars::EmptyMutation;
|
use types::scalars::EmptyMutation;
|
||||||
|
|
||||||
|
#[derive(GraphQLEnum)]
|
||||||
|
#[graphql(name = "SampleEnum", _internal)]
|
||||||
enum Sample {
|
enum Sample {
|
||||||
One,
|
One,
|
||||||
Two,
|
Two,
|
||||||
|
@ -24,11 +26,6 @@ graphql_scalar!(Scalar as "SampleScalar" {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
graphql_enum!(Sample as "SampleEnum" {
|
|
||||||
Sample::One => "ONE",
|
|
||||||
Sample::Two => "TWO",
|
|
||||||
});
|
|
||||||
|
|
||||||
graphql_interface!(Interface: () as "SampleInterface" |&self| {
|
graphql_interface!(Interface: () as "SampleInterface" |&self| {
|
||||||
description: "A sample interface"
|
description: "A sample interface"
|
||||||
|
|
||||||
|
|
|
@ -1,193 +0,0 @@
|
||||||
/**
|
|
||||||
Expose simple enums
|
|
||||||
|
|
||||||
GraphQL enums are similar to enums classes C++ - more like grouped constants
|
|
||||||
with type safety than what Rust enums offer. This macro can be used to export
|
|
||||||
non-data carrying Rust enums to GraphQL:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
# #[macro_use] extern crate juniper;
|
|
||||||
enum Color {
|
|
||||||
Red,
|
|
||||||
Orange,
|
|
||||||
Green,
|
|
||||||
Blue,
|
|
||||||
Black,
|
|
||||||
}
|
|
||||||
|
|
||||||
graphql_enum!(Color {
|
|
||||||
Color::Red => "RED" as "The color red",
|
|
||||||
Color::Orange => "ORANGE",
|
|
||||||
Color::Green => "GREEN",
|
|
||||||
Color::Blue => "BLUE",
|
|
||||||
Color::Black => "BLACK" deprecated "Superseded by ORANGE",
|
|
||||||
});
|
|
||||||
|
|
||||||
# fn main() { }
|
|
||||||
```
|
|
||||||
|
|
||||||
The macro expands to a `match` statement which will result in a compilation
|
|
||||||
error if not all enum variants are covered. It also creates an implementation
|
|
||||||
for `FromInputValue` and `ToInputValue`, making it usable in arguments and
|
|
||||||
default values.
|
|
||||||
|
|
||||||
If you want to expose the enum under a different name than the Rust type,
|
|
||||||
you can write `graphql_enum!(Color as "MyColor" { ...`.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! graphql_enum {
|
|
||||||
( @as_expr, $e:expr) => { $e };
|
|
||||||
( @as_pattern, $p:pat) => { $p };
|
|
||||||
( @as_path, $p:path) => { $p };
|
|
||||||
|
|
||||||
// Calls $val.$func($arg) if $arg is not None
|
|
||||||
( @maybe_apply, None, $func:ident, $val:expr ) => { $val };
|
|
||||||
( @maybe_apply, $arg:tt, $func:ident, $val:expr ) => { $val.$func($arg) };
|
|
||||||
|
|
||||||
// Each of the @parse match arms accumulates data up to a call to @generate.
|
|
||||||
//
|
|
||||||
// ( $name, $outname, $descr ): the name of the Rust enum, the name of the
|
|
||||||
// GraphQL enum (as a string), and the description of the enum (as a string or None)
|
|
||||||
//
|
|
||||||
// [ ( $eval, $ename, $edescr, $edepr ) , ] the value of the Rust enum,
|
|
||||||
// the value of the GraphQL enum (as a string), the description of the enum
|
|
||||||
// value (as a string or None), and the deprecation reason of the enum value
|
|
||||||
// (as a string or None).
|
|
||||||
(
|
|
||||||
@generate,
|
|
||||||
( $name:path, $outname:tt, $descr:tt ),
|
|
||||||
[ $( ( $eval:tt, $ename:tt, $edescr:tt, $edepr:tt ) , )* ]
|
|
||||||
) => {
|
|
||||||
impl $crate::GraphQLType for $name {
|
|
||||||
type Context = ();
|
|
||||||
type TypeInfo = ();
|
|
||||||
|
|
||||||
fn name(_: &()) -> Option<&str> {
|
|
||||||
Some(graphql_enum!(@as_expr, $outname))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn meta<'r>(info: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> {
|
|
||||||
graphql_enum!(
|
|
||||||
@maybe_apply, $descr, description,
|
|
||||||
registry.build_enum_type::<$name>(info, &[
|
|
||||||
$(
|
|
||||||
graphql_enum!(
|
|
||||||
@maybe_apply,
|
|
||||||
$edepr, deprecated,
|
|
||||||
graphql_enum!(
|
|
||||||
@maybe_apply,
|
|
||||||
$edescr, description,
|
|
||||||
$crate::meta::EnumValue::new(graphql_enum!(@as_expr, $ename))))
|
|
||||||
),*
|
|
||||||
]))
|
|
||||||
.into_meta()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve(&self, _: &(), _: Option<&[$crate::Selection]>, _: &$crate::Executor<Self::Context>) -> $crate::Value {
|
|
||||||
match *self {
|
|
||||||
$(
|
|
||||||
graphql_enum!(@as_pattern, $eval) =>
|
|
||||||
$crate::Value::string(graphql_enum!(@as_expr, $ename)) ),*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $crate::FromInputValue for $name {
|
|
||||||
fn from_input_value(v: &$crate::InputValue) -> Option<$name> {
|
|
||||||
match v.as_enum_value().or_else(|| v.as_string_value()) {
|
|
||||||
$(
|
|
||||||
Some(graphql_enum!(@as_pattern, $ename))
|
|
||||||
=> Some(graphql_enum!(@as_expr, $eval)), )*
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $crate::ToInputValue for $name {
|
|
||||||
fn to_input_value(&self) -> $crate::InputValue {
|
|
||||||
match *self {
|
|
||||||
$(
|
|
||||||
graphql_enum!(@as_pattern, $eval) =>
|
|
||||||
$crate::InputValue::string(graphql_enum!(@as_expr, $ename)) ),*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// No more items to parse
|
|
||||||
( @parse, $meta:tt, $acc:tt, ) => {
|
|
||||||
graphql_enum!( @generate, $meta, $acc );
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove extraneous commas
|
|
||||||
( @parse, $meta:tt, $acc:tt, , $($rest:tt)* ) => {
|
|
||||||
graphql_enum!( @parse, $meta, $acc, $($rest)* );
|
|
||||||
};
|
|
||||||
|
|
||||||
// description: <description>
|
|
||||||
(
|
|
||||||
@parse,
|
|
||||||
( $name:tt, $outname:tt, $_ignore:tt ),
|
|
||||||
$acc:tt,
|
|
||||||
description: $descr:tt $($items:tt)*
|
|
||||||
) => {
|
|
||||||
graphql_enum!( @parse, ( $name, $outname, $descr ), $acc, $($items)* );
|
|
||||||
};
|
|
||||||
|
|
||||||
// RustEnumValue => "GraphQL enum value" deprecated <reason>
|
|
||||||
(
|
|
||||||
@parse,
|
|
||||||
$meta:tt,
|
|
||||||
[ $($acc:tt ,)* ],
|
|
||||||
$eval:path => $ename:tt deprecated $depr:tt $($rest:tt)*
|
|
||||||
) => {
|
|
||||||
graphql_enum!( @parse, $meta, [ $($acc ,)* ( $eval, $ename, None, $depr ), ], $($rest)* );
|
|
||||||
};
|
|
||||||
|
|
||||||
// RustEnumValue => "GraphQL enum value" as <description> deprecated <reason>
|
|
||||||
(
|
|
||||||
@parse,
|
|
||||||
$meta:tt,
|
|
||||||
[ $($acc:tt ,)* ],
|
|
||||||
$eval:path => $ename:tt as $descr:tt deprecated $depr:tt $($rest:tt)*
|
|
||||||
) => {
|
|
||||||
graphql_enum!( @parse, $meta, [ $($acc ,)* ( $eval, $ename, $descr, $depr ), ], $($rest)* );
|
|
||||||
};
|
|
||||||
|
|
||||||
// RustEnumValue => "GraphQL enum value" as <description>
|
|
||||||
(
|
|
||||||
@parse,
|
|
||||||
$meta:tt,
|
|
||||||
[ $($acc:tt ,)* ],
|
|
||||||
$eval:path => $ename:tt as $descr:tt $($rest:tt)*
|
|
||||||
) => {
|
|
||||||
graphql_enum!( @parse, $meta, [ $($acc ,)* ( $eval, $ename, $descr, None ), ], $($rest)* );
|
|
||||||
};
|
|
||||||
|
|
||||||
// RustEnumValue => "GraphQL enum value"
|
|
||||||
(
|
|
||||||
@parse,
|
|
||||||
$meta:tt,
|
|
||||||
[ $($acc:tt ,)* ],
|
|
||||||
$eval:path => $ename:tt $($rest:tt)*
|
|
||||||
) => {
|
|
||||||
graphql_enum!( @parse, $meta, [ $($acc ,)* ( $eval , $ename , None , None ), ], $($rest)* );
|
|
||||||
};
|
|
||||||
|
|
||||||
// Entry point:
|
|
||||||
// RustEnumName as "GraphQLEnumName" { ... }
|
|
||||||
(
|
|
||||||
$name:path as $outname:tt { $($items:tt)* }
|
|
||||||
) => {
|
|
||||||
graphql_enum!( @parse, ( $name, $outname, None ), [ ], $($items)* );
|
|
||||||
};
|
|
||||||
|
|
||||||
// Entry point
|
|
||||||
// RustEnumName { ... }
|
|
||||||
(
|
|
||||||
$name:path { $($items:tt)* }
|
|
||||||
) => {
|
|
||||||
graphql_enum!( @parse, ( $name, (stringify!($name)), None ), [ ], $($items)* );
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,6 +1,4 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod enums;
|
|
||||||
#[macro_use]
|
|
||||||
mod object;
|
mod object;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod interface;
|
mod interface;
|
||||||
|
|
|
@ -5,34 +5,6 @@ use value::Value;
|
||||||
use schema::model::RootNode;
|
use schema::model::RootNode;
|
||||||
use types::scalars::EmptyMutation;
|
use types::scalars::EmptyMutation;
|
||||||
|
|
||||||
|
|
||||||
enum DefaultName {
|
|
||||||
Foo,
|
|
||||||
Bar,
|
|
||||||
}
|
|
||||||
enum Named {
|
|
||||||
Foo,
|
|
||||||
Bar,
|
|
||||||
}
|
|
||||||
enum NoTrailingComma {
|
|
||||||
Foo,
|
|
||||||
Bar,
|
|
||||||
}
|
|
||||||
enum EnumDescription {
|
|
||||||
Foo,
|
|
||||||
Bar,
|
|
||||||
}
|
|
||||||
enum EnumValueDescription {
|
|
||||||
Foo,
|
|
||||||
Bar,
|
|
||||||
}
|
|
||||||
enum EnumDeprecation {
|
|
||||||
Foo,
|
|
||||||
Bar,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Root;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Syntax to validate:
|
Syntax to validate:
|
||||||
|
@ -45,37 +17,53 @@ Syntax to validate:
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
graphql_enum!(DefaultName {
|
#[derive(GraphQLEnum)]
|
||||||
DefaultName::Foo => "FOO",
|
#[graphql(_internal)]
|
||||||
DefaultName::Bar => "BAR",
|
enum DefaultName {
|
||||||
});
|
Foo,
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
|
||||||
graphql_enum!(Named as "ANamedEnum" {
|
#[derive(GraphQLEnum)]
|
||||||
Named::Foo => "FOO",
|
#[graphql(name = "ANamedEnum", _internal)]
|
||||||
Named::Bar => "BAR",
|
enum Named {
|
||||||
});
|
Foo,
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
|
||||||
graphql_enum!(NoTrailingComma {
|
#[derive(GraphQLEnum)]
|
||||||
NoTrailingComma::Foo => "FOO",
|
#[graphql(_internal)]
|
||||||
NoTrailingComma::Bar => "BAR"
|
enum NoTrailingComma {
|
||||||
});
|
Foo,
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
|
||||||
graphql_enum!(EnumDescription {
|
#[derive(GraphQLEnum)]
|
||||||
description: "A description of the enum itself"
|
#[graphql(description = "A description of the enum itself", _internal)]
|
||||||
|
enum EnumDescription {
|
||||||
|
Foo,
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
|
||||||
EnumDescription::Foo => "FOO",
|
#[derive(GraphQLEnum)]
|
||||||
EnumDescription::Bar => "BAR",
|
#[graphql(_internal)]
|
||||||
});
|
enum EnumValueDescription {
|
||||||
|
#[graphql(description = "The FOO value")]
|
||||||
|
Foo,
|
||||||
|
#[graphql(description = "The BAR value")]
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
|
||||||
graphql_enum!(EnumValueDescription {
|
#[derive(GraphQLEnum)]
|
||||||
EnumValueDescription::Foo => "FOO" as "The FOO value",
|
#[graphql(_internal)]
|
||||||
EnumValueDescription::Bar => "BAR" as "The BAR value",
|
enum EnumDeprecation {
|
||||||
});
|
#[graphql(deprecated = "Please don't use FOO any more")]
|
||||||
|
Foo,
|
||||||
|
#[graphql(description = "The BAR value", deprecated = "Please don't use BAR any more")]
|
||||||
|
Bar,
|
||||||
|
}
|
||||||
|
|
||||||
graphql_enum!(EnumDeprecation {
|
struct Root;
|
||||||
EnumDeprecation::Foo => "FOO" deprecated "Please don't use FOO any more",
|
|
||||||
EnumDeprecation::Bar => "BAR" as "The BAR value" deprecated "Please don't use BAR any more",
|
|
||||||
});
|
|
||||||
|
|
||||||
graphql_object!(Root: () |&self| {
|
graphql_object!(Root: () |&self| {
|
||||||
field default_name() -> DefaultName { DefaultName::Foo }
|
field default_name() -> DefaultName { DefaultName::Foo }
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
mod enums;
|
|
||||||
mod scalar;
|
mod scalar;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
mod input_object;
|
mod input_object;
|
||||||
|
@ -7,6 +6,7 @@ mod field;
|
||||||
mod object;
|
mod object;
|
||||||
mod interface;
|
mod interface;
|
||||||
mod union;
|
mod union;
|
||||||
|
mod enums;
|
||||||
|
|
||||||
|
|
||||||
// This asserts that the input objects defined public actually became public
|
// This asserts that the input objects defined public actually became public
|
||||||
|
|
|
@ -49,13 +49,17 @@ pub struct DirectiveType<'a> {
|
||||||
pub arguments: Vec<Argument<'a>>,
|
pub arguments: Vec<Argument<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(GraphQLEnum, Clone, PartialEq, Eq, Debug)]
|
||||||
|
#[graphql(name = "__DirectiveLocation", _internal)]
|
||||||
pub enum DirectiveLocation {
|
pub enum DirectiveLocation {
|
||||||
Query,
|
Query,
|
||||||
Mutation,
|
Mutation,
|
||||||
Field,
|
Field,
|
||||||
|
#[graphql(name = "FRAGMENT_DEFINITION")]
|
||||||
FragmentDefinition,
|
FragmentDefinition,
|
||||||
|
#[graphql(name = "FRAGMENT_SPREAD")]
|
||||||
FragmentSpread,
|
FragmentSpread,
|
||||||
|
#[graphql(name = "INLINE_SPREAD")]
|
||||||
InlineFragment,
|
InlineFragment,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,17 +232,6 @@ graphql_object!(EnumValue: () as "__EnumValue" |&self| {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
graphql_enum!(TypeKind as "__TypeKind" {
|
|
||||||
TypeKind::Scalar => "SCALAR",
|
|
||||||
TypeKind::Object => "OBJECT",
|
|
||||||
TypeKind::Interface => "INTERFACE",
|
|
||||||
TypeKind::Union => "UNION",
|
|
||||||
TypeKind::Enum => "ENUM",
|
|
||||||
TypeKind::InputObject => "INPUT_OBJECT",
|
|
||||||
TypeKind::List => "LIST",
|
|
||||||
TypeKind::NonNull => "NON_NULL",
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
graphql_object!(<'a> DirectiveType<'a>: SchemaType<'a> as "__Directive" |&self| {
|
graphql_object!(<'a> DirectiveType<'a>: SchemaType<'a> as "__Directive" |&self| {
|
||||||
field name() -> &String {
|
field name() -> &String {
|
||||||
|
@ -282,11 +271,3 @@ graphql_object!(<'a> DirectiveType<'a>: SchemaType<'a> as "__Directive" |&self|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
graphql_enum!(DirectiveLocation as "__DirectiveLocation" {
|
|
||||||
DirectiveLocation::Query => "QUERY",
|
|
||||||
DirectiveLocation::Mutation => "MUTATION",
|
|
||||||
DirectiveLocation::Field => "FIELD",
|
|
||||||
DirectiveLocation::FragmentDefinition => "FRAGMENT_DEFINITION",
|
|
||||||
DirectiveLocation::FragmentSpread => "FRAGMENT_SPREAD",
|
|
||||||
DirectiveLocation::InlineFragment => "INLINE_FRAGMENT",
|
|
||||||
});
|
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
#[derive(GraphQLEnum, Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
|
#[graphql(_internal)]
|
||||||
pub enum Episode {
|
pub enum Episode {
|
||||||
|
#[graphql(name = "NEW_HOPE")]
|
||||||
NewHope,
|
NewHope,
|
||||||
Empire,
|
Empire,
|
||||||
Jedi,
|
Jedi,
|
||||||
|
|
|
@ -3,12 +3,6 @@ use executor::Context;
|
||||||
|
|
||||||
impl Context for Database {}
|
impl Context for Database {}
|
||||||
|
|
||||||
graphql_enum!(Episode {
|
|
||||||
Episode::NewHope => "NEW_HOPE",
|
|
||||||
Episode::Empire => "EMPIRE",
|
|
||||||
Episode::Jedi => "JEDI",
|
|
||||||
});
|
|
||||||
|
|
||||||
graphql_interface!(<'a> &'a Character: Database as "Character" |&self| {
|
graphql_interface!(<'a> &'a Character: Database as "Character" |&self| {
|
||||||
description: "A character in the Star Wars Trilogy"
|
description: "A character in the Star Wars Trilogy"
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,9 @@ use parser::Spanning;
|
||||||
///
|
///
|
||||||
/// The GraphQL specification defines a number of type kinds - the meta type
|
/// The GraphQL specification defines a number of type kinds - the meta type
|
||||||
/// of a type.
|
/// of a type.
|
||||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
#[derive(GraphQLEnum, Clone, Eq, PartialEq, Debug)]
|
||||||
|
// Note: _internal flag needed to make derive work in juniper crate itself.
|
||||||
|
#[graphql(name = "__TypeKind", _internal)]
|
||||||
pub enum TypeKind {
|
pub enum TypeKind {
|
||||||
/// ## Scalar types
|
/// ## Scalar types
|
||||||
///
|
///
|
||||||
|
@ -48,6 +50,7 @@ pub enum TypeKind {
|
||||||
/// ## Input objects
|
/// ## Input objects
|
||||||
///
|
///
|
||||||
/// Represents complex values provided in queries _into_ the system.
|
/// Represents complex values provided in queries _into_ the system.
|
||||||
|
#[graphql(name = "INPUT_OBJECT")]
|
||||||
InputObject,
|
InputObject,
|
||||||
|
|
||||||
/// ## List types
|
/// ## List types
|
||||||
|
@ -61,6 +64,7 @@ pub enum TypeKind {
|
||||||
///
|
///
|
||||||
/// In GraphQL, nullable types are the default. By putting a `!` after a
|
/// In GraphQL, nullable types are the default. By putting a `!` after a
|
||||||
/// type, it becomes non-nullable.
|
/// type, it becomes non-nullable.
|
||||||
|
#[graphql(name = "NON_NULL")]
|
||||||
NonNull,
|
NonNull,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,17 @@ use util::*;
|
||||||
struct EnumAttrs {
|
struct EnumAttrs {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
|
internal: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnumAttrs {
|
impl EnumAttrs {
|
||||||
fn from_input(input: &DeriveInput) -> EnumAttrs {
|
fn from_input(input: &DeriveInput) -> EnumAttrs {
|
||||||
let mut res = EnumAttrs::default();
|
let mut res = EnumAttrs{
|
||||||
|
name: None,
|
||||||
|
description: None,
|
||||||
|
/// Flag to specify whether the calling crate is the "juniper" crate itself.
|
||||||
|
internal: false,
|
||||||
|
};
|
||||||
|
|
||||||
// Check attributes for name and description.
|
// Check attributes for name and description.
|
||||||
if let Some(items) = get_graphl_attr(&input.attrs) {
|
if let Some(items) = get_graphl_attr(&input.attrs) {
|
||||||
|
@ -26,6 +32,15 @@ impl EnumAttrs {
|
||||||
res.description = Some(val);
|
res.description = Some(val);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
match item {
|
||||||
|
&NestedMetaItem::MetaItem(MetaItem::Word(ref ident)) => {
|
||||||
|
if ident == "_internal" {
|
||||||
|
res.internal = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
|
}
|
||||||
panic!(format!(
|
panic!(format!(
|
||||||
"Unknown attribute for #[derive(GraphQLEnum)]: {:?}",
|
"Unknown attribute for #[derive(GraphQLEnum)]: {:?}",
|
||||||
item
|
item
|
||||||
|
@ -119,7 +134,7 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
|
||||||
None => quote!{ None },
|
None => quote!{ None },
|
||||||
};
|
};
|
||||||
let value = quote!{
|
let value = quote!{
|
||||||
::juniper::meta::EnumValue{
|
_juniper::meta::EnumValue{
|
||||||
name: #name.to_string(),
|
name: #name.to_string(),
|
||||||
description: #descr,
|
description: #descr,
|
||||||
deprecation_reason: #depr,
|
deprecation_reason: #depr,
|
||||||
|
@ -129,7 +144,7 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
|
||||||
|
|
||||||
// Build resolve match clause.
|
// Build resolve match clause.
|
||||||
let resolve = quote!{
|
let resolve = quote!{
|
||||||
&#ident::#var_ident => ::juniper::Value::String(#name.to_string()),
|
&#ident::#var_ident => _juniper::Value::String(#name.to_string()),
|
||||||
};
|
};
|
||||||
resolves.push(resolve);
|
resolves.push(resolve);
|
||||||
|
|
||||||
|
@ -142,13 +157,13 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
|
||||||
// Buil to_input clause.
|
// Buil to_input clause.
|
||||||
let to_input = quote!{
|
let to_input = quote!{
|
||||||
&#ident::#var_ident =>
|
&#ident::#var_ident =>
|
||||||
::juniper::InputValue::string(#name.to_string()),
|
_juniper::InputValue::string(#name.to_string()),
|
||||||
};
|
};
|
||||||
to_inputs.push(to_input);
|
to_inputs.push(to_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
quote! {
|
let body = quote! {
|
||||||
impl ::juniper::GraphQLType for #ident {
|
impl _juniper::GraphQLType for #ident {
|
||||||
type Context = ();
|
type Context = ();
|
||||||
type TypeInfo = ();
|
type TypeInfo = ();
|
||||||
|
|
||||||
|
@ -156,7 +171,7 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
|
||||||
Some(#name)
|
Some(#name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta<'r>(_: &(), registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> {
|
fn meta<'r>(_: &(), registry: &mut _juniper::Registry<'r>) -> _juniper::meta::MetaType<'r> {
|
||||||
let meta = registry.build_enum_type::<#ident>(&(), &[
|
let meta = registry.build_enum_type::<#ident>(&(), &[
|
||||||
#(#values)*
|
#(#values)*
|
||||||
]);
|
]);
|
||||||
|
@ -164,15 +179,15 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
|
||||||
meta.into_meta()
|
meta.into_meta()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve(&self, _: &(), _: Option<&[::juniper::Selection]>, _: &::juniper::Executor<Self::Context>) -> ::juniper::Value {
|
fn resolve(&self, _: &(), _: Option<&[_juniper::Selection]>, _: &_juniper::Executor<Self::Context>) -> _juniper::Value {
|
||||||
match self {
|
match self {
|
||||||
#(#resolves)*
|
#(#resolves)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::juniper::FromInputValue for #ident {
|
impl _juniper::FromInputValue for #ident {
|
||||||
fn from_input_value(v: &::juniper::InputValue) -> Option<#ident> {
|
fn from_input_value(v: &_juniper::InputValue) -> Option<#ident> {
|
||||||
match v.as_enum_value().or_else(|| v.as_string_value()) {
|
match v.as_enum_value().or_else(|| v.as_string_value()) {
|
||||||
#(#from_inputs)*
|
#(#from_inputs)*
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -180,12 +195,49 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::juniper::ToInputValue for #ident {
|
impl _juniper::ToInputValue for #ident {
|
||||||
fn to_input_value(&self) -> ::juniper::InputValue {
|
fn to_input_value(&self) -> _juniper::InputValue {
|
||||||
match self {
|
match self {
|
||||||
#(#to_inputs)*
|
#(#to_inputs)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let dummy_const = Ident::new(format!("_IMPL_GRAPHQLENUM_FOR_{}", ident));
|
||||||
|
|
||||||
|
// This ugly hack makes it possible to use the derive inside juniper itself.
|
||||||
|
// FIXME: Figure out a better way to do this!
|
||||||
|
let crate_reference = if attrs.internal {
|
||||||
|
quote! {
|
||||||
|
#[doc(hidden)]
|
||||||
|
mod _juniper {
|
||||||
|
pub use ::{
|
||||||
|
InputValue,
|
||||||
|
Value,
|
||||||
|
ToInputValue,
|
||||||
|
FromInputValue,
|
||||||
|
Executor,
|
||||||
|
Selection,
|
||||||
|
Registry,
|
||||||
|
GraphQLType,
|
||||||
|
meta
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
extern crate juniper as _juniper;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let generated = quote! {
|
||||||
|
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
|
||||||
|
#[doc(hidden)]
|
||||||
|
const #dummy_const : () = {
|
||||||
|
#crate_reference
|
||||||
|
#body
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
generated
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue