use std::collections::BTreeSet;
use cratestack_core::{Field, Schema, TypeRef};
pub(super) fn response_reachable(schema: &Schema) -> BTreeSet<&str> {
let mut pending: Vec<&str> = Vec::new();
pending.extend(schema.models.iter().map(|m| m.name.as_str()));
pending.extend(schema.views.iter().map(|v| v.name.as_str()));
for procedure in &schema.procedures {
type_names(&procedure.return_type, &mut pending);
}
for query in &schema.queries {
type_names(&query.result_type, &mut pending);
}
let mut reached = BTreeSet::new();
while let Some(name) = pending.pop() {
if !reached.insert(name) {
continue;
}
for field in fields_of(schema, name) {
type_names(&field.ty, &mut pending);
}
}
reached
}
fn type_names<'a>(ty: &'a TypeRef, out: &mut Vec<&'a str>) {
out.push(&ty.name);
for arg in &ty.generic_args {
type_names(arg, out);
}
}
fn fields_of<'a>(schema: &'a Schema, name: &str) -> &'a [Field] {
if let Some(model) = schema.models.iter().find(|m| m.name == name) {
return &model.fields;
}
if let Some(view) = schema.views.iter().find(|v| v.name == name) {
return &view.fields;
}
if let Some(ty) = schema.types.iter().find(|t| t.name == name) {
return &ty.fields;
}
&[]
}