//! Shared code-file classification for extraction and pre-ranking scope filters. use std::{path::Path, sync::OnceLock}; pub const CODE_EXTENSIONS: &[&str] = &[ "rs", "py", "pyi", "js", "jsx", "mjs", "cjs", "ts", "tsx", "mts", "cts", "c", "h", "cpp", "cc", "cxx", "hpp", "hxx", "hh", "go", "java", "kt", "kts", "cs", "swift", "m", "mm", "rb", "php", "phtml", "scala", "sc", "sql", "sh", "bash", "zsh", "fish", "ps1", "psm1", "psd1", "bat", "cmd", "lua", "r", "pl", "pm", "ex", "exs", "erl", "hrl", "hs", "lhs", "clj", "cljs", "cljc", "dart", "vue", "svelte", "graphql", "gql", "tf", "tfvars", "proto", "zig", "vb", "vbs", "f", "for", "f90", "f95", "f03", "pas", "d", "cmake", ]; const CODE_FILENAMES: &[&str] = &[ "makefile", "gnumakefile", "dockerfile", "cmakelists.txt", "justfile", ]; pub fn is_code_path(path: &Path) -> bool { let extension = path .extension() .and_then(|value| value.to_str()) .unwrap_or("") .to_ascii_lowercase(); let filename = path .file_name() .and_then(|value| value.to_str()) .unwrap_or("") .to_ascii_lowercase(); CODE_EXTENSIONS.contains(&extension.as_str()) || CODE_FILENAMES.contains(&filename.as_str()) } /// Static trusted SQL predicate for the shared internal `files f` alias. No /// caller-controlled query, path or extension is interpolated into this SQL. pub fn code_file_predicate() -> &'static str { static SQL: OnceLock = OnceLock::new(); SQL.get_or_init(|| { let literals = |values: &[&str]| { values .iter() .map(|value| format!("'{value}'")) .collect::>() .join(",") }; format!( "(f.extension IN ({}) OR lower(f.filename) IN ({}))", literals(CODE_EXTENSIONS), literals(CODE_FILENAMES) ) }) }