Skip to content

Commit c9936da

Browse files
committed
rust: bear output filtering extracted into filtering module
1 parent c445ba0 commit c9936da

File tree

2 files changed

+66
-65
lines changed

2 files changed

+66
-65
lines changed

rust/bear/src/filter.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
*/
1919

2020
use std::collections::HashSet;
21+
use std::hash::{DefaultHasher, Hash, Hasher};
2122
use std::path::PathBuf;
2223

24+
use crate::config;
2325
use json_compilation_db::Entry;
2426

2527
/// A predicate that can be used to filter compilation database entries.
@@ -168,6 +170,56 @@ impl EntryPredicateBuilder {
168170
}
169171
}
170172

173+
impl TryFrom<&config::Filter> for EntryPredicate {
174+
type Error = anyhow::Error;
175+
176+
/// Create a filter from the configuration.
177+
fn try_from(config: &config::Filter) -> Result<Self, Self::Error> {
178+
// - Check if the source file exists
179+
// - Check if the source file is not in the exclude list of the configuration
180+
// - Check if the source file is in the include list of the configuration
181+
let source_exist_check = EntryPredicateBuilder::filter_by_source_existence(
182+
config.source.include_only_existing_files,
183+
);
184+
let source_paths_to_exclude = EntryPredicateBuilder::filter_by_source_paths(
185+
config.source.paths_to_exclude.clone(),
186+
);
187+
let source_paths_to_include = EntryPredicateBuilder::filter_by_source_paths(
188+
config.source.paths_to_include.clone(),
189+
);
190+
let source_checks = source_exist_check & !source_paths_to_exclude & source_paths_to_include;
191+
// - Check if the compiler path is not in the list of the configuration
192+
// - Check if the compiler arguments are not in the list of the configuration
193+
let compiler_with_path = EntryPredicateBuilder::filter_by_compiler_paths(
194+
config.compilers.with_paths.clone(),
195+
);
196+
let compiler_with_argument = EntryPredicateBuilder::filter_by_compiler_arguments(
197+
config.compilers.with_arguments.clone(),
198+
);
199+
let compiler_checks = !compiler_with_path & !compiler_with_argument;
200+
// - Check if the entry is not a duplicate based on the fields of the configuration
201+
let hash_function = create_hash(config.duplicates.by_fields.clone());
202+
let duplicates = EntryPredicateBuilder::filter_duplicate_entries(hash_function);
203+
204+
Ok((source_checks & compiler_checks & duplicates).build())
205+
}
206+
}
207+
208+
fn create_hash(fields: Vec<config::OutputFields>) -> impl Fn(&Entry) -> u64 + 'static {
209+
move |entry: &Entry| {
210+
let mut hasher = DefaultHasher::new();
211+
for field in &fields {
212+
match field {
213+
config::OutputFields::Directory => entry.directory.hash(&mut hasher),
214+
config::OutputFields::File => entry.file.hash(&mut hasher),
215+
config::OutputFields::Arguments => entry.arguments.hash(&mut hasher),
216+
config::OutputFields::Output => entry.output.hash(&mut hasher),
217+
}
218+
}
219+
hasher.finish()
220+
}
221+
}
222+
171223
#[cfg(test)]
172224
mod test {
173225
use std::hash::{Hash, Hasher};

rust/bear/src/output.rs

Lines changed: 14 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,14 @@
1818
*/
1919
use std::collections::HashSet;
2020
use std::fs::{File, OpenOptions};
21-
use std::hash::{DefaultHasher, Hash, Hasher};
2221
use std::io::{BufReader, BufWriter};
2322
use std::path::{Path, PathBuf};
2423

2524
use crate::{args, config, filter};
2625
use anyhow::{anyhow, Context, Result};
2726
use json_compilation_db::Entry;
2827
use path_absolutize::Absolutize;
29-
use semantic::{CompilerPass, Meaning};
28+
use semantic;
3029
use serde_json::Error;
3130

3231
/// Responsible for writing the final compilation database file.
@@ -85,7 +84,7 @@ impl OutputWriter {
8584
fn write_into_compilation_db(
8685
&self,
8786
entries: impl Iterator<Item = Entry>,
88-
) -> anyhow::Result<()> {
87+
) -> Result<()> {
8988
// Filter out the entries as per the configuration.
9089
let filter: filter::EntryPredicate = TryFrom::try_from(&self.filter)?;
9190
let filtered_entries = entries.filter(filter);
@@ -172,59 +171,9 @@ fn validate_duplicates_by_fields(fields: &[config::OutputFields]) -> Vec<config:
172171
.collect()
173172
}
174173

175-
impl TryFrom<&config::Filter> for filter::EntryPredicate {
176-
type Error = anyhow::Error;
177-
178-
/// Create a filter from the configuration.
179-
fn try_from(config: &config::Filter) -> std::result::Result<Self, Self::Error> {
180-
// - Check if the source file exists
181-
// - Check if the source file is not in the exclude list of the configuration
182-
// - Check if the source file is in the include list of the configuration
183-
let source_exist_check = filter::EntryPredicateBuilder::filter_by_source_existence(
184-
config.source.include_only_existing_files,
185-
);
186-
let source_paths_to_exclude = filter::EntryPredicateBuilder::filter_by_source_paths(
187-
config.source.paths_to_exclude.clone(),
188-
);
189-
let source_paths_to_include = filter::EntryPredicateBuilder::filter_by_source_paths(
190-
config.source.paths_to_include.clone(),
191-
);
192-
let source_checks = source_exist_check & !source_paths_to_exclude & source_paths_to_include;
193-
// - Check if the compiler path is not in the list of the configuration
194-
// - Check if the compiler arguments are not in the list of the configuration
195-
let compiler_with_path = filter::EntryPredicateBuilder::filter_by_compiler_paths(
196-
config.compilers.with_paths.clone(),
197-
);
198-
let compiler_with_argument = filter::EntryPredicateBuilder::filter_by_compiler_arguments(
199-
config.compilers.with_arguments.clone(),
200-
);
201-
let compiler_checks = !compiler_with_path & !compiler_with_argument;
202-
// - Check if the entry is not a duplicate based on the fields of the configuration
203-
let hash_function = create_hash(config.duplicates.by_fields.clone());
204-
let duplicates = filter::EntryPredicateBuilder::filter_duplicate_entries(hash_function);
205-
206-
Ok((source_checks & compiler_checks & duplicates).build())
207-
}
208-
}
209-
210-
fn create_hash(fields: Vec<config::OutputFields>) -> impl Fn(&Entry) -> u64 + 'static {
211-
move |entry: &Entry| {
212-
let mut hasher = DefaultHasher::new();
213-
for field in &fields {
214-
match field {
215-
config::OutputFields::Directory => entry.directory.hash(&mut hasher),
216-
config::OutputFields::File => entry.file.hash(&mut hasher),
217-
config::OutputFields::Arguments => entry.arguments.hash(&mut hasher),
218-
config::OutputFields::Output => entry.output.hash(&mut hasher),
219-
}
220-
}
221-
hasher.finish()
222-
}
223-
}
224-
225-
pub fn into_entries(value: Meaning) -> Result<Vec<Entry>, anyhow::Error> {
174+
pub fn into_entries(value: semantic::Meaning) -> Result<Vec<Entry>, anyhow::Error> {
226175
match value {
227-
Meaning::Compiler {
176+
semantic::Meaning::Compiler {
228177
compiler,
229178
working_dir,
230179
passes,
@@ -233,10 +182,10 @@ pub fn into_entries(value: Meaning) -> Result<Vec<Entry>, anyhow::Error> {
233182
.iter()
234183
.flat_map(|pass| -> Result<Entry, anyhow::Error> {
235184
match pass {
236-
CompilerPass::Preprocess => {
185+
semantic::CompilerPass::Preprocess => {
237186
Err(anyhow!("preprocess pass should not show up in results"))
238187
}
239-
CompilerPass::Compile {
188+
semantic::CompilerPass::Compile {
240189
source,
241190
output,
242191
flags,
@@ -305,10 +254,10 @@ mod test {
305254
fn test_non_compilations() -> Result<()> {
306255
let empty: Vec<Entry> = vec![];
307256

308-
let result: Vec<Entry> = into_entries(Meaning::Ignored)?;
257+
let result: Vec<Entry> = into_entries(semantic::Meaning::Ignored)?;
309258
assert_eq!(empty, result);
310259

311-
let input = Meaning::Compiler {
260+
let input = semantic::Meaning::Compiler {
312261
compiler: PathBuf::from("/usr/bin/cc"),
313262
working_dir: PathBuf::from("/home/user"),
314263
passes: vec![],
@@ -321,10 +270,10 @@ mod test {
321270

322271
#[test]
323272
fn test_single_source_compilation() -> Result<()> {
324-
let input = Meaning::Compiler {
273+
let input = semantic::Meaning::Compiler {
325274
compiler: PathBuf::from("clang"),
326275
working_dir: PathBuf::from("/home/user"),
327-
passes: vec![CompilerPass::Compile {
276+
passes: vec![semantic::CompilerPass::Compile {
328277
source: PathBuf::from("source.c"),
329278
output: Some(PathBuf::from("source.o")),
330279
flags: vec_of_strings!["-Wall"],
@@ -347,17 +296,17 @@ mod test {
347296

348297
#[test]
349298
fn test_multiple_sources_compilation() -> Result<()> {
350-
let input = Meaning::Compiler {
299+
let input = semantic::Meaning::Compiler {
351300
compiler: PathBuf::from("clang"),
352301
working_dir: PathBuf::from("/home/user"),
353302
passes: vec![
354-
CompilerPass::Preprocess,
355-
CompilerPass::Compile {
303+
semantic::CompilerPass::Preprocess,
304+
semantic::CompilerPass::Compile {
356305
source: PathBuf::from("/tmp/source1.c"),
357306
output: None,
358307
flags: vec_of_strings!["-Wall"],
359308
},
360-
CompilerPass::Compile {
309+
semantic::CompilerPass::Compile {
361310
source: PathBuf::from("../source2.c"),
362311
output: None,
363312
flags: vec_of_strings!["-Wall"],

0 commit comments

Comments
 (0)