use std::collections::HashMap;
use crate::{
diagnostics::{ObjectType, UndefinedDefinition, UniqueDefinition},
hir::UnionMember,
ApolloDiagnostic, ValidationDatabase,
};
pub fn check(db: &dyn ValidationDatabase) -> Vec<ApolloDiagnostic> {
let mut diagnostics = Vec::new();
for union_def in db.unions().iter() {
let mut seen: HashMap<&str, &UnionMember> = HashMap::new();
for union_member in union_def.union_members().iter() {
let name = union_member.name();
let offset: usize = union_member
.ast_node(db.upcast())
.text_range()
.start()
.into();
let len: usize = union_member.ast_node(db.upcast()).text_range().len().into();
if let Some(prev_def) = seen.get(&name) {
let prev_offset: usize = prev_def.ast_node(db.upcast()).text_range().start().into();
let prev_node_len: usize = prev_def.ast_node(db.upcast()).text_range().len().into();
diagnostics.push(ApolloDiagnostic::UniqueDefinition(UniqueDefinition {
name: name.into(),
ty: "union member".into(),
src: db.input(),
original_definition: (prev_offset, prev_node_len).into(),
redefined_definition: (offset, len).into(),
help: Some(format!(
"`{name}` must only be defined once in this document."
)),
}));
} else {
seen.insert(name, union_member);
}
let union_member_type = db
.upcast()
.find_type_system_definition_by_name(name.to_string());
if union_member_type.is_none() {
diagnostics.push(ApolloDiagnostic::UndefinedDefinition(UndefinedDefinition {
ty: name.into(),
src: db.input(),
definition: (offset, len).into(),
}))
} else if let Some(ty) = union_member_type {
if !ty.is_object_type_definition() {
diagnostics.push(ApolloDiagnostic::ObjectType(ObjectType {
name: name.into(),
ty: ty.ty(),
src: db.input(),
definition: (offset, len).into(),
}))
}
}
}
}
diagnostics
}