Skip to content

Commit 253c1b4

Browse files
committed
interpreter construction is reviewed
1 parent 9075ab7 commit 253c1b4

File tree

5 files changed

+336
-221
lines changed

5 files changed

+336
-221
lines changed

bear/src/environment.rs

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22

3+
use std::collections::HashSet;
4+
35
pub const KEY_DESTINATION: &str = "INTERCEPT_COLLECTOR_ADDRESS";
46

57
// man page for `ld.so` (Linux dynamic linker/loader)
@@ -46,42 +48,80 @@ pub const KEY_CARGO__RUSTC_WRAPPER: &str = "RUSTC_WRAPPER";
4648

4749
pub const KEY_CARGO__RUSTFLAGS: &str = "RUSTFLAGS";
4850

51+
static MAKE_PROGRAM_KEYS: std::sync::LazyLock<HashSet<&'static str>> =
52+
std::sync::LazyLock::new(|| {
53+
[
54+
KEY_MAKE__C_COMPILER,
55+
KEY_MAKE__CXX_COMPILER,
56+
KEY_MAKE__C_PREPROCESSOR,
57+
KEY_MAKE__FORTRAN_COMPILER,
58+
KEY_MAKE__ARCHIVE,
59+
KEY_MAKE__ASSEMBLER,
60+
KEY_MAKE__MODULA_COMPILER,
61+
KEY_MAKE__PASCAL_COMPILER,
62+
KEY_MAKE__LEX,
63+
KEY_MAKE__YACC,
64+
KEY_MAKE__LINT,
65+
]
66+
.iter()
67+
.cloned()
68+
.collect()
69+
});
70+
71+
static MAKE_FLAGS_KEYS: std::sync::LazyLock<HashSet<&'static str>> =
72+
std::sync::LazyLock::new(|| {
73+
[
74+
KEY_MAKE__AR_FLAGS,
75+
KEY_MAKE__AS_FLAGS,
76+
KEY_MAKE__C_FLAGS,
77+
KEY_MAKE__CXX_FLAGS,
78+
KEY_MAKE__C_PREPROCESSOR_FLAGS,
79+
KEY_MAKE__FORTRAN_FLAGS,
80+
KEY_MAKE__LINKER_FLAGS,
81+
KEY_MAKE__LINKER_LIBS,
82+
KEY_MAKE__LEX_FLAGS,
83+
KEY_MAKE__YACC_FLAGS,
84+
KEY_MAKE__PASCAL_FLAGS,
85+
KEY_MAKE__LINT_FLAGS,
86+
]
87+
.iter()
88+
.cloned()
89+
.collect()
90+
});
91+
92+
static CARGO_PROGRAM_KEYS: std::sync::LazyLock<HashSet<&'static str>> =
93+
std::sync::LazyLock::new(|| {
94+
[KEY_CARGO__CARGO, KEY_CARGO__RUSTC, KEY_CARGO__RUSTC_WRAPPER]
95+
.iter()
96+
.cloned()
97+
.collect()
98+
});
99+
100+
static CARGO_FLAGS_KEYS: std::sync::LazyLock<HashSet<&'static str>> =
101+
std::sync::LazyLock::new(|| [KEY_CARGO__RUSTFLAGS].iter().cloned().collect());
102+
103+
static GCC_INCLUDE_KEYS: std::sync::LazyLock<HashSet<&'static str>> =
104+
std::sync::LazyLock::new(|| {
105+
[
106+
KEY_GCC__C_INCLUDE_1,
107+
KEY_GCC__C_INCLUDE_2,
108+
KEY_GCC__C_INCLUDE_3,
109+
KEY_GCC__OBJC_INCLUDE,
110+
]
111+
.iter()
112+
.cloned()
113+
.collect()
114+
});
115+
49116
pub fn relevant_env(key: &str) -> bool {
50-
matches!(
51-
key,
52-
KEY_DESTINATION
53-
| KEY_OS__PRELOAD_PATH
54-
| KEY_OS__PATH
55-
| KEY_GCC__C_INCLUDE_1
56-
| KEY_GCC__C_INCLUDE_2
57-
| KEY_GCC__C_INCLUDE_3
58-
| KEY_GCC__OBJC_INCLUDE
59-
| KEY_MAKE__C_COMPILER
60-
| KEY_MAKE__CXX_COMPILER
61-
| KEY_MAKE__C_PREPROCESSOR
62-
| KEY_MAKE__FORTRAN_COMPILER
63-
| KEY_MAKE__ARCHIVE
64-
| KEY_MAKE__ASSEMBLER
65-
| KEY_MAKE__MODULA_COMPILER
66-
| KEY_MAKE__PASCAL_COMPILER
67-
| KEY_MAKE__LEX
68-
| KEY_MAKE__YACC
69-
| KEY_MAKE__LINT
70-
| KEY_MAKE__AR_FLAGS
71-
| KEY_MAKE__AS_FLAGS
72-
| KEY_MAKE__C_FLAGS
73-
| KEY_MAKE__CXX_FLAGS
74-
| KEY_MAKE__C_PREPROCESSOR_FLAGS
75-
| KEY_MAKE__FORTRAN_FLAGS
76-
| KEY_MAKE__LINKER_FLAGS
77-
| KEY_MAKE__LINKER_LIBS
78-
| KEY_MAKE__LEX_FLAGS
79-
| KEY_MAKE__YACC_FLAGS
80-
| KEY_MAKE__PASCAL_FLAGS
81-
| KEY_MAKE__LINT_FLAGS
82-
| KEY_CARGO__CARGO
83-
| KEY_CARGO__RUSTC
84-
| KEY_CARGO__RUSTC_WRAPPER
85-
| KEY_CARGO__RUSTFLAGS
86-
)
117+
matches!(key, KEY_DESTINATION | KEY_OS__PRELOAD_PATH | KEY_OS__PATH)
118+
|| MAKE_PROGRAM_KEYS.contains(key)
119+
|| MAKE_FLAGS_KEYS.contains(key)
120+
|| CARGO_PROGRAM_KEYS.contains(key)
121+
|| CARGO_FLAGS_KEYS.contains(key)
122+
|| GCC_INCLUDE_KEYS.contains(key)
123+
}
124+
125+
pub fn program_env(key: &str) -> bool {
126+
MAKE_PROGRAM_KEYS.contains(key) || CARGO_PROGRAM_KEYS.contains(key)
87127
}

