feat: implement all P1/P2/P3/P4 improvements from issue backlog
P1 correctness: - filter test files by default (--include-tests to opt in) - per-module diagrams show cross-module dependency arrows - qualified type names (Module::TypeName) fix false edges from duplicate names P2 output richness: - method parameter types and return types in class diagrams (Rust + Python) - Python pyproject.toml project analyzer (--level project for monorepos) P3 unique value: - boundary rules in archlens.toml ([rules] allow/deny, --strict enforcement) P4 nice to have: - dependency weight labels on module arrows (--no-weights to disable) - --watch mode with 500ms debounce - D2 renderer adapter (--format d2) - interactive self-contained HTML viewer (--format html) - git-aware incremental analysis (--since <ref>)
This commit is contained in:
@@ -128,3 +128,145 @@ fn extracts_mod_declarations() {
|
||||
assert!(imports.iter().any(|r| r.target() == "crate::models"));
|
||||
assert!(imports.iter().any(|r| r.target() == "crate::services"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_rust_method_with_typed_params() {
|
||||
let source = r#"
|
||||
pub struct OrderService;
|
||||
impl OrderService {
|
||||
pub fn process(&self, order: Order, count: u64) {}
|
||||
}
|
||||
"#;
|
||||
let result = analyze_rust(source, "service.rs");
|
||||
|
||||
let element = result
|
||||
.elements()
|
||||
.iter()
|
||||
.find(|e| e.name() == "OrderService")
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
element
|
||||
.methods()
|
||||
.iter()
|
||||
.any(|m| m.contains("order: Order") && m.contains("count: u64")),
|
||||
"expected typed params in method, got: {:?}",
|
||||
element.methods()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_rust_method_return_type() {
|
||||
let source = r#"
|
||||
pub struct OrderService;
|
||||
impl OrderService {
|
||||
pub fn get(&self) -> Order {}
|
||||
}
|
||||
"#;
|
||||
let result = analyze_rust(source, "service.rs");
|
||||
|
||||
let element = result
|
||||
.elements()
|
||||
.iter()
|
||||
.find(|e| e.name() == "OrderService")
|
||||
.unwrap();
|
||||
|
||||
assert!(
|
||||
element.methods().iter().any(|m| m.contains("-> Order")),
|
||||
"expected return type in method, got: {:?}",
|
||||
element.methods()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_rust_method_params_and_return() {
|
||||
let source = r#"
|
||||
pub struct OrderService;
|
||||
impl OrderService {
|
||||
pub fn process(&self, order: Order) -> Result<(), Error> {}
|
||||
}
|
||||
"#;
|
||||
let result = analyze_rust(source, "service.rs");
|
||||
|
||||
let element = result
|
||||
.elements()
|
||||
.iter()
|
||||
.find(|e| e.name() == "OrderService")
|
||||
.unwrap();
|
||||
|
||||
let method = element
|
||||
.methods()
|
||||
.iter()
|
||||
.find(|m| m.contains("process"))
|
||||
.unwrap();
|
||||
assert!(method.contains("order: Order"), "missing param: {method}");
|
||||
assert!(method.contains("->"), "missing return arrow: {method}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_rust_static_method_params() {
|
||||
let source = r#"
|
||||
pub struct Finder;
|
||||
impl Finder {
|
||||
pub fn detect(path: &str, count: usize) -> bool { false }
|
||||
}
|
||||
"#;
|
||||
let result = analyze_rust(source, "finder.rs");
|
||||
let element = result
|
||||
.elements()
|
||||
.iter()
|
||||
.find(|e| e.name() == "Finder")
|
||||
.unwrap();
|
||||
let method = element
|
||||
.methods()
|
||||
.iter()
|
||||
.find(|m| m.contains("detect"))
|
||||
.unwrap();
|
||||
assert!(method.contains("path"), "missing path param: {method}");
|
||||
assert!(method.contains("count"), "missing count param: {method}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_rust_private_method_params() {
|
||||
let source = r#"
|
||||
pub struct WalkdirDiscovery;
|
||||
impl WalkdirDiscovery {
|
||||
fn detect_language(path: &std::path::Path) -> Option<String> { None }
|
||||
}
|
||||
"#;
|
||||
let result = analyze_rust(source, "discovery.rs");
|
||||
let element = result
|
||||
.elements()
|
||||
.iter()
|
||||
.find(|e| e.name() == "WalkdirDiscovery")
|
||||
.unwrap();
|
||||
let method = element
|
||||
.methods()
|
||||
.iter()
|
||||
.find(|m| m.contains("detect_language"))
|
||||
.unwrap();
|
||||
assert!(method.contains("path"), "missing path param: {method}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_rust_method_reference_param() {
|
||||
let source = r#"
|
||||
use std::path::Path;
|
||||
pub struct WalkdirDiscovery;
|
||||
impl WalkdirDiscovery {
|
||||
fn detect_language(path: &Path) -> Option<String> { None }
|
||||
}
|
||||
"#;
|
||||
let result = analyze_rust(source, "discovery.rs");
|
||||
let element = result
|
||||
.elements()
|
||||
.iter()
|
||||
.find(|e| e.name() == "WalkdirDiscovery")
|
||||
.unwrap();
|
||||
let method = element
|
||||
.methods()
|
||||
.iter()
|
||||
.find(|m| m.contains("detect_language"))
|
||||
.unwrap();
|
||||
assert!(method.contains("path"), "missing path param: {method}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user