Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rust_arkitect"
version = "0.2.5"
version = "0.3.0"
authors = ["Patrick Luca Fazzi <patrick91@live.it>"]
edition = "2021"
description = "rust_arkitect is a lightweight library for defining and validating architectural rules in Rust projects"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,11 @@ impl Display for TestRule {

// Implement the Rule trait
impl Rule for TestRule {
fn apply(&self, _file: &str) -> Result<(), String> {
fn apply(&self, _file: &RustFile) -> Result<(), String> {
Ok(())
}

fn is_applicable(&self, _file: &str) -> bool {
fn is_applicable(&self, _file: &RustFile) -> bool {
true
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/dependency_parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub fn get_dependencies_in_file(path: &str) -> Vec<String> {
};

match get_module(path) {
Ok(module) => get_dependencies_in_ast(ast, &module),
Ok(module) => get_dependencies_in_ast(&ast, &module),
Err(_e) => vec![],
}
}
Expand Down Expand Up @@ -45,10 +45,10 @@ fn get_dependencies_in_str(s: &str, module: &str) -> Vec<String> {
Err(e) => panic!("Failed to parse string '{}': {}", s, e),
};

get_dependencies_in_ast(ast, module)
get_dependencies_in_ast(&ast, module)
}

fn get_dependencies_in_ast(ast: File, current_module: &str) -> Vec<String> {
pub fn get_dependencies_in_ast(ast: &File, current_module: &str) -> Vec<String> {
let mut dependencies = Vec::new();

for item in ast.items.iter() {
Expand Down
19 changes: 9 additions & 10 deletions src/engine.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::rules::rule::Rule;
use crate::rules::rule::{Rule, RustFile};
use ansi_term::Color::RGB;
use ansi_term::Style;
use log::{debug, error, info};
Expand Down Expand Up @@ -90,17 +90,16 @@
fn apply_rules(&mut self, file: PathBuf) {
let file_name = file.to_str().unwrap();
let bold = Style::new().bold().fg(RGB(0, 255, 0));
let absolute_file_name = file
.canonicalize()
.ok()
.and_then(|p| p.to_str().map(String::from))
.unwrap_or_else(|| "Unknown file".to_string());

info!("🛠Applying rules to {}", bold.paint(absolute_file_name));
let file = RustFile::from(file_name);
info!(
"🛠Applying rules to {} ({})",
&file.logical_path,
bold.paint(&file.path)

Check warning on line 97 in src/engine.rs

View check run for this annotation

Codecov / codecov/patch

src/engine.rs#L95-L97

Added lines #L95 - L97 were not covered by tests
);
for rule in self.rules {
if rule.is_applicable(file_name) {
if rule.is_applicable(&file) {
debug!("🟢 Rule {} applied", rule);
match rule.apply(file_name) {
match rule.apply(&file) {
Ok(_) => info!("\u{2705} Rule {} respected", rule),
Err(e) => {
error!("🟥 Rule {} violated: {}", rule, e);
Expand Down
39 changes: 16 additions & 23 deletions src/rules/may_depend_on.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::dependency_parsing::{get_dependencies_in_file, get_module};
use crate::rules::rule::Rule;
use crate::dependency_parsing::get_dependencies_in_ast;
use crate::rules::rule::{Rule, RustFile};
use crate::rules::utils::IsChild;
use ansi_term::Color::RGB;
use ansi_term::Style;
Expand All @@ -8,15 +8,15 @@ use std::fmt::{Display, Formatter};

#[derive(Debug)]
pub struct MayDependOnRule {
pub(crate) subject: String,
pub(crate) allowed_dependencies: Vec<String>,
pub subject: String,
pub allowed_dependencies: Vec<String>,
}

impl Display for MayDependOnRule {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut allowed_dependencies: Vec<String> = Vec::new();
allowed_dependencies.extend(self.allowed_dependencies.clone());
let bold = Style::new().bold().fg(ansi_term::Color::RGB(255, 165, 0));
let bold = Style::new().bold().fg(RGB(255, 165, 0));
if allowed_dependencies.is_empty() {
write!(
f,
Expand All @@ -35,20 +35,13 @@ impl Display for MayDependOnRule {
}

impl Rule for MayDependOnRule {
fn apply(&self, file: &str) -> Result<(), String> {
let module = get_module(file).unwrap();
let subject = if module.len() > self.subject.len() {
&self.subject
} else {
&module
};

let dependencies = get_dependencies_in_file(file);
fn apply(&self, file: &RustFile) -> Result<(), String> {
let dependencies = get_dependencies_in_ast(&file.ast, &file.logical_path);

let forbidden_dependencies: Vec<String> = dependencies
.iter()
.filter(|&dependency| {
let is_child_of_subject = dependency.is_child_of(subject);
let is_child_of_subject = dependency.is_child_of(&self.subject);
if !is_child_of_subject {
let is_allowed = self
.allowed_dependencies
Expand All @@ -69,23 +62,22 @@ impl Rule for MayDependOnRule {
return Err(format!(
"Forbidden dependencies to {} in file://{}",
red.paint("[".to_string() + &forbidden_dependencies.join(", ") + "]"),
file
file.path
));
}

Ok(())
}

fn is_applicable(&self, file: &str) -> bool {
fn is_applicable(&self, file: &RustFile) -> bool {
let orange = Style::new().bold().fg(ansi_term::Color::RGB(255, 165, 0));
let green = Style::new().bold().fg(ansi_term::Color::RGB(0, 255, 0));
let module = get_module(file).unwrap();
debug!(
"File {} mapped to module {}",
green.paint(file),
orange.paint(&module)
green.paint(&file.path),
orange.paint(&file.logical_path)
);
module.is_child_of(&self.subject)
file.logical_path.is_child_of(&self.subject)
}
}

Expand All @@ -100,8 +92,9 @@ mod tests {
allowed_dependencies: vec!["conversion::domain::domain_function_1".to_string()],
};

let result =
rule.apply("./../rust_arkitect/examples/sample_project/src/conversion/application.rs");
let result = rule.apply(&RustFile::from(
"./../rust_arkitect/examples/sample_project/src/conversion/application.rs",
));

assert!(result.is_err());
}
Expand Down
29 changes: 15 additions & 14 deletions src/rules/must_not_depend_on.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::dependency_parsing::{get_dependencies_in_file, get_module};
use crate::rules::rule::Rule;
use crate::dependency_parsing::get_dependencies_in_file;
use crate::rules::rule::{Rule, RustFile};
use crate::rules::utils::IsChild;
use ansi_term::Color::RGB;
use ansi_term::Style;
Expand Down Expand Up @@ -44,8 +44,8 @@ impl Display for MustNotDependOnRule {
}

impl Rule for MustNotDependOnRule {
fn apply(&self, file: &str) -> Result<(), String> {
let dependencies = get_dependencies_in_file(file);
fn apply(&self, file: &RustFile) -> Result<(), String> {
let dependencies = get_dependencies_in_file(&file.path);

let forbidden_dependencies: Vec<String> = dependencies
.iter()
Expand All @@ -62,23 +62,22 @@ impl Rule for MustNotDependOnRule {
return Err(format!(
"Forbidden dependencies to {} in file://{}",
red.paint("[".to_string() + &forbidden_dependencies.join(", ") + "]"),
file
file.path
));
}

Ok(())
}

fn is_applicable(&self, file: &str) -> bool {
fn is_applicable(&self, file: &RustFile) -> bool {
let orange = Style::new().bold().fg(RGB(255, 165, 0));
let green = Style::new().bold().fg(RGB(0, 255, 0));
let module = get_module(file).unwrap();
debug!(
"File {} mapped to module {}",
green.paint(file),
orange.paint(&module)
green.paint(&file.path),
orange.paint(&file.logical_path)
);
module.is_child_of(&self.subject)
file.logical_path.is_child_of(&self.subject)
}
}

Expand All @@ -93,8 +92,9 @@ mod tests {
forbidden_dependencies: vec!["sample_project::contracts".to_string()],
};

let result =
rule.apply("./../rust_arkitect/examples/sample_project/src/conversion/application.rs");
let result = rule.apply(&RustFile::from(
"./../rust_arkitect/examples/sample_project/src/conversion/application.rs",
));

assert!(result.is_err());
}
Expand All @@ -106,8 +106,9 @@ mod tests {
forbidden_dependencies: vec!["sample_project::policy_management".to_string()],
};

let result =
rule.apply("./../rust_arkitect/examples/sample_project/src/conversion/application.rs");
let result = rule.apply(&RustFile::from(
"./../rust_arkitect/examples/sample_project/src/conversion/application.rs",
));

assert!(result.is_ok());
}
Expand Down
14 changes: 7 additions & 7 deletions src/rules/must_not_depend_on_anything.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::dependency_parsing::{get_dependencies_in_file, get_module};
use crate::rules::rule::Rule;
use crate::dependency_parsing::get_dependencies_in_file;
use crate::rules::rule::{Rule, RustFile};
use crate::rules::utils::IsChild;
use ansi_term::Color::RGB;
use ansi_term::Style;
Expand Down Expand Up @@ -34,8 +34,8 @@
}

impl Rule for MustNotDependOnAnythingRule {
fn apply(&self, file: &str) -> Result<(), String> {
let dependencies = get_dependencies_in_file(file);
fn apply(&self, file: &RustFile) -> Result<(), String> {
let dependencies = get_dependencies_in_file(&file.path);

Check warning on line 38 in src/rules/must_not_depend_on_anything.rs

View check run for this annotation

Codecov / codecov/patch

src/rules/must_not_depend_on_anything.rs#L37-L38

Added lines #L37 - L38 were not covered by tests

let forbidden_dependencies: Vec<String> = dependencies
.iter()
Expand All @@ -56,13 +56,13 @@
Err(format!(
"Forbidden dependencies to {} in file://{}",
red.paint("[".to_string() + &forbidden_dependencies.join(", ") + "]"),
file
file.path
))
}
}

fn is_applicable(&self, file: &str) -> bool {
get_module(file).unwrap().is_child_of(&self.subject)
fn is_applicable(&self, file: &RustFile) -> bool {
file.logical_path.is_child_of(&self.subject)

Check warning on line 65 in src/rules/must_not_depend_on_anything.rs

View check run for this annotation

Codecov / codecov/patch

src/rules/must_not_depend_on_anything.rs#L64-L65

Added lines #L64 - L65 were not covered by tests
}
}

Expand Down
Loading
Loading