|
1 |
| -use crate::fscloc::cloc; |
2 |
| -use ignore::{DirEntry, WalkBuilder, WalkState::Continue}; |
| 1 | +use crate::context::workspace_context::WorkspaceContext; |
3 | 2 | use rayon::prelude::*;
|
4 | 3 | use std::{
|
5 |
| - collections::{HashMap, HashSet}, |
| 4 | + collections::HashMap, |
6 | 5 | path::{Path, PathBuf},
|
7 |
| - sync::Mutex, |
| 6 | + str::FromStr, |
8 | 7 | };
|
9 | 8 |
|
10 |
| -use super::cloc::Stats; |
| 9 | +use super::cloc::{self, Stats}; |
11 | 10 |
|
12 | 11 | pub fn count_lines_of_code_and_collect_line_numbers_to_ignore(
|
13 |
| - src: &Path, |
14 |
| - src_filepaths: &[String], |
| 12 | + root: &Path, |
15 | 13 | skip_cloc: bool,
|
16 |
| - included: &HashSet<PathBuf>, |
17 |
| -) -> Mutex<HashMap<String, Stats>> { |
18 |
| - let (tx, rx) = crossbeam_channel::unbounded(); |
19 |
| - |
20 |
| - let form_path = |path: &String| { |
21 |
| - // Soldiity compiler shenanigans ?? |
22 |
| - // In the line `==== ??? ====` of the output, we're supposed to see the filename |
23 |
| - // But sometimes solc puts filenames with path containing two forward slashes |
24 |
| - // Example `contracts/templegold//AuctionBase.sol` in there |
25 |
| - // Although there is a separate entry for `contracts/templegold/AuctionBase.sol`. |
26 |
| - // We want to omit reading the former |
27 |
| - if path.contains("//") { |
28 |
| - // When using foundry-compilers-aletheia, there is no separate entry so we'll |
29 |
| - // adjust the same entry |
30 |
| - let adjusted_path = path.replace("//", "/"); |
31 |
| - Path::new(&src).join(adjusted_path) |
32 |
| - } else { |
33 |
| - Path::new(&src).join(path) |
34 |
| - } |
35 |
| - }; |
36 |
| - |
37 |
| - let src_filepaths_as_paths = src_filepaths |
38 |
| - .iter() |
39 |
| - .map(form_path) |
40 |
| - .filter(|s| included.contains(s.strip_prefix(src).unwrap())) |
41 |
| - .collect::<Vec<_>>(); |
42 |
| - |
43 |
| - if !src_filepaths_as_paths.is_empty() { |
44 |
| - // Only add the paths to WalkBuilder that we want to do analysis on. |
45 |
| - let mut walker = WalkBuilder::new(src_filepaths_as_paths[0].clone()); |
46 |
| - |
47 |
| - for item in src_filepaths_as_paths.iter().skip(1) { |
48 |
| - walker.add(item); |
49 |
| - } |
50 |
| - |
51 |
| - walker.build_parallel().run(|| { |
52 |
| - let tx = tx.clone(); |
53 |
| - Box::new(move |res| { |
54 |
| - if let Ok(target) = res { |
55 |
| - if target.file_type().unwrap().is_file() { |
56 |
| - let send = target.to_owned(); |
57 |
| - tx.send(send).unwrap(); |
58 |
| - } |
59 |
| - } |
60 |
| - Continue |
61 |
| - }) |
62 |
| - }); |
63 |
| - } |
64 |
| - |
65 |
| - drop(tx); // without this, the program would not terminate .. because receiver would |
66 |
| - // think that the `tx` is still waiting to send something.. but we're done |
67 |
| - // the clones have been dropped but not the original |
68 |
| - // refer rust docs for more on automatic garbage collection :) |
69 |
| - |
70 |
| - let lines_of_code = Mutex::new(HashMap::new()); |
71 |
| - |
72 |
| - let receive = |target_file: DirEntry| { |
73 |
| - // println!("Processing: {:?}", target_file.path()); |
74 |
| - let r_content = std::fs::read_to_string(target_file.path()).unwrap(); |
75 |
| - let stats = cloc::get_stats(&r_content, skip_cloc); |
76 |
| - let key = String::from(target_file.path().to_string_lossy()); |
77 |
| - let mut lock = lines_of_code.lock().unwrap(); |
78 |
| - // println!("Inserting: {} - {}", key, stats.code); |
79 |
| - lock.insert(key, stats); |
80 |
| - }; |
81 |
| - |
82 |
| - rx.into_iter().par_bridge().for_each(receive); |
83 |
| - lines_of_code |
| 14 | + context: &WorkspaceContext, |
| 15 | +) -> HashMap<String, Stats> { |
| 16 | + context |
| 17 | + .source_units() |
| 18 | + .par_iter() |
| 19 | + .map(|source_unit| { |
| 20 | + let path = source_unit.absolute_path.clone().expect("absolute path not inserted"); |
| 21 | + let path = path.replace("//", "/"); // Condense entries that look like `contracts/templegold//AuctionBase.sol` |
| 22 | + if !context.included.contains(&PathBuf::from_str(&path).unwrap()) { |
| 23 | + return None; |
| 24 | + } |
| 25 | + let content = source_unit.source.as_ref().expect("source not filled"); |
| 26 | + let stats = cloc::get_stats(content, skip_cloc); |
| 27 | + let full_path = root.join(&path).to_string_lossy().to_string(); |
| 28 | + Some((full_path, stats)) |
| 29 | + }) |
| 30 | + .flatten() |
| 31 | + .collect() |
84 | 32 | }
|
0 commit comments