Skip to content

Commit 34970a2

Browse files
committed
Support interfaces that implement other interfaces.
1 parent 8a759df commit 34970a2

File tree

7 files changed

+67
-29
lines changed

7 files changed

+67
-29
lines changed

src/schema/ast.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ pub struct InterfaceType<'a, T: Text<'a>> {
182182
pub position: Pos,
183183
pub description: Option<String>,
184184
pub name: T::Value,
185+
pub implements_interfaces: Vec<T::Value>,
185186
pub directives: Vec<Directive<'a, T>>,
186187
pub fields: Vec<Field<'a, T>>,
187188
}
@@ -194,6 +195,7 @@ impl<'a, T> InterfaceType<'a, T>
194195
position: Pos::default(),
195196
description: None,
196197
name,
198+
implements_interfaces: vec![],
197199
directives: vec![],
198200
fields: vec![],
199201
}
@@ -204,6 +206,7 @@ impl<'a, T> InterfaceType<'a, T>
204206
pub struct InterfaceTypeExtension<'a, T: Text<'a>> {
205207
pub position: Pos,
206208
pub name: T::Value,
209+
pub implements_interfaces: Vec<T::Value>,
207210
pub directives: Vec<Directive<'a, T>>,
208211
pub fields: Vec<Field<'a, T>>,
209212
}
@@ -215,6 +218,7 @@ where T: Text<'a>
215218
Self {
216219
position: Pos::default(),
217220
name,
221+
implements_interfaces: vec![],
218222
directives: vec![],
219223
fields: vec![],
220224
}

src/schema/format.rs

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::common::Text;
66
use crate::schema::ast::*;
77

88

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

3535

36-
impl<'a, T> Displayable for Document<'a, T>
36+
impl<'a, T> Displayable for Document<'a, T>
3737
where T: Text<'a>,
3838
{
3939
fn display(&self, f: &mut Formatter) {
@@ -43,7 +43,7 @@ impl<'a, T> Displayable for Document<'a, T>
4343
}
4444
}
4545

46-
impl<'a, T> Displayable for Definition<'a, T>
46+
impl<'a, T> Displayable for Definition<'a, T>
4747
where T: Text<'a>,
4848
{
4949
fn display(&self, f: &mut Formatter) {
@@ -57,7 +57,7 @@ impl<'a, T> Displayable for Definition<'a, T>
5757
}
5858
}
5959

60-
impl<'a, T> Displayable for SchemaDefinition<'a, T>
60+
impl<'a, T> Displayable for SchemaDefinition<'a, T>
6161
where T: Text<'a>,
6262
{
6363
fn display(&self, f: &mut Formatter) {
@@ -88,7 +88,7 @@ impl<'a, T> Displayable for SchemaDefinition<'a, T>
8888
}
8989
}
9090

91-
impl<'a, T> Displayable for TypeDefinition<'a, T>
91+
impl<'a, T> Displayable for TypeDefinition<'a, T>
9292
where T: Text<'a>,
9393
{
9494
fn display(&self, f: &mut Formatter) {
@@ -103,7 +103,7 @@ impl<'a, T> Displayable for TypeDefinition<'a, T>
103103
}
104104
}
105105

106-
impl<'a, T> Displayable for ScalarType<'a, T>
106+
impl<'a, T> Displayable for ScalarType<'a, T>
107107
where T: Text<'a>,
108108
{
109109
fn display(&self, f: &mut Formatter) {
@@ -116,7 +116,7 @@ impl<'a, T> Displayable for ScalarType<'a, T>
116116
}
117117
}
118118

119-
impl<'a, T> Displayable for ScalarTypeExtension<'a, T>
119+
impl<'a, T> Displayable for ScalarTypeExtension<'a, T>
120120
where T: Text<'a>,
121121
{
122122
fn display(&self, f: &mut Formatter) {
@@ -128,7 +128,7 @@ impl<'a, T> Displayable for ScalarTypeExtension<'a, T>
128128
}
129129
}
130130

131-
fn format_fields<'a, T>(fields: &[Field<'a, T>], f: &mut Formatter)
131+
fn format_fields<'a, T>(fields: &[Field<'a, T>], f: &mut Formatter)
132132
where T: Text<'a>,
133133
{
134134
if !fields.is_empty() {
@@ -143,7 +143,7 @@ fn format_fields<'a, T>(fields: &[Field<'a, T>], f: &mut Formatter)
143143
}
144144
}
145145

146-
impl<'a, T> Displayable for ObjectType<'a, T>
146+
impl<'a, T> Displayable for ObjectType<'a, T>
147147
where T: Text<'a>,
148148
{
149149
fn display(&self, f: &mut Formatter) {
@@ -164,7 +164,7 @@ impl<'a, T> Displayable for ObjectType<'a, T>
164164
}
165165
}
166166

