Some checks failed
CI / Check / Test (push) Failing after 1m24s
Hex arch + DDD, tree-sitter parsing, Mermaid/ASCII output. Supports Rust + Python. 92 tests. CI, diff, --check for staleness detection.
131 lines
4.0 KiB
Rust
131 lines
4.0 KiB
Rust
use archlens_domain::{
|
|
CodeElementKind, FilePath, Language, RelationshipKind, SourceFile, ports::SourceAnalyzer,
|
|
};
|
|
use archlens_tree_sitter::TreeSitterAnalyzer;
|
|
|
|
fn analyze_rust(source: &str, filename: &str) -> archlens_domain::AnalysisResult {
|
|
let dir = tempfile::tempdir().unwrap();
|
|
let file_path = dir.path().join(filename);
|
|
std::fs::write(&file_path, source).unwrap();
|
|
|
|
let analyzer = TreeSitterAnalyzer::new();
|
|
let source_file = SourceFile::new(
|
|
FilePath::new(file_path.to_str().unwrap()).unwrap(),
|
|
Language::Rust,
|
|
);
|
|
analyzer.analyze_file(&source_file).unwrap()
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_rust_struct() {
|
|
let result = analyze_rust("pub struct Order {\n id: u64,\n}", "order.rs");
|
|
|
|
assert_eq!(result.elements().len(), 1);
|
|
assert_eq!(result.elements()[0].name(), "Order");
|
|
assert_eq!(result.elements()[0].kind(), CodeElementKind::Struct);
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_rust_enum() {
|
|
let result = analyze_rust(
|
|
"pub enum Status {\n Active,\n Inactive,\n}",
|
|
"status.rs",
|
|
);
|
|
|
|
assert_eq!(result.elements().len(), 1);
|
|
assert_eq!(result.elements()[0].name(), "Status");
|
|
assert_eq!(result.elements()[0].kind(), CodeElementKind::Enum);
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_rust_trait() {
|
|
let result = analyze_rust("pub trait Repository {\n fn find(&self);\n}", "repo.rs");
|
|
|
|
assert_eq!(result.elements().len(), 1);
|
|
assert_eq!(result.elements()[0].name(), "Repository");
|
|
assert_eq!(result.elements()[0].kind(), CodeElementKind::Trait);
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_composition_from_struct_fields() {
|
|
let source =
|
|
"pub struct Order {\n id: u64,\n}\npub struct OrderService {\n order: Order,\n}";
|
|
let result = analyze_rust(source, "service.rs");
|
|
|
|
assert_eq!(result.elements().len(), 2);
|
|
assert_eq!(result.relationships().len(), 1);
|
|
assert_eq!(result.relationships()[0].source(), "OrderService");
|
|
assert_eq!(result.relationships()[0].target(), "Order");
|
|
assert_eq!(
|
|
result.relationships()[0].kind(),
|
|
RelationshipKind::Composition
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_inheritance_from_trait_impl() {
|
|
let source = "pub trait Printable {}\npub struct Order {}\nimpl Printable for Order {}";
|
|
let result = analyze_rust(source, "order.rs");
|
|
|
|
let inheritance: Vec<_> = result
|
|
.relationships()
|
|
.iter()
|
|
.filter(|r| r.kind() == RelationshipKind::Inheritance)
|
|
.collect();
|
|
|
|
assert_eq!(inheritance.len(), 1);
|
|
assert_eq!(inheritance[0].source(), "Order");
|
|
assert_eq!(inheritance[0].target(), "Printable");
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_use_imports() {
|
|
let source =
|
|
"use crate::domain::Order;\nuse crate::ports::Repository;\n\npub struct Service {}";
|
|
let result = analyze_rust(source, "service.rs");
|
|
|
|
let imports: Vec<_> = result
|
|
.relationships()
|
|
.iter()
|
|
.filter(|r| r.kind() == RelationshipKind::Import)
|
|
.collect();
|
|
|
|
assert!(imports.iter().any(|r| r.target() == "crate::domain::Order"));
|
|
assert!(
|
|
imports
|
|
.iter()
|
|
.any(|r| r.target() == "crate::ports::Repository")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn filters_std_and_external_crate_imports() {
|
|
let source =
|
|
"use std::collections::HashMap;\nuse serde::Serialize;\nuse crate::models::Order;\n";
|
|
let result = analyze_rust(source, "lib.rs");
|
|
|
|
let imports: Vec<_> = result
|
|
.relationships()
|
|
.iter()
|
|
.filter(|r| r.kind() == RelationshipKind::Import)
|
|
.collect();
|
|
|
|
assert_eq!(imports.len(), 1);
|
|
assert_eq!(imports[0].target(), "crate::models::Order");
|
|
}
|
|
|
|
#[test]
|
|
fn extracts_mod_declarations() {
|
|
let source = "mod models;\nmod services;\npub struct App {}";
|
|
let result = analyze_rust(source, "lib.rs");
|
|
|
|
let imports: Vec<_> = result
|
|
.relationships()
|
|
.iter()
|
|
.filter(|r| r.kind() == RelationshipKind::Import)
|
|
.collect();
|
|
|
|
assert!(imports.iter().any(|r| r.target() == "crate::models"));
|
|
assert!(imports.iter().any(|r| r.target() == "crate::services"));
|
|
}
|