Skip to content

Commit f7d62f4

Browse files
Robert Balickifacebook-github-bot
authored andcommitted
When adding a concrete object that implements an interface to a schema, also modify interfaces
Summary: * When we modify a schema (AFAIK this only happens with resolvers), when a new concrete type that implements an interface is added, the interface is not modified to include that type in its implementing_objects. * Fix that * This is not an issue when we build the schema. Reviewed By: alunyov Differential Revision: D44298502 fbshipit-source-id: c439fa222a6ee307cb803ebf992fabae63c805c8
1 parent 0466d31 commit f7d62f4

File tree

1 file changed

+76
-2
lines changed
  • compiler/crates/schema/src/in_memory

1 file changed

+76
-2
lines changed

compiler/crates/schema/src/in_memory/mod.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,8 +1071,32 @@ impl InMemorySchema {
10711071
)]);
10721072
}
10731073

1074-
let object_id = Type::Object(ObjectID(self.objects.len() as u32));
1075-
self.type_map.insert(object_name.item, object_id);
1074+
let object_id = self.objects.len() as u32;
1075+
let object_type = Type::Object(ObjectID(self.objects.len() as u32));
1076+
self.type_map.insert(object_name.item, object_type);
1077+
1078+
let interfaces = object
1079+
.interfaces
1080+
.iter()
1081+
.map(|name| self.build_interface_id(name, &location_key))
1082+
.collect::<DiagnosticsResult<Vec<_>>>()?;
1083+
1084+
for interface_id in &interfaces {
1085+
// All interfaces implemented by this concrete object should exist, and this
1086+
// should be checked beforehand.
1087+
let interface_obj = self
1088+
.interfaces
1089+
.get_mut(interface_id.0 as usize)
1090+
.expect("Expected interface to exist");
1091+
1092+
if !interface_obj
1093+
.implementing_objects
1094+
.contains(&ObjectID(object_id))
1095+
{
1096+
interface_obj.implementing_objects.push(ObjectID(object_id))
1097+
}
1098+
}
1099+
10761100
self.add_definition(
10771101
&TypeSystemDefinition::ObjectTypeDefinition(object),
10781102
&location_key,
@@ -1668,6 +1692,8 @@ fn expect_object_type_name(type_map: &TypeMap, object_id: ObjectID) -> StringKey
16681692

16691693
#[cfg(test)]
16701694
mod tests {
1695+
use common::Span;
1696+
16711697
use super::*;
16721698

16731699
#[test]
@@ -1676,4 +1702,52 @@ mod tests {
16761702
extend_without_duplicates(&mut target, vec![1, 10, 100]);
16771703
assert_eq!(target, vec![10, 11, 1, 100]);
16781704
}
1705+
1706+
fn identifier_from_value(value: StringKey) -> Identifier {
1707+
Identifier {
1708+
span: Span { start: 0, end: 1 },
1709+
token: Token {
1710+
span: Span { start: 0, end: 1 },
1711+
kind: TokenKind::Identifier,
1712+
},
1713+
value,
1714+
}
1715+
}
1716+
1717+
#[test]
1718+
fn test_adding_extension_object() {
1719+
let mut schema = InMemorySchema::create_uninitialized();
1720+
1721+
schema
1722+
.add_interface(Interface {
1723+
name: WithLocation::generated(InterfaceName("ITunes".intern())),
1724+
is_extension: false,
1725+
implementing_interfaces: vec![],
1726+
implementing_objects: vec![],
1727+
fields: vec![],
1728+
directives: vec![],
1729+
interfaces: vec![],
1730+
description: None,
1731+
})
1732+
.unwrap();
1733+
1734+
schema
1735+
.add_extension_object(
1736+
ObjectTypeDefinition {
1737+
name: identifier_from_value("EarlyModel".intern()),
1738+
interfaces: vec![identifier_from_value("ITunes".intern())],
1739+
directives: vec![],
1740+
fields: None,
1741+
},
1742+
SourceLocationKey::Generated,
1743+
)
1744+
.unwrap();
1745+
1746+
let interface = schema.interface(InterfaceID(0));
1747+
1748+
assert!(
1749+
interface.implementing_objects.len() == 1,
1750+
"ITunes should have an implementing object"
1751+
);
1752+
}
16791753
}

0 commit comments

Comments
 (0)