167-
impl<'a, T> Displayable for ObjectTypeExtension<'a, T>
167+
impl<'a, T> Displayable for ObjectTypeExtension<'a, T>
168168
where T: Text<'a>,
169169
{
170170
fn display(&self, f: &mut Formatter) {
@@ -184,7 +184,7 @@ impl<'a, T> Displayable for ObjectTypeExtension<'a, T>
184184
}
185185
}
186186

187-
impl<'a, T> Displayable for InputValue<'a, T>
187+
impl<'a, T> Displayable for InputValue<'a, T>
188188
where T: Text<'a>,
189189
{
190190
fn display(&self, f: &mut Formatter) {
@@ -203,7 +203,7 @@ impl<'a, T> Displayable for InputValue<'a, T>
203203
}
204204
}
205205

206-
fn format_arguments<'a, T>(arguments: &[InputValue<'a, T>], f: &mut Formatter)
206+
fn format_arguments<'a, T>(arguments: &[InputValue<'a, T>], f: &mut Formatter)
207207
where T: Text<'a>,
208208
{
209209
if !arguments.is_empty() {
@@ -217,7 +217,7 @@ fn format_arguments<'a, T>(arguments: &[InputValue<'a, T>], f: &mut Formatter)
217217
}
218218
}
219219

220-
impl<'a, T> Displayable for Field<'a, T>
220+
impl<'a, T> Displayable for Field<'a, T>
221221
where T: Text<'a>,
222222
{
223223
fn display(&self, f: &mut Formatter) {
@@ -232,32 +232,48 @@ impl<'a, T> Displayable for Field<'a, T>
232232
}
233233
}
234234

235-
impl<'a, T> Displayable for InterfaceType<'a, T>
235+
impl<'a, T> Displayable for InterfaceType<'a, T>
236236
where T: Text<'a>,
237237
{
238238
fn display(&self, f: &mut Formatter) {
239239
description(&self.description, f);
240240
f.indent();
241241
f.write("interface ");
242242
f.write(self.name.as_ref());
243+
if !self.implements_interfaces.is_empty() {
244+
f.write(" implements ");
245+
f.write(self.implements_interfaces[0].as_ref());
246+
for name in &self.implements_interfaces[1..] {
247+
f.write(" & ");
248+
f.write(name.as_ref());
249+
}
250+
}
243251
format_directives(&self.directives, f);
244252
format_fields(&self.fields, f);
245253
}
246254
}
247255

248-
impl<'a, T> Displayable for InterfaceTypeExtension<'a, T>
256+
impl<'a, T> Displayable for InterfaceTypeExtension<'a, T>
249257
where T: Text<'a>,
250258
{
251259
fn display(&self, f: &mut Formatter) {
252260
f.indent();
253261
f.write("extend interface ");
254262
f.write(self.name.as_ref());
263+
if !self.implements_interfaces.is_empty() {
264+
f.write(" implements ");
265+
f.write(self.implements_interfaces[0].as_ref());
266+
for name in &self.implements_interfaces[1..] {
267+
f.write(" & ");
268+
f.write(name.as_ref());
269+
}
270+
}
255271
format_directives(&self.directives, f);
256272
format_fields(&self.fields, f);
257273
}
258274
}
259275

260-
impl<'a, T> Displayable for UnionType<'a, T>
276+
impl<'a, T> Displayable for UnionType<'a, T>
261277
where T: Text<'a>,
262278
{
263279
fn display(&self, f: &mut Formatter) {
@@ -278,7 +294,7 @@ impl<'a, T> Displayable for UnionType<'a, T>
278294
}
279295
}
280296

281-
impl<'a, T> Displayable for UnionTypeExtension<'a, T>
297+
impl<'a, T> Displayable for UnionTypeExtension<'a, T>
282298
where T: Text<'a>,
283299
{
284300
fn display(&self, f: &mut Formatter) {
@@ -298,7 +314,7 @@ impl<'a, T> Displayable for UnionTypeExtension<'a, T>
298314
}
299315
}
300316

301-
impl<'a, T> Displayable for EnumType<'a, T>
317+
impl<'a, T> Displayable for EnumType<'a, T>
302318
where T: Text<'a>,
303319
{
304320
fn display(&self, f: &mut Formatter) {
@@ -327,7 +343,7 @@ impl<'a, T> Displayable for EnumType<'a, T>
327343
}
328344
}
329345

330-
impl<'a, T> Displayable for EnumTypeExtension<'a, T>
346+
impl<'a, T> Displayable for EnumTypeExtension<'a, T>
331347
where T: Text<'a>,
332348
{
333349
fn display(&self, f: &mut Formatter) {
@@ -355,7 +371,7 @@ impl<'a, T> Displayable for EnumTypeExtension<'a, T>
355371
}
356372
}
357373