bear/src/modes/mod.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -299,13 +299,7 @@ mod impls {
299299
// Transform and log the events to semantics.
300300
let semantics = events
301301
.into_iter()
302-
.inspect(|event| {
303-
log::debug!("Processing event: {event:?}");
304-
})
305-
.flat_map(|event| self.interpreter.recognize(&event.execution))
306-
.inspect(|semantic| {
307-
log::debug!("Recognized semantic: {semantic:?}");
308-
});
302+
.flat_map(|event| self.interpreter.recognize(&event.execution));
309303

310304
// Consume the entries and write them to the output file.
311305
self.writer.write(semantics)?;

bear/src/semantic/interpreters/filter.rs

Lines changed: 44 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,26 @@ use std::path::PathBuf;
1111
use thiserror::Error;
1212

1313
/// A wrapper interpreter that applies filtering to recognized compiler commands.
14-
pub struct FilteringInterpreter<T: Interpreter> {
14+
pub(super) struct FilteringInterpreter<T: Interpreter> {
1515
inner: T,
16-
filter: Filter,
16+
filter: Option<Filter>,
1717
}
1818

1919
impl<T: Interpreter> FilteringInterpreter<T> {
20-
/// Creates a new filtering interpreter that wraps another interpreter.
21-
fn new(inner: T, filter: Filter) -> Self {
22-
Self { inner, filter }
23-
}
24-
2520
/// Creates a filtering interpreter from configuration.
26-
pub fn from_config(
27-
inner: T,
28-
compilers: &[config::Compiler],
29-
sources: &config::SourceFilter,
30-
) -> Result<Self, InterpreterConfigError> {
31-
let filter = Filter::try_from((compilers, sources))?;
32-
Ok(Self::new(inner, filter))
21+
pub fn from_filter(inner: T, filter: Filter) -> Self {
22+
Self {
23+
inner,
24+
filter: Some(filter),
25+
}
3326
}
3427

3528
/// Creates a pass-through filtering interpreter (no filtering applied).
3629
pub fn pass_through(inner: T) -> Self {
37-
Self::new(inner, Filter::Skip)
30+
Self {
31+
inner,
32+
filter: None,
33+
}
3834
}
3935
}
4036

@@ -43,53 +39,45 @@ impl<T: Interpreter> Interpreter for FilteringInterpreter<T> {
4339
// First, let the inner interpreter recognize the command
4440
let command = self.inner.recognize(execution)?;
4541

46-
match command {
47-
Command::Compiler(compiler_cmd) => {
48-
// Apply filtering to the compiler command
49-
match self.filter.filter_command(&compiler_cmd) {
50-
Ok(()) => Some(Command::Compiler(compiler_cmd)),
51-
Err(reason) => Some(Command::Filtered(reason)),
42+
if let Some(filter) = &self.filter {
43+
// If a filter is set, apply it to the recognized command
44+
match command {
45+
Command::Compiler(compiler_cmd) => {
46+
// Apply filtering to the compiler command
47+
match filter.filter_command(&compiler_cmd) {
48+
Ok(_) => Some(Command::Compiler(compiler_cmd)),
49+
Err(reason) => Some(Command::Filtered(reason)),
50+
}
5251
}
52+
// Pass through other command types unchanged
53+
other => Some(other),
5354
}
54-
// Pass through other command types unchanged
55-
other => Some(other),
55+
} else {
56+
// If no filter is set, return the command as is
57+
Some(command)
5658
}
5759
}
5860
}
5961

6062
#[derive(Debug)]
61-
enum Filter {
62-
/// Apply filtering according to the configuration
63-
Filter {
64-
compiler_filters: HashMap<PathBuf, config::IgnoreOrConsider>,
65-
source_filters: Vec<config::DirectoryFilter>,
66-
},
67-
/// Skip filtering (pass through unchanged)
68-
Skip,
63+
pub(super) struct Filter {
64+
compiler_filters: HashMap<PathBuf, config::IgnoreOrConsider>,
65+
source_filters: Vec<config::DirectoryFilter>,
6966
}
7067

7168
impl Filter {
7269
fn filter_command(&self, cmd: &CompilerCommand) -> Result<(), String> {
73-
match self {
74-
Filter::Skip => Ok(()),
75-
Filter::Filter {
76-
compiler_filters,
77-
source_filters,
78-
} => {
79-
// Check if the compiler should be filtered
80-
if let Some(reason) = self.should_filter_compiler(&cmd.executable, compiler_filters)
81-
{
82-
return Err(reason);
83-
}
84-
85-
// Check if any source files should be filtered
86-
if let Some(reason) = self.should_filter_sources(cmd, source_filters) {
87-
return Err(reason);
88-
}
70+
// Check if the compiler should be filtered
71+
if let Some(reason) = self.should_filter_compiler(&cmd.executable, &self.compiler_filters) {
72+
return Err(reason);
73+
}
8974

90-
Ok(())
91-
}
75+
// Check if any source files should be filtered
76+
if let Some(reason) = self.should_filter_sources(cmd, &self.source_filters) {
77+
return Err(reason);
9278
}
79+
80+
Ok(())
9381
}
9482

9583
fn should_filter_compiler(
@@ -282,7 +270,7 @@ impl TryFrom<(&[config::Compiler], &config::SourceFilter)> for Filter {
282270
// Validate source configuration
283271
let source_filters = Self::validate_source_configuration(sources)?;
284272

285-
Ok(Self::Filter {
273+
Ok(Self {
286274
compiler_filters,
287275
source_filters,
288276
})
@@ -355,8 +343,9 @@ mod tests {
355343
.times(1)
356344
.return_const(Some(Command::Compiler(mock_cmd)));
357345

358-
let sut =
359-
FilteringInterpreter::from_config(mock_interpreter, &compilers, &sources).unwrap();
346+
let filter =
347+
Filter::try_from((compilers.as_slice(), &sources)).expect("Failed to create filter");
348+
let sut = FilteringInterpreter::from_filter(mock_interpreter, filter);
360349

361350
let execution = Execution::from_strings(
362351
"/usr/bin/gcc",
@@ -392,8 +381,9 @@ mod tests {
392381
.times(1)
393382
.return_const(Some(Command::Compiler(mock_cmd)));
394383

395-
let sut =
396-
FilteringInterpreter::from_config(mock_interpreter, &compilers, &sources).unwrap();
384+
let filter =
385+
Filter::try_from((compilers.as_slice(), &sources)).expect("Failed to create filter");
386+
let sut = FilteringInterpreter::from_filter(mock_interpreter, filter);
397387

398388
let execution = Execution::from_strings(
399389
"/usr/bin/gcc",

0 commit comments

Comments
 (0)