Skip to content

Support interfaces that implement other interfaces. #49

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/schema/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ pub struct InterfaceType<'a, T: Text<'a>> {
pub position: Pos,
pub description: Option<String>,
pub name: T::Value,
pub implements_interfaces: Vec<T::Value>,
pub directives: Vec<Directive<'a, T>>,
pub fields: Vec<Field<'a, T>>,
}
Expand All @@ -194,6 +195,7 @@ impl<'a, T> InterfaceType<'a, T>
position: Pos::default(),
description: None,
name,
implements_interfaces: vec![],
directives: vec![],
fields: vec![],
}
Expand All @@ -204,6 +206,7 @@ impl<'a, T> InterfaceType<'a, T>
pub struct InterfaceTypeExtension<'a, T: Text<'a>> {
pub position: Pos,
pub name: T::Value,
pub implements_interfaces: Vec<T::Value>,
pub directives: Vec<Directive<'a, T>>,
pub fields: Vec<Field<'a, T>>,
}
Expand All @@ -215,6 +218,7 @@ where T: Text<'a>
Self {
position: Pos::default(),
name,
implements_interfaces: vec![],
directives: vec![],
fields: vec![],
}
Expand Down
66 changes: 41 additions & 25 deletions src/schema/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::common::Text;
use crate::schema::ast::*;


impl<'a, T> Document<'a, T>
impl<'a, T> Document<'a, T>
where T: Text<'a>,
{
/// Format a document according to style
Expand All @@ -33,7 +33,7 @@ fn description<'a>(description: &Option<String>, f: &mut Formatter) {
}


impl<'a, T> Displayable for Document<'a, T>
impl<'a, T> Displayable for Document<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -43,7 +43,7 @@ impl<'a, T> Displayable for Document<'a, T>
}
}

impl<'a, T> Displayable for Definition<'a, T>
impl<'a, T> Displayable for Definition<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -57,7 +57,7 @@ impl<'a, T> Displayable for Definition<'a, T>
}
}

impl<'a, T> Displayable for SchemaDefinition<'a, T>
impl<'a, T> Displayable for SchemaDefinition<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand Down Expand Up @@ -88,7 +88,7 @@ impl<'a, T> Displayable for SchemaDefinition<'a, T>
}
}

impl<'a, T> Displayable for TypeDefinition<'a, T>
impl<'a, T> Displayable for TypeDefinition<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -103,7 +103,7 @@ impl<'a, T> Displayable for TypeDefinition<'a, T>
}
}

impl<'a, T> Displayable for ScalarType<'a, T>
impl<'a, T> Displayable for ScalarType<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -116,7 +116,7 @@ impl<'a, T> Displayable for ScalarType<'a, T>
}
}

impl<'a, T> Displayable for ScalarTypeExtension<'a, T>
impl<'a, T> Displayable for ScalarTypeExtension<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -128,7 +128,7 @@ impl<'a, T> Displayable for ScalarTypeExtension<'a, T>
}
}

fn format_fields<'a, T>(fields: &[Field<'a, T>], f: &mut Formatter)
fn format_fields<'a, T>(fields: &[Field<'a, T>], f: &mut Formatter)
where T: Text<'a>,
{
if !fields.is_empty() {
Expand All @@ -143,7 +143,7 @@ fn format_fields<'a, T>(fields: &[Field<'a, T>], f: &mut Formatter)
}
}

impl<'a, T> Displayable for ObjectType<'a, T>
impl<'a, T> Displayable for ObjectType<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -164,7 +164,7 @@ impl<'a, T> Displayable for ObjectType<'a, T>
}
}

impl<'a, T> Displayable for ObjectTypeExtension<'a, T>
impl<'a, T> Displayable for ObjectTypeExtension<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -184,7 +184,7 @@ impl<'a, T> Displayable for ObjectTypeExtension<'a, T>
}
}

impl<'a, T> Displayable for InputValue<'a, T>
impl<'a, T> Displayable for InputValue<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -203,7 +203,7 @@ impl<'a, T> Displayable for InputValue<'a, T>
}
}

fn format_arguments<'a, T>(arguments: &[InputValue<'a, T>], f: &mut Formatter)
fn format_arguments<'a, T>(arguments: &[InputValue<'a, T>], f: &mut Formatter)
where T: Text<'a>,
{
if !arguments.is_empty() {
Expand All @@ -217,7 +217,7 @@ fn format_arguments<'a, T>(arguments: &[InputValue<'a, T>], f: &mut Formatter)
}
}

impl<'a, T> Displayable for Field<'a, T>
impl<'a, T> Displayable for Field<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -232,32 +232,48 @@ impl<'a, T> Displayable for Field<'a, T>
}
}

impl<'a, T> Displayable for InterfaceType<'a, T>
impl<'a, T> Displayable for InterfaceType<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
description(&self.description, f);
f.indent();
f.write("interface ");
f.write(self.name.as_ref());
if !self.implements_interfaces.is_empty() {
f.write(" implements ");
f.write(self.implements_interfaces[0].as_ref());
for name in &self.implements_interfaces[1..] {
f.write(" & ");
f.write(name.as_ref());
}
}
format_directives(&self.directives, f);
format_fields(&self.fields, f);
}
}

impl<'a, T> Displayable for InterfaceTypeExtension<'a, T>
impl<'a, T> Displayable for InterfaceTypeExtension<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
f.indent();
f.write("extend interface ");
f.write(self.name.as_ref());
if !self.implements_interfaces.is_empty() {
f.write(" implements ");
f.write(self.implements_interfaces[0].as_ref());
for name in &self.implements_interfaces[1..] {
f.write(" & ");
f.write(name.as_ref());
}
}
format_directives(&self.directives, f);
format_fields(&self.fields, f);
}
}