358-
fn format_inputs<'a, T>(fields: &[InputValue<'a, T>], f: &mut Formatter)
374+
fn format_inputs<'a, T>(fields: &[InputValue<'a, T>], f: &mut Formatter)
359375
where T: Text<'a>,
360376
{
361377
if !fields.is_empty() {
@@ -372,7 +388,7 @@ fn format_inputs<'a, T>(fields: &[InputValue<'a, T>], f: &mut Formatter)
372388
}
373389
}
374390

375-
impl<'a, T> Displayable for InputObjectType<'a, T>
391+
impl<'a, T> Displayable for InputObjectType<'a, T>
376392
where T: Text<'a>,
377393
{
378394
fn display(&self, f: &mut Formatter) {
@@ -385,7 +401,7 @@ impl<'a, T> Displayable for InputObjectType<'a, T>
385401
}
386402
}
387403

388-
impl<'a, T> Displayable for InputObjectTypeExtension<'a, T>
404+
impl<'a, T> Displayable for InputObjectTypeExtension<'a, T>
389405
where T: Text<'a>,
390406
{
391407
fn display(&self, f: &mut Formatter) {
@@ -397,7 +413,7 @@ impl<'a, T> Displayable for InputObjectTypeExtension<'a, T>
397413
}
398414
}
399415

400-
impl<'a, T> Displayable for TypeExtension<'a, T>
416+
impl<'a, T> Displayable for TypeExtension<'a, T>
401417
where T: Text<'a>,
402418
{
403419
fn display(&self, f: &mut Formatter) {
@@ -412,7 +428,7 @@ impl<'a, T> Displayable for TypeExtension<'a, T>
412428
}
413429
}
414430

415-
impl<'a, T> Displayable for DirectiveDefinition<'a, T>
431+
impl<'a, T> Displayable for DirectiveDefinition<'a, T>
416432
where T: Text<'a>,
417433
{
418434
fn display(&self, f: &mut Formatter) {
@@ -441,7 +457,7 @@ impl<'a, T> Displayable for DirectiveDefinition<'a, T>
441457
}
442458

443459
impl_display!(
444-
'a
460+
'a
445461
Document,
446462
Definition,
447463
SchemaDefinition,

src/schema/grammar.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,15 @@ pub fn interface_type<'a, T>(input: &mut TokenStream<'a>)
241241
(
242242
position(),
243243
ident("interface").with(name::<'a, T>()),
244+
parser(implements_interfaces::<T>),
244245
parser(directives),
245246
parser(fields),
246247
)
247-
.map(|(position, name, directives, fields)| {
248+
.map(|(position, name, interfaces, directives, fields)| {
248249
InterfaceType {
249-
position, name, directives, fields,
250+
position, name,
251+
implements_interfaces: interfaces,
252+
directives, fields,
250253
description: None, // is filled in described_definition
251254
}
252255
})
@@ -260,10 +263,11 @@ pub fn interface_type_extension<'a, T>(input: &mut TokenStream<'a>)
260263
(
261264
position(),
262265
ident("interface").with(name::<'a, T>()),
266+
parser(implements_interfaces::<T>),
263267
parser(directives),
264268
parser(fields),
265269
)
266-
.flat_map(|(position, name, directives, fields)| {
270+
.flat_map(|(position, name, interfaces, directives, fields)| {
267271
if directives.is_empty() && fields.is_empty() {
268272
let mut e = Errors::empty(position);
269273
e.add_error(Error::expected_static_message(
@@ -272,7 +276,9 @@ pub fn interface_type_extension<'a, T>(input: &mut TokenStream<'a>)
272276
return Err(e);
273277
}
274278
Ok(InterfaceTypeExtension {
275-
position, name, directives, fields,
279+
position, name,
280+
implements_interfaces: interfaces,
281+
directives, fields,
276282
})
277283
})
278284
.parse_stream(input)

tests/schema_roundtrips.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ fn roundtrip2(filename: &str) {
3535
#[test] fn minimal_type() { roundtrip("minimal_type"); }
3636
#[test] fn implements() { roundtrip("implements"); }
3737
#[test] fn implements_amp() { roundtrip2("implements_amp"); }
38+
#[test] fn implements_interface() { roundtrip("implements_interface"); }
3839
#[test] fn simple_object() { roundtrip("simple_object"); }
3940
#[test] fn extend_object() { roundtrip("extend_object"); }
4041
#[test] fn interface() { roundtrip("interface"); }
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
extend interface Bar {
22
two(argument: InputType!): Type
33
}
4+
5+
extend interface Foo implements IOne & ITwo {
6+
three(argument: [InputType!]!): Type
7+
}

tests/schemas/extend_object.graphql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
extend type Foo {
22
seven(argument: [String]): Type
33
}
4+
5+
extend type Bar implements IOne & ITwo {
6+
five(argument: [String!]!): Type
7+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
interface IOne implements ITwo
2+
3+
interface IThree implements IFour & IFive

0 commit comments

Comments
 (0)