use amalgam_core::types::Type;
use std::collections::HashSet;
pub fn find_k8s_type_references(ty: &Type) -> HashSet<String> {
let mut refs = HashSet::new();
collect_references(ty, &mut refs);
refs
}
fn collect_references(ty: &Type, refs: &mut HashSet<String>) {
match ty {
Type::Reference(name) => {
if is_k8s_type(name) {
refs.insert(name.clone());
}
}
Type::Array(inner) => collect_references(inner, refs),
Type::Optional(inner) => collect_references(inner, refs),
Type::Map { value, .. } => collect_references(value, refs),
Type::Record { fields, .. } => {
for field in fields.values() {
collect_references(&field.ty, refs);
}
}
Type::Union(types) => {
for t in types {
collect_references(t, refs);
}
}
Type::TaggedUnion { variants, .. } => {
for t in variants.values() {
collect_references(t, refs);
}
}
Type::Contract { base, .. } => collect_references(base, refs),
_ => {}
}
}
fn is_k8s_type(name: &str) -> bool {
matches!(
name,
"ListMeta"
| "ObjectMeta"
| "LabelSelector"
| "Time"
| "MicroTime"
| "Status"
| "StatusDetails"
| "StatusCause"
| "FieldsV1"
| "ManagedFieldsEntry"
| "OwnerReference"
| "Preconditions"
| "DeleteOptions"
| "ListOptions"
| "GetOptions"
| "WatchEvent"
)
}
pub fn generate_k8s_import(type_name: &str, current_version: &str) -> Option<String> {
let (import_path, version) = match type_name {
"ListMeta" | "ObjectMeta" | "LabelSelector" | "Status" | "StatusDetails"
| "DeleteOptions" | "ListOptions" | "GetOptions" | "WatchEvent" | "ManagedFieldsEntry"
| "OwnerReference" | "Preconditions" => {
("../v1", "v1")
}
"Time" | "MicroTime" | "FieldsV1" | "StatusCause" => {
("../v1", "v1")
}
_ => return None,
};
if version == current_version {
return None;
}
Some(format!(
"let {} = import \"{}/{}.ncl\" in",
type_name.to_lowercase(),
import_path,
type_name.to_lowercase()
))
}
pub fn fix_k8s_imports(
content: &str,
type_refs: &HashSet<String>,
current_version: &str,
) -> String {
let mut imports = Vec::new();
let mut replacements = Vec::new();
for type_name in type_refs {
if let Some(import_stmt) = generate_k8s_import(type_name, current_version) {
imports.push(import_stmt);
replacements.push((
format!("| {}", type_name),
format!("| {}.{}", type_name.to_lowercase(), type_name),
));
}
}
if imports.is_empty() {
return content.to_string();
}
let mut result = imports.join("\n") + "\n\n" + content;
for (from, to) in replacements {
result = result.replace(&from, &to);
}
result
}