1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
use crate::framework_detector::Frameworks; use std::collections::BTreeMap; use std::path::Path; use walkdir::{DirEntry, WalkDir}; pub mod go; pub mod js; pub mod jvm; pub mod rust; type TaggingAction<'a> = fn(dir: &DirEntry) -> Option<&'a str>; type FrameworkAnalysisAction = fn(dir: &DirEntry, frameworks: &Frameworks); struct LangDetector<'a> { tagging: TaggingAction<'a>, framework_analysis: FrameworkAnalysisAction, } pub struct LangDetectors<'a> { pub frameworks: Frameworks, pub(crate) tags: BTreeMap<&'a str, bool>, detectors: Vec<LangDetector<'a>>, } impl<'a> Default for LangDetectors<'a> { fn default() -> Self { LangDetectors { tags: BTreeMap::default(), detectors: vec![ LangDetector { tagging: jvm::tagging, framework_analysis: jvm::framework_analysis, }, LangDetector { tagging: js::tagging, framework_analysis: js::framework_analysis, }, LangDetector { tagging: go::tagging, framework_analysis: go::framework_analysis, }, LangDetector { tagging: rust::tagging, framework_analysis: rust::framework_analysis, }, ], frameworks: Frameworks::default(), } } } impl<'a> LangDetectors<'a> { pub fn detect<P: AsRef<Path>>(&mut self, path: P) { traverse_project_directory(path, |dir_entry| { self.tagging(dir_entry); self.framework_analysis(dir_entry); }) } fn tagging(&mut self, dir_entry: &DirEntry) { for detector in self.detectors.iter() { match (detector.tagging)(dir_entry) { Some(tag) => { self.tags.insert(tag, true); } _ => continue, } } } fn framework_analysis(&mut self, dir_entry: &DirEntry) { for detector in self.detectors.iter() { (detector.framework_analysis)(dir_entry, &mut self.frameworks); } } } fn traverse_project_directory<'a, P: AsRef<Path>, F>(path: P, mut each_entry_callback: F) where F: FnMut(&DirEntry), { let walk_dir = WalkDir::new(path); for dir_entry in walk_dir.into_iter() { if dir_entry.is_err() { continue; } let entry = dir_entry.unwrap(); if entry.path().file_name().is_none() { println!("none file_name {:?}", entry.path()); continue; } (each_entry_callback)(&entry) } }