use std::fs;
use std::sync::Arc;
use dup_defs_core::{Def, Frontend, KindSpec};
use rayon::prelude::*;
use crate::defs::scan_source;
pub static FUNCTIONS: KindSpec =
KindSpec { id: "functions", label: "FUNCTION", noun_plural: "functions", section: 1, body: true, fn_like: true };
pub static METHODS: KindSpec =
KindSpec { id: "methods", label: "METHOD", noun_plural: "methods", section: 4, body: true, fn_like: true };
pub static CLASSES: KindSpec =
KindSpec { id: "classes", label: "CLASS", noun_plural: "classes", section: 7, body: true, fn_like: false };
pub static CONSTANTS: KindSpec =
KindSpec { id: "constants", label: "CONSTANT", noun_plural: "constants", section: 0, body: false, fn_like: false };
pub static TYPE_ALIASES: KindSpec =
KindSpec { id: "type-aliases", label: "TYPE_ALIAS", noun_plural: "type aliases", section: 9, body: false, fn_like: false };
static KINDS: &[&KindSpec] = &[&FUNCTIONS, &METHODS, &CLASSES, &CONSTANTS, &TYPE_ALIASES];
pub(crate) fn kind_spec(id: &str) -> &'static KindSpec {
match id {
"functions" => &FUNCTIONS,
"methods" => &METHODS,
"classes" => &CLASSES,
"constants" => &CONSTANTS,
"type-aliases" => &TYPE_ALIASES,
other => unreachable!("py-canon emitted unknown kind {other:?}"),
}
}
pub struct Python;
impl Frontend for Python {
fn lang(&self) -> &'static str {
"py"
}
fn extensions(&self) -> &'static [&'static str] {
&["py"]
}
fn kinds(&self) -> &'static [&'static KindSpec] {
KINDS
}
fn scan(&self, files: &[Arc<str>]) -> Vec<Def> {
files
.par_iter()
.flat_map(|f| fs::read_to_string(&**f).map_or_else(|_| Vec::new(), |src| scan_source(&src, f)))
.collect()
}
}
#[cfg(test)]
mod tests {
use super::Python;
use dup_defs_core::Frontend;
#[test]
fn registry_metadata() {
let py = Python;
assert_eq!(py.lang(), "py");
assert_eq!(py.extensions(), &["py"]);
assert_eq!(py.kinds().len(), 5);
assert!(py.kinds().iter().all(|k| k.id != "interfaces"), "interfaces is TS-only");
}
}