Skip to content

Commit

Permalink
Merge pull request #49 from obi1kenobi/support_interface_extension
Browse files Browse the repository at this point in the history
Support interfaces that implement other interfaces.
  • Loading branch information
tailhook authored Oct 8, 2021
2 parents 8a759df + 34970a2 commit b322a14
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 29 deletions.
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

0 comments on commit b322a14

Please sign in to comment.