use crate::ast;
use crate::schema;
use crate::validation::diagnostics::DiagnosticData;
use crate::validation::DiagnosticList;
pub(crate) fn validate_schema_definition(diagnostics: &mut DiagnosticList, schema: &crate::Schema) {
if schema.schema_definition.query.is_none() {
let location = schema.schema_definition.location();
diagnostics.push(location, DiagnosticData::QueryRootOperationType);
}
validate_root_operation_definitions(diagnostics, schema);
super::directive::validate_directives(
diagnostics,
Some(schema),
schema.schema_definition.directives.iter(),
ast::DirectiveLocation::Schema,
Default::default(),
);
}
pub(crate) fn validate_root_operation_definitions(
diagnostics: &mut DiagnosticList,
schema: &crate::Schema,
) {
let mut seen: Vec<(ast::OperationType, &crate::Name)> = Vec::new();
for (op, name) in schema.schema_definition.iter_root_operations() {
let type_def = schema.types.get(name.as_ref());
if let Some(type_def) = type_def {
if !matches!(type_def, schema::ExtendedType::Object(_)) {
diagnostics.push(
name.location(),
DiagnosticData::RootOperationObjectType {
name: name.as_ref().clone(),
describe_type: type_def.describe(),
},
);
}
} else {
diagnostics.push(
name.location(),
DiagnosticData::UndefinedDefinition {
name: name.as_ref().clone(),
},
);
}
if let Some((original_op, original_name)) = seen
.iter()
.find(|(_, seen_name)| *seen_name == name.as_ref())
{
diagnostics.push(
name.location(),
DiagnosticData::DuplicateRootOperationType {
name: name.as_ref().clone(),
original_operation: *original_op,
original_definition: original_name.location(),
redefined_operation: op,
redefined_definition: name.location(),
},
);
} else {
seen.push((op, name));
}
}
}