diff --git a/src/lib.rs b/src/lib.rs index 9eafae7..6ec980d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -159,11 +159,14 @@ impl<'a> SnippetsProducer<'a> { return GlobSet::empty(); } let mut globset = GlobSetBuilder::new(); - elems.iter().filter(|e| !e.is_empty()).for_each(|e| { - if let Ok(glob) = Glob::new(e) { + elems + .iter() + .filter(|e| !e.is_empty()) + .filter_map(|e| Glob::new(e).ok()) + .for_each(|glob| { globset.add(glob); - } - }); + }); + globset.build().map_or(GlobSet::empty(), |globset| globset) } } @@ -220,10 +223,8 @@ impl ConcurrentRunner { .into_iter() .filter_entry(|e| !is_hidden(e)) { - let entry = match entry { - Ok(entry) => entry, - Err(e) => return Err(Error::Concurrent(format!("Sender: {}", e).into())), - }; + let entry = + entry.map_err(|e| Error::Concurrent(format!("Sender: {}", e).into()))?; let path = entry.path().to_path_buf(); if entry_is_valid(&path, include, exclude) { self.send_file(path, &sender)?; @@ -322,10 +323,10 @@ fn extract_file_snippets( // Convert source code bytes to an utf-8 string. // When the conversion is not possible for every bytes, // encode all bytes as utf-8. - let source_file = match std::str::from_utf8(&source_file_bytes) { - Ok(source_file) => source_file.to_owned(), - Err(_) => encode_to_utf8(&source_file_bytes).ok()?, - }; + let source_file = std::str::from_utf8(&source_file_bytes).map_or_else( + |_| encode_to_utf8(&source_file_bytes).ok(), + |source_file| Some(source_file.to_owned()), + )?; // Guess which is the language associated to the source file. let language = guess_language(source_file.as_bytes(), &source_path).0?; diff --git a/src/snippets.rs b/src/snippets.rs index 9505aa0..2f80c2b 100644 --- a/src/snippets.rs +++ b/src/snippets.rs @@ -146,31 +146,38 @@ fn obtain_snippets_single_space( }); } +fn get_snippet_text(source_file: &str, space: &FuncSpace) -> String { + // Get code snippet from source code. + source_file + .lines() + .skip(space.start_line.saturating_sub(1)) + .take((space.end_line - space.start_line) + 1) + .collect::>() + .join("\n") +} + fn obtain_snippets( spaces: &[FuncSpace], source_file: &str, complexity_thresholds: Vec<(Complexity, usize)>, snippets: &mut HashMap>, ) { - // Iter over spaces. - for space in spaces { + // Initialize the stack with the input spaces. + let mut spaces_stack: Vec<&FuncSpace> = spaces.iter().collect(); + + // Iter over stack spaces. + while let Some(space) = spaces_stack.pop() { let complexity_thresholds = complexity_thresholds .iter() .filter_map(|(complexity, threshold)| { complexity.value(space, *threshold).map(|complexity_value| { if complexity_value > *threshold { - // Get code snippet from source code. - let str_lines: Vec<&str> = source_file - .lines() - .skip(space.start_line.saturating_sub(1)) - .take((space.end_line - space.start_line) + 1) - .collect(); save_snippets( *complexity, complexity_value, space.start_line, space.end_line, - str_lines.join("\n"), + get_snippet_text(source_file, space), snippets, ); } @@ -181,7 +188,7 @@ fn obtain_snippets( // Obtain snippets from subspaces which have high complexities values. if !complexity_thresholds.is_empty() { - obtain_snippets(&space.spaces, source_file, complexity_thresholds, snippets); + spaces_stack.extend(&space.spaces); } } } @@ -196,8 +203,11 @@ pub(crate) fn get_code_snippets( // Delete complexity metrics which are below a specified threshold. let complexity_thresholds = complexities .iter() - .filter(|(complexity, threshold)| complexity.value(&space, *threshold).is_some()) - .map(|(complexity, threshold)| (*complexity, *threshold)) + .filter_map(|(complexity, threshold)| { + complexity + .value(&space, *threshold) + .map(|_| (*complexity, *threshold)) + }) .collect::>(); // Do not extract snippets when the code has lower complexities values. @@ -229,5 +239,11 @@ pub(crate) fn get_code_snippets( ); } + // Sort extracted snippets by start line. + metrics_snippets + .snippets + .values_mut() + .for_each(|s| s.sort_unstable_by_key(|snippet| snippet.start_line)); + Some(metrics_snippets) }