use super::{kaikai, python};
pub fn is_supported(language: &str) -> bool {
matches!(
language,
"Rust"
| "Python"
| "JavaScript"
| "TypeScript"
| "JSX"
| "TSX"
| "Go"
| "Kaikai"
| "Elixir"
| "Elixir Script"
)
}
pub fn extract_imports(language: &str, source: &str) -> Vec<String> {
match language {
"Python" => python::extract(source),
"JavaScript" | "TypeScript" | "JSX" | "TSX" => extract_js(source),
"Go" => extract_go(source),
"Kaikai" => kaikai::extract(source),
_ => vec![],
}
}
fn extract_js(source: &str) -> Vec<String> {
let mut imports = Vec::new();
for line in source.lines() {
let trimmed = line.trim();
if trimmed.starts_with("//") || trimmed.starts_with("*") || trimmed.starts_with("/*") {
continue;
}
if let Some(path) = find_relative_string(trimmed) {
imports.push(path);
}
}
imports
}
fn find_relative_string(line: &str) -> Option<String> {
for &q in &['"', '\'', '`'] {
let mut search = line;
while let Some(start) = search.find(q) {
let inner = &search[start + 1..];
if (inner.starts_with("./") || inner.starts_with("../"))
&& let Some(end) = inner.find(q)
{
return Some(inner[..end].to_string());
}
search = &search[start + 1..];
if search.is_empty() {
break;
}
}
}
None
}
fn extract_go(source: &str) -> Vec<String> {
let mut imports = Vec::new();
let mut in_block = false;
for line in source.lines() {
let trimmed = line.trim();
if trimmed == "import (" {
in_block = true;
continue;
}
if in_block && trimmed == ")" {
in_block = false;
continue;
}
let candidate = if in_block {
Some(trimmed)
} else {
trimmed.strip_prefix("import ").map(str::trim)
};
if let Some(s) = candidate {
if let Some(path) = extract_quoted(s).filter(|p| !p.is_empty()) {
imports.push(path);
}
}
}
imports
}
fn extract_quoted(s: &str) -> Option<String> {
let start = s.rfind('"')?;
let before = &s[..start];
let start2 = before.rfind('"')? + 1;
Some(before[start2..].to_string())
}
#[cfg(test)]
#[path = "extractor_test.rs"]
mod tests;