// extern use itertools::Itertools; use rayon::prelude::*; use similarity::{ProgramFile, Similarity}; use tree_sitter::Parser; fn parser() -> Parser { let mut parser = Parser::new(); parser .set_language(tree_sitter_javascript::language()) .unwrap(); parser } fn main() { let args = std::env::args().skip(1).collect::>(); // read and parse files from disk let (files, errors): (Vec<_>, Vec<_>) = args .par_iter() .map(|arg| ProgramFile::new(arg, &mut parser())) .partition(Result::is_ok); // dump errors if any errors.into_iter().map(Result::unwrap_err).for_each(|err| { eprintln!("{}", err); }); let files: Vec<_> = files.into_iter().map(Result::unwrap).collect(); // compare every pair of files for similarity (0..files.len()) .combinations(2) .map(|item| (item[0], item[1])) .par_bridge() .for_each(|(one, two)| { let one = &files[one]; let two = &files[two]; if one.is_similar(&two, |n| !n.is_extra()) && one.path != two.path { println!("{} {}", one.path.display(), two.path.display()); } }); }