Skip to content

Commit ea3a5b3

Browse files
committed
rust: semantic transformation implements path transformation based on config
1 parent 122d48a commit ea3a5b3

File tree

6 files changed

+451
-286
lines changed

6 files changed

+451
-286
lines changed

rust/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ chrono = { version = "0.4", default-features = false, features = ["std", "clock"
1717
log = { version = "0.4", default-features = false, features = ["std"] }
1818
env_logger = { version = "0.11", default-features = false, features = ["humantime"]}
1919
rand = { version = "0.9", default-features = false, features = ["std", "thread_rng"] }
20-
path-absolutize = "3.1"
2120
directories = "6.0"
2221
nom = { version = "7.1", default-features = false, features = ["std"] }
2322
regex = "1.9"

rust/bear/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ directories.workspace = true
3434
chrono.workspace = true
3535
log.workspace = true
3636
env_logger.workspace = true
37-
path-absolutize.workspace = true
3837
shell-words.workspace = true
3938
nom.workspace = true
4039
regex.workspace = true

rust/bear/src/config.rs

Lines changed: 58 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
//! - The configuration directory of the application.
1818
//!
1919
//! The configuration file content is validated against the schema version,
20-
//! syntax and semantic constraints. If the configuration file is invalid,
20+
//! syntax, and semantic constraints. If the configuration file is invalid,
2121
//! the application will exit with an error message explaining the issue.
2222
//!
2323
//! ```yaml
@@ -35,9 +35,9 @@
3535
//! specification: clang
3636
//! compilers:
3737
//! - path: /usr/local/bin/cc
38-
//! ignore: always
39-
//! - path: /usr/bin/cc
4038
//! ignore: never
39+
//! - path: /usr/bin/cc
40+
//! ignore: always
4141
//! - path: /usr/bin/c++
4242
//! ignore: conditional
4343
//! arguments:
@@ -67,8 +67,9 @@
6767
//! - directory
6868
//! format:
6969
//! paths:
70-
//! resolver: original
71-
//! relative: false
70+
//! directory: canonical
71+
//! file: canonical
72+
//! output: canonical
7273
//! ```
7374
//!
7475
//! ```yaml
@@ -200,7 +201,7 @@ impl Main {
200201
/// The configuration for that is capturing the directory where the wrapper scripts are stored
201202
/// and the list of executables to wrap.
202203
///
203-
/// In preload mode, the compiler is intercepted by a shared library that is preloaded before
204+
/// In preload mode, the compiler is intercepted by a shared library preloaded before
204205
/// the compiler is executed. The configuration for that is the path to the shared library.
205206
#[derive(Debug, PartialEq, Deserialize, Serialize)]
206207
#[serde(tag = "mode")]
@@ -264,7 +265,7 @@ impl Default for Intercept {
264265

265266
/// Output configuration is used to customize the output format.
266267
///
267-
/// Allow to customize the output format of the compiler calls.
268+
/// Allow customizing the output format of the compiler calls.
268269
///
269270
/// - Clang: Output the compiler calls in the clang project defined "JSON compilation database"
270271
/// format. (The format is used by clang tooling and other tools based on that library.)
@@ -301,7 +302,7 @@ impl Default for Output {
301302

302303
/// Represents instructions to transform the compiler calls.
303304
///
304-
/// Allow to transform the compiler calls by adding or removing arguments.
305+
/// Allow transforming the compiler calls by adding or removing arguments.
305306
/// It also can instruct to filter out the compiler call from the output.
306307
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
307308
pub struct Compiler {
@@ -314,31 +315,25 @@ pub struct Compiler {
314315

315316
/// Represents instructions to ignore the compiler call.
316317
///
317-
/// The meaning of the possible values are:
318+
/// The meaning of the possible values is:
318319
/// - Always: Always ignore the compiler call.
319320
/// - Never: Never ignore the compiler call. (Default)
320321
/// - Conditional: Ignore the compiler call if the arguments match.
321-
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
322+
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
322323
pub enum IgnoreOrConsider {
323324
#[serde(rename = "always", alias = "true")]
324325
Always,
326+
#[default]
325327
#[serde(rename = "never", alias = "false")]
326328
Never,
327329
#[serde(rename = "conditional")]
328330
Conditional,
329331
}
330332

331-
/// The default ignore mode is never ignore.
332-
impl Default for IgnoreOrConsider {
333-
fn default() -> Self {
334-
IgnoreOrConsider::Never
335-
}
336-
}
337-
338333
/// Argument lists to match, add or remove.
339334
///
340335
/// The `match` field is used to specify the arguments to match. Can be used only with the
341-
/// conditional ignore mode.
336+
/// conditional mode.
342337
///
343338
/// The `add` or `remove` fields are used to specify the arguments to add or remove. These can be
344339
/// used with the conditional or never ignore mode.
@@ -354,19 +349,28 @@ pub struct Arguments {
354349

355350
/// Source filter configuration is used to filter the compiler calls based on the source files.
356351
///
357-
/// Allow to filter the compiler calls based on the source files.
352+
/// Allow filtering the compiler calls based on the source files.
358353
///
359354
/// - Include only existing files: can be true or false.
360355
/// - List of directories to include or exclude.
361356
/// (The order of these entries will imply the order of evaluation.)
362-
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
357+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
363358
pub struct SourceFilter {
364-
#[serde(default = "default_disabled")]
359+
#[serde(default = "default_enabled")]
365360
pub only_existing_files: bool,
366361
#[serde(default)]
367362
pub paths: Vec<DirectoryFilter>,
368363
}
369364

365+
impl Default for SourceFilter {
366+
fn default() -> Self {
367+
SourceFilter {
368+
only_existing_files: true,
369+
paths: vec![],
370+
}
371+
}
372+
}
373+
370374
/// Directory filter configuration is used to filter the compiler calls based on
371375
/// the source file location.
372376
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
@@ -415,41 +419,34 @@ pub enum OutputFields {
415419
/// Format configuration of the JSON compilation database.
416420
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
417421
pub struct Format {
422+
#[serde(default)]
418423
pub paths: PathFormat,
419424
}
420425

421426
/// Format configuration of paths in the JSON compilation database.
422427
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
423428
pub struct PathFormat {
424429
#[serde(default)]
425-
pub resolver: PathResolver,
426-
#[serde(default = "default_disabled")]
427-
pub relative: bool,
430+
pub directory: PathResolver,
431+
#[serde(default)]
432+
pub file: PathResolver,
433+
#[serde(default)]
434+
pub output: PathResolver,
428435
}
429436

430-
/// Path resolver configuration.
431-
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
437+
#[derive(Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
432438
pub enum PathResolver {
433-
/// The original path is the path as it is passed to the compiler.
434-
#[serde(rename = "original", alias = "is")]
435-
Original,
436-
/// The absolute path from the original path. Symlinks are not resolved.
437-
#[serde(rename = "absolute")]
438-
Absolute,
439-
/// The canonical path is the absolute path with the symlinks resolved.
439+
/// The directory path will be resolved to the canonical path. (Default)
440+
#[default]
440441
#[serde(rename = "canonical")]
441442
Canonical,
443+
/// The directory path will be resolved to the relative path to the directory attribute.
444+
#[serde(rename = "relative")]
445+
Relative,
442446
}
443447

444-
/// The default path format is the original path.
445-
impl Default for PathResolver {
446-
fn default() -> Self {
447-
PathResolver::Original
448-
}
449-
}
450-
451-
fn default_disabled() -> bool {
452-
false
448+
fn default_enabled() -> bool {
449+
true
453450
}
454451

455452
/// The default directory where the wrapper executables will be stored.
@@ -538,8 +535,9 @@ mod test {
538535
- directory
539536
format:
540537
paths:
541-
resolver: canonical
542-
relative: false
538+
directory: canonical
539+
file: canonical
540+
output: canonical
543541
"#;
544542

545543
let result = Main::from_reader(content).unwrap();
@@ -611,8 +609,9 @@ mod test {
611609
},
612610
format: Format {
613611
paths: PathFormat {
614-
resolver: PathResolver::Canonical,
615-
relative: false,
612+
directory: PathResolver::Canonical,
613+
file: PathResolver::Canonical,
614+
output: PathResolver::Canonical,
616615
},
617616
},
618617
},
@@ -661,8 +660,9 @@ mod test {
661660
},
662661
format: Format {
663662
paths: PathFormat {
664-
resolver: PathResolver::Original,
665-
relative: false,
663+
directory: PathResolver::Canonical,
664+
file: PathResolver::Canonical,
665+
output: PathResolver::Canonical,
666666
},
667667
},
668668
},
@@ -720,8 +720,9 @@ mod test {
720720
- file
721721
format:
722722
paths:
723-
resolver: canonical
724-
relative: true
723+
directory: relative
724+
file: relative
725+
output: relative
725726
"#;
726727

727728
let result = Main::from_reader(content).unwrap();
@@ -762,8 +763,9 @@ mod test {
762763
},
763764
format: Format {
764765
paths: PathFormat {
765-
resolver: PathResolver::Canonical,
766-
relative: true,
766+
directory: PathResolver::Relative,
767+
file: PathResolver::Relative,
768+
output: PathResolver::Relative,
767769
},
768770
},
769771
},
@@ -781,7 +783,10 @@ mod test {
781783
intercept: Intercept::default(),
782784
output: Output::Clang {
783785
compilers: vec![],
784-
sources: SourceFilter::default(),
786+
sources: SourceFilter {
787+
only_existing_files: true,
788+
paths: vec![],
789+
},
785790
duplicates: DuplicateFilter::default(),
786791
format: Format::default(),
787792
},

rust/bear/src/modes/semantic.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::intercept::Envelope;
44
use crate::output::OutputWriter;
55
use crate::semantic::interpreters::create_interpreter;
6-
use crate::semantic::transformation::Transformation;
6+
use crate::semantic::transformation::FilterAndFormat;
77
use crate::{args, config, output, semantic};
88
use anyhow::Context;
99
use std::fs::{File, OpenOptions};
@@ -13,20 +13,20 @@ use std::path::{Path, PathBuf};
1313
/// The semantic analysis that is independent of the event source.
1414
pub(super) struct SemanticAnalysisPipeline {
1515
interpreter: Box<dyn semantic::Interpreter>,
16-
transform: Box<dyn semantic::Transform>,
16+
transformation: Box<dyn semantic::Transformation>,
1717
output_writer: OutputWriterImpl,
1818
}
1919

2020
impl SemanticAnalysisPipeline {
2121
/// Create a new semantic mode instance.
2222
pub(super) fn from(output: args::BuildSemantic, config: &config::Main) -> anyhow::Result<Self> {
2323
let interpreter = create_interpreter(config);
24-
let transform = Transformation::from(&config.output);
24+
let transformation = FilterAndFormat::try_from(&config.output)?;
2525
let output_writer = OutputWriterImpl::create(&output, &config.output)?;
2626

2727
Ok(Self {
2828
interpreter: Box::new(interpreter),
29-
transform: Box::new(transform),
29+
transformation: Box::new(transformation),
3030
output_writer,
3131
})
3232
}
@@ -44,7 +44,7 @@ impl SemanticAnalysisPipeline {
4444
.map(|envelope| envelope.event.execution)
4545
.flat_map(|execution| self.interpreter.recognize(&execution))
4646
.inspect(|semantic| log::debug!("semantic: {:?}", semantic))
47-
.flat_map(|semantic| self.transform.apply(semantic));
47+
.flat_map(|semantic| self.transformation.apply(semantic));
4848
// Consume the entries and write them to the output file.
4949
// The exit code is based on the result of the output writer.
5050
self.output_writer.run(entries)

rust/bear/src/semantic/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ impl<T> IntoIterator for Recognition<T> {
8484
/// It conditionally removes compiler calls based on compiler names or flags.
8585
/// It can also alter the compiler flags of the compiler calls. The actions
8686
/// are defined in the configuration this module is given.
87-
pub trait Transform: Send {
88-
fn apply(&self, _: CompilerCall) -> Option<CompilerCall>;
87+
pub trait Transformation: Send {
88+
fn apply(&self, _: CompilerCall) -> anyhow::Result<CompilerCall>;
8989
}
9090

9191
/// Serialize compiler calls into a JSON array.

0 commit comments

Comments
 (0)