Skip to content

Commit f8a69b3

Browse files
committed
feat(compiler): allow SDL to contain built-in type redefinition
Updates `SchemaBuilder` to allow SDL to contain built-in meta types (e.g. `__Type`) redefinitions. GraphQL spec doesn't really define the expected behavior for handling SDL with redeclared meta fields (see: [#1036](graphql/graphql-spec#1036), [#1049](graphql/graphql-spec#1049)). `graphql-js` [reference implementation](https://github.com/graphql/graphql-js/blob/v16.11.0/src/utilities/extendSchema.ts#L187) simply ignores those redefinitions even if the underlying type definitions don't match. This PR updates `ignore_builtin_redefinitions` option to also ignore meta types redefinitions (previously it was only allowing built-in scalar redefinitions #990).
1 parent 1e79063 commit f8a69b3

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

crates/apollo-compiler/src/schema/from_ast.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,15 @@ impl SchemaBuilder {
134134
}
135135
Entry::Occupied(entry) => {
136136
let previous = entry.get();
137+
if self.ignore_builtin_redefinitions && previous.is_built_in() {
138+
continue;
139+
}
140+
137141
if $is_scalar && previous.is_built_in() {
138-
if self.ignore_builtin_redefinitions {
139-
continue;
140-
} else {
141-
self.errors.push(
142-
$def.location(),
143-
BuildError::BuiltInScalarTypeRedefinition,
144-
)
145-
}
142+
self.errors.push(
143+
$def.location(),
144+
BuildError::BuiltInScalarTypeRedefinition,
145+
)
146146
} else {
147147
self.errors.push(
148148
$def.name.location(),

crates/apollo-compiler/tests/validation/types.rs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2020,7 +2020,7 @@ mod variable_default_values {
20202020
}
20212021

20222022
#[test]
2023-
fn handles_built_in_type_redefinition() {
2023+
fn handles_built_in_scalar_redefinition() {
20242024
let schema = r#"
20252025
scalar String
20262026
@@ -2049,3 +2049,48 @@ type Query {
20492049
.build()
20502050
.expect("schema parsed successfully");
20512051
}
2052+
2053+
#[test]
2054+
fn handles_built_in_type_redefinition() {
2055+
let schema = r#"
2056+
type __Directive {
2057+
name: String!
2058+
description: String!
2059+
isRepeatable: String!
2060+
args: __InputValue
2061+
locations: String!
2062+
}
2063+
2064+
type Query {
2065+
foo: String
2066+
}
2067+
"#;
2068+
2069+
let errors = Schema::parse_and_validate(schema, "schema.graphql")
2070+
.expect_err("invalid schema")
2071+
.errors;
2072+
let expected = expect![[r#"
2073+
Error: the type `__Directive` is defined multiple times in the schema
2074+
╭─[ built_in.graphql:87:6 ]
2075+
2076+
87 │ type __Directive {
2077+
│ ─────┬─────
2078+
│ ╰─────── previous definition of `__Directive` here
2079+
2080+
├─[ schema.graphql:2:6 ]
2081+
2082+
2 │ type __Directive {
2083+
│ ─────┬─────
2084+
│ ╰─────── `__Directive` redefined here
2085+
2086+
│ Help: remove or rename one of the definitions, or use `extend`
2087+
────╯
2088+
"#]];
2089+
expected.assert_eq(&errors.to_string());
2090+
2091+
let builder = SchemaBuilder::new().ignore_builtin_redefinitions();
2092+
let _ = builder
2093+
.parse(schema, "schema.graphql")
2094+
.build()
2095+
.expect("schema parsed successfully");
2096+
}

0 commit comments

Comments
 (0)