apollo_compiler/validation/
object.rs

1use crate::ast;
2use crate::schema::validation::BuiltInScalars;
3use crate::schema::ObjectType;
4use crate::validation::diagnostics::DiagnosticData;
5use crate::validation::field::validate_field_definitions;
6use crate::validation::DiagnosticList;
7use crate::Node;
8
9pub(crate) fn validate_object_type_definition(
10    diagnostics: &mut DiagnosticList,
11    schema: &crate::Schema,
12    built_in_scalars: &mut BuiltInScalars,
13    object: &Node<ObjectType>,
14) {
15    super::directive::validate_directives(
16        diagnostics,
17        Some(schema),
18        object.directives.iter_ast(),
19        ast::DirectiveLocation::Object,
20        // objects don't use variables
21        Default::default(),
22    );
23
24    // Object Type field validations.
25    validate_field_definitions(diagnostics, schema, built_in_scalars, &object.fields);
26
27    // validate there is at least one field on the type
28    // https://spec.graphql.org/draft/#sel-FAHZhCFDBAACDA4qe
29    if object.fields.is_empty() {
30        diagnostics.push(
31            object.location(),
32            DiagnosticData::EmptyFieldSet {
33                type_name: object.name.clone(),
34                type_location: object.location(),
35                extensions_locations: object
36                    .extensions()
37                    .iter()
38                    .map(|ext| ext.location())
39                    .collect(),
40            },
41        );
42    }
43
44    // Implements Interfaces validation.
45    super::interface::validate_implements_interfaces(
46        diagnostics,
47        schema,
48        &object.name,
49        object.location(),
50        &object.implements_interfaces,
51    );
52
53    // When defining an interface that implements another interface, the
54    // implementing interface must define each field that is specified by
55    // the implemented interface.
56    //
57    // Returns a Missing Field error.
58    for implements_interface in &object.implements_interfaces {
59        if let Some(interface) = schema.get_interface(implements_interface) {
60            for interface_field in interface.fields.values() {
61                if object.fields.contains_key(&interface_field.name) {
62                    continue;
63                }
64
65                diagnostics.push(
66                    object.location(),
67                    DiagnosticData::MissingInterfaceField {
68                        name: object.name.clone(),
69                        implements_location: implements_interface.location(),
70                        interface: implements_interface.name.clone(),
71                        field: interface_field.name.clone(),
72                        field_location: interface_field.location(),
73                    },
74                );
75            }
76        }
77    }
78}