1use std::fs;
8use std::sync::Arc;
9
10use dup_defs_core::{Def, Frontend, KindSpec};
11use rayon::prelude::*;
12
13use crate::defs::scan_source;
14
15pub use find_dup_defs_canon::kinds::{CLASSES, CONSTANTS, FUNCTIONS, METHODS, TYPE_ALIASES};
18
19static KINDS: &[&KindSpec] = &[&FUNCTIONS, &METHODS, &CLASSES, &CONSTANTS, &TYPE_ALIASES];
20
21pub(crate) fn kind_spec(id: &str) -> &'static KindSpec {
24 match id {
25 "functions" => &FUNCTIONS,
26 "methods" => &METHODS,
27 "classes" => &CLASSES,
28 "constants" => &CONSTANTS,
29 "type-aliases" => &TYPE_ALIASES,
30 other => unreachable!("py-canon emitted unknown kind {other:?}"),
31 }
32}
33
34pub struct Python;
36
37impl Frontend for Python {
38 fn lang(&self) -> &'static str {
39 "py"
40 }
41 fn extensions(&self) -> &'static [&'static str] {
42 &["py"]
43 }
44 fn kinds(&self) -> &'static [&'static KindSpec] {
45 KINDS
46 }
47 fn scan(&self, files: &[Arc<str>]) -> Vec<Def> {
48 files
49 .par_iter()
50 .flat_map(|f| fs::read_to_string(&**f).map_or_else(|_| Vec::new(), |src| scan_source(&src, f)))
51 .collect()
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::Python;
58 use dup_defs_core::Frontend;
59
60 #[test]
61 fn registry_metadata() {
62 let py = Python;
63 assert_eq!(py.lang(), "py");
64 assert_eq!(py.extensions(), &["py"]);
65 assert_eq!(py.kinds().len(), 5);
66 assert!(py.kinds().iter().all(|k| k.id != "interfaces"), "interfaces is TS-only");
67 }
68}