use crate::code_block::{Arg, CodeBlock};
use crate::import::ImportRef;
use crate::lang::CodeLang;
pub fn collect_imports<L: CodeLang>(block: &CodeBlock<L>) -> Vec<ImportRef> {
let mut refs = Vec::new();
walk_parts(block, &mut refs);
refs
}
fn walk_parts<L: CodeLang>(block: &CodeBlock<L>, refs: &mut Vec<ImportRef>) {
for arg in &block.args {
match arg {
Arg::TypeName(tn) => {
tn.collect_imports(refs);
}
Arg::Code(inner) => {
walk_parts(inner, refs);
}
_ => {}
}
}
}
pub fn collect_imports_many<L: CodeLang>(blocks: &[&CodeBlock<L>]) -> Vec<ImportRef> {
let mut refs = Vec::new();
for block in blocks {
walk_parts(block, &mut refs);
}
refs
}
#[cfg(test)]
mod tests {
use super::*;
use crate::lang::typescript::TypeScript;
use crate::type_name::TypeName;
#[test]
fn test_collect_from_single_type() {
let user = TypeName::<TypeScript>::importable("./models", "User");
let mut builder = CodeBlock::<TypeScript>::builder();
builder.add_statement("const u: %T = getUser()", (user,));
let block = builder.build().unwrap();
let refs = collect_imports(&block);
assert_eq!(refs.len(), 1);
assert_eq!(refs[0].module, "./models");
assert_eq!(refs[0].name, "User");
}
#[test]
fn test_collect_from_nested_codeblock() {
let user = TypeName::<TypeScript>::importable("./models", "User");
let mut inner_builder = CodeBlock::<TypeScript>::builder();
inner_builder.add_statement("return new %T()", (user,));
let inner = inner_builder.build().unwrap();
let mut outer_builder = CodeBlock::<TypeScript>::builder();
outer_builder.add_code(inner);
let outer = outer_builder.build().unwrap();
let refs = collect_imports(&outer);
assert_eq!(refs.len(), 1);
assert_eq!(refs[0].name, "User");
}
#[test]
fn test_collect_three_types() {
let user = TypeName::<TypeScript>::importable("./models", "User");
let tag = TypeName::<TypeScript>::importable("./models", "Tag");
let base = TypeName::<TypeScript>::importable("./base", "BaseApi");
let mut builder = CodeBlock::<TypeScript>::builder();
builder.add("const u: %T = get%T(%T)", (user, tag, base));
let block = builder.build().unwrap();
let refs = collect_imports(&block);
assert_eq!(refs.len(), 3);
}
#[test]
fn test_collect_no_types() {
let mut builder = CodeBlock::<TypeScript>::builder();
builder.add_statement("const x = 42", ());
let block = builder.build().unwrap();
let refs = collect_imports(&block);
assert!(refs.is_empty());
}
#[test]
fn test_collect_from_raw_content() {
let raw = TypeName::<TypeScript>::raw("any");
let mut builder = CodeBlock::<TypeScript>::builder();
builder.add_statement("const x: %T = null", (raw,));
let block = builder.build().unwrap();
let refs = collect_imports(&block);
assert!(refs.is_empty());
}
}