impl<'a, T> Displayable for UnionType<'a, T>
impl<'a, T> Displayable for UnionType<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -278,7 +294,7 @@ impl<'a, T> Displayable for UnionType<'a, T>
}
}

impl<'a, T> Displayable for UnionTypeExtension<'a, T>
impl<'a, T> Displayable for UnionTypeExtension<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -298,7 +314,7 @@ impl<'a, T> Displayable for UnionTypeExtension<'a, T>
}
}

impl<'a, T> Displayable for EnumType<'a, T>
impl<'a, T> Displayable for EnumType<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand Down Expand Up @@ -327,7 +343,7 @@ impl<'a, T> Displayable for EnumType<'a, T>
}
}

impl<'a, T> Displayable for EnumTypeExtension<'a, T>
impl<'a, T> Displayable for EnumTypeExtension<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand Down Expand Up @@ -355,7 +371,7 @@ impl<'a, T> Displayable for EnumTypeExtension<'a, T>
}
}

fn format_inputs<'a, T>(fields: &[InputValue<'a, T>], f: &mut Formatter)
fn format_inputs<'a, T>(fields: &[InputValue<'a, T>], f: &mut Formatter)
where T: Text<'a>,
{
if !fields.is_empty() {
Expand All @@ -372,7 +388,7 @@ fn format_inputs<'a, T>(fields: &[InputValue<'a, T>], f: &mut Formatter)
}
}

impl<'a, T> Displayable for InputObjectType<'a, T>
impl<'a, T> Displayable for InputObjectType<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -385,7 +401,7 @@ impl<'a, T> Displayable for InputObjectType<'a, T>
}
}

impl<'a, T> Displayable for InputObjectTypeExtension<'a, T>
impl<'a, T> Displayable for InputObjectTypeExtension<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -397,7 +413,7 @@ impl<'a, T> Displayable for InputObjectTypeExtension<'a, T>
}
}

impl<'a, T> Displayable for TypeExtension<'a, T>
impl<'a, T> Displayable for TypeExtension<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand All @@ -412,7 +428,7 @@ impl<'a, T> Displayable for TypeExtension<'a, T>
}
}

impl<'a, T> Displayable for DirectiveDefinition<'a, T>
impl<'a, T> Displayable for DirectiveDefinition<'a, T>
where T: Text<'a>,
{
fn display(&self, f: &mut Formatter) {
Expand Down Expand Up @@ -441,7 +457,7 @@ impl<'a, T> Displayable for DirectiveDefinition<'a, T>
}

impl_display!(
'a
'a
Document,
Definition,
SchemaDefinition,
Expand Down
14 changes: 10 additions & 4 deletions src/schema/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,15 @@ pub fn interface_type<'a, T>(input: &mut TokenStream<'a>)
(
position(),
ident("interface").with(name::<'a, T>()),
parser(implements_interfaces::<T>),
parser(directives),
parser(fields),
)
.map(|(position, name, directives, fields)| {
.map(|(position, name, interfaces, directives, fields)| {
InterfaceType {
position, name, directives, fields,
position, name,
implements_interfaces: interfaces,
directives, fields,
description: None, // is filled in described_definition
}
})
Expand All @@ -260,10 +263,11 @@ pub fn interface_type_extension<'a, T>(input: &mut TokenStream<'a>)
(
position(),
ident("interface").with(name::<'a, T>()),
parser(implements_interfaces::<T>),
parser(directives),
parser(fields),
)
.flat_map(|(position, name, directives, fields)| {
.flat_map(|(position, name, interfaces, directives, fields)| {
if directives.is_empty() && fields.is_empty() {
let mut e = Errors::empty(position);
e.add_error(Error::expected_static_message(
Expand All @@ -272,7 +276,9 @@ pub fn interface_type_extension<'a, T>(input: &mut TokenStream<'a>)
return Err(e);
}
Ok(InterfaceTypeExtension {
position, name, directives, fields,
position, name,
implements_interfaces: interfaces,
directives, fields,
})
})
.parse_stream(input)
Expand Down
1 change: 1 addition & 0 deletions tests/schema_roundtrips.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fn roundtrip2(filename: &str) {
#[test] fn minimal_type() { roundtrip("minimal_type"); }
#[test] fn implements() { roundtrip("implements"); }
#[test] fn implements_amp() { roundtrip2("implements_amp"); }
#[test] fn implements_interface() { roundtrip("implements_interface"); }
#[test] fn simple_object() { roundtrip("simple_object"); }
#[test] fn extend_object() { roundtrip("extend_object"); }
#[test] fn interface() { roundtrip("interface"); }
Expand Down
4 changes: 4 additions & 0 deletions tests/schemas/extend_interface.graphql
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
extend interface Bar {
two(argument: InputType!): Type
}

extend interface Foo implements IOne & ITwo {
three(argument: [InputType!]!): Type
}
4 changes: 4 additions & 0 deletions tests/schemas/extend_object.graphql
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
extend type Foo {
seven(argument: [String]): Type
}

extend type Bar implements IOne & ITwo {
five(argument: [String!]!): Type
}
3 changes: 3 additions & 0 deletions tests/schemas/implements_interface.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
interface IOne implements ITwo

interface IThree implements IFour & IFive