use std::fs;
use std::sync::Arc;
use dup_defs_core::{Def, Frontend, KindSpec};
use rayon::prelude::*;
use crate::defs::scan_source;
pub use find_dup_defs_canon::kinds::{CLASSES, CONSTANTS, FUNCTIONS, METHODS, TYPE_ALIASES};
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");
}
}