Skip to content

Commit

Permalink
rust: semantic module got comments
Browse files Browse the repository at this point in the history
  • Loading branch information
rizsotto committed Oct 7, 2024
1 parent 2da6d29 commit f758845
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 22 deletions.
4 changes: 3 additions & 1 deletion rust/semantic/src/tools/combinators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
use crate::{Meaning, RecognitionResult, Tool};
use intercept::ipc::Execution;

/// Represents a set of tools, where any of them can recognize the semantic.
/// The evaluation is done in the order of the tools. The first one which
/// recognizes the semantic will be returned as result.
pub struct Any {
tools: Vec<Box<dyn Tool>>,
}
Expand All @@ -31,7 +34,6 @@ impl Any {
}

impl Tool for Any {
/// Any of the tool recognize the semantic, will be returned as result.
fn recognize(&self, x: &Execution) -> RecognitionResult {
for tool in &self.tools {
match tool.recognize(x) {
Expand Down
25 changes: 14 additions & 11 deletions rust/semantic/src/tools/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,33 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

use std::path::{Path, PathBuf};
use std::collections::HashSet;
use std::path::PathBuf;
use std::vec;

use super::super::{CompilerPass, Meaning, RecognitionResult, Tool};
use super::matchers::source::looks_like_a_source_file;
use intercept::ipc::Execution;

/// A tool to recognize a compiler by executable name.
pub struct Generic {
pub executable: PathBuf,
executables: HashSet<PathBuf>,
}

impl Generic {
pub fn new(compiler: &Path) -> Box<dyn Tool> {
Box::new(Self {
executable: compiler.to_path_buf(),
})
pub fn from(compilers: &[PathBuf]) -> Box<dyn Tool> {
let executables = compilers.iter().map(|compiler| compiler.clone()).collect();
Box::new(Self { executables })
}
}

impl Tool for Generic {
/// Any of the tool recognize the semantic, will be returned as result.
/// This tool is a naive implementation only considering:
/// - the executable name,
/// - one of the arguments is a source file,
/// - the rest of the arguments are flags.
fn recognize(&self, x: &Execution) -> RecognitionResult {
if x.executable == self.executable {
if self.executables.contains(&x.executable) {
let mut flags = vec![];
let mut sources = vec![];

Expand Down Expand Up @@ -80,7 +83,7 @@ mod test {

use lazy_static::lazy_static;

use crate::vec_of_strings;
use crate::{vec_of_pathbuf, vec_of_strings};

use super::*;

Expand Down Expand Up @@ -145,7 +148,7 @@ mod test {

lazy_static! {
static ref SUT: Generic = Generic {
executable: PathBuf::from("/usr/bin/something"),
executables: vec_of_pathbuf!["/usr/bin/something"].into_iter().collect()
};
}
}
21 changes: 19 additions & 2 deletions rust/semantic/src/tools/ignore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use std::path::PathBuf;
use super::super::{Meaning, RecognitionResult, Tool};
use intercept::ipc::Execution;

/// A tool to ignore a command execution by executable name.
pub struct IgnoreByPath {
executables: HashSet<PathBuf>,
}
Expand All @@ -39,6 +40,7 @@ impl IgnoreByPath {
}
}

/// A tool to ignore a command execution by arguments.
impl Tool for IgnoreByPath {
fn recognize(&self, execution: &Execution) -> RecognitionResult {
if self.executables.contains(&execution.executable) {
Expand Down Expand Up @@ -193,7 +195,7 @@ mod test {
use super::*;

#[test]
fn test_unix_tools_are_recognized() {
fn test_executions_are_ignored_by_executable_name() {
let input = Execution {
executable: PathBuf::from("/usr/bin/ls"),
arguments: vec_of_strings!["ls", "/home/user/build"],
Expand Down Expand Up @@ -221,5 +223,20 @@ mod test {
assert_eq!(RecognitionResult::NotRecognized, sut.recognize(&input))
}

// TODO: implement test cases for args
#[test]
fn test_executions_are_ignored_by_args() {
let input = Execution {
executable: PathBuf::from("/usr/bin/ls"),
arguments: vec_of_strings!["ls", "-l", "/home/user/build"],
working_dir: PathBuf::from("/home/user"),
environment: HashMap::new(),
};
// let sut = IgnoreByArgs::new(&["-l".to_string()]);
let sut = IgnoreByArgs::new(&vec_of_strings!("-l"));

assert_eq!(
RecognitionResult::Recognized(Ok(Meaning::Ignored)),
sut.recognize(&input)
)
}
}
76 changes: 68 additions & 8 deletions rust/semantic/src/tools/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,40 +30,42 @@ mod generic;
mod ignore;
mod matchers;

/// A builder for creating a tool which can recognize the semantic of a compiler,
/// or ignore known non-compilers.
pub struct Builder {
tools: Vec<Box<dyn Tool>>,
}

// TODO: write unit test for this!!!
impl Builder {
/// Creates a new builder with default settings.
pub fn new() -> Self {
// FIXME: replace this with gcc, when it's implemented
let gcc = PathBuf::from("/usr/bin/g++");
// FIXME: replace generic with gcc, when it's implemented
Builder {
tools: vec![
// ignore executables which are not compilers,
IgnoreByPath::new(),
// recognize default compiler
Generic::new(gcc.as_path()),
Generic::from(&[PathBuf::from("/usr/bin/g++")]),
],
}
}

/// Factory method to create a new tool from the builder.
pub fn build(self) -> impl Tool {
Any::new(self.tools)
}

/// Adds new tools to recognize as compilers by executable name.
pub fn compilers_to_recognize(mut self, compilers: &[PathBuf]) -> Self {
if !compilers.is_empty() {
// Add the new compilers at the end of the tools.
for compiler in compilers {
let tool = Generic::new(compiler);
self.tools.push(tool);
}
let tool = Generic::from(compilers);
self.tools.push(tool);
}
self
}

/// Adds new tools to recognize as non-compilers by executable names.
pub fn compilers_to_exclude(mut self, compilers: &[PathBuf]) -> Self {
if !compilers.is_empty() {
// Add these new compilers at the front of the tools.
Expand All @@ -73,6 +75,7 @@ impl Builder {
self
}

/// Adds new tools to recognize as non-compilers by arguments.
pub fn compilers_to_exclude_by_arguments(mut self, args: &[String]) -> Self {
if !args.is_empty() {
// Add these new compilers at the front of the tools.
Expand All @@ -82,3 +85,60 @@ impl Builder {
self
}
}

#[cfg(test)]
mod test {
use std::collections::HashMap;
use std::path::PathBuf;

use super::super::{vec_of_pathbuf, vec_of_strings};
use super::super::{Meaning, RecognitionResult};
use super::*;
use intercept::ipc::Execution;

#[test]
fn test_builder() {
let sut = Builder::new().build();

let input = any_execution();
match sut.recognize(&input) {
RecognitionResult::Recognized(Ok(Meaning::Compiler { .. })) => assert!(true),
_ => assert!(false),
}
}

#[test]
fn test_builder_with_compilers_to_exclude() {
let compilers = vec_of_pathbuf!["/usr/bin/g++"];
let sut = Builder::new().compilers_to_exclude(&compilers).build();

let input = any_execution();
match sut.recognize(&input) {
RecognitionResult::Recognized(Ok(Meaning::Ignored)) => assert!(true),
_ => assert!(false),
}
}

#[test]
fn test_builder_with_compilers_to_exclude_by_arguments() {
let args = vec_of_strings!["-c"];
let sut = Builder::new()
.compilers_to_exclude_by_arguments(&args)
.build();

let input = any_execution();
match sut.recognize(&input) {
RecognitionResult::Recognized(Ok(Meaning::Ignored)) => assert!(true),
_ => assert!(false),
}
}

fn any_execution() -> Execution {
Execution {
executable: PathBuf::from("/usr/bin/g++"),
arguments: vec_of_strings!["g++", "-c", "main.cpp"],
environment: HashMap::new(),
working_dir: PathBuf::from("/home/user"),
}
}
}

0 comments on commit f758845

Please sign in to comment.