//! cargo-constitution: Rust编译器Lint插件 //! //! 在编译期验证Rust代码是否符合NAC宪法约束 pub mod lints; pub mod utils; pub use lints::{LintRunner, LintViolation, Severity, ConstitutionalParameter, Obligation}; pub use utils::{load_constitutional_state, find_constitutional_state_file}; use std::path::Path; use walkdir::WalkDir; /// 检查项目中的所有Rust文件 pub fn check_project>(project_dir: P) -> Result, String> { // 1. 查找宪法状态文件 let state_file = find_constitutional_state_file(&project_dir) .ok_or("Constitutional state file not found")?; // 2. 加载宪法状态 let state = load_constitutional_state(&state_file)?; // 3. 转换参数格式 let parameters: Vec = state .parameters .iter() .map(|p| ConstitutionalParameter { name: p.name.clone(), value: p.value.to_string().trim_matches('"').to_string(), rust_type: p.rust_type.clone(), clause: p.clause.clone(), }) .collect(); // 4. 提取条款列表 let clauses: Vec = state.clauses.iter().map(|c| c.id.clone()).collect(); // 5. 提取义务列表(简化处理) let obligations: Vec = vec![]; // 6. 创建lint运行器 let runner = LintRunner::new(parameters, clauses, obligations); // 7. 遍历所有Rust文件 let mut all_violations = Vec::new(); for entry in WalkDir::new(&project_dir) .into_iter() .filter_map(|e| e.ok()) .filter(|e| e.path().extension().map_or(false, |ext| ext == "rs")) { let path = entry.path(); if let Ok(source) = std::fs::read_to_string(path) { let violations = runner.run(&source, path.to_str().expect("mainnet: handle error")); all_violations.extend(violations); } } Ok(all_violations) } #[cfg(test)] mod tests { use super::*; #[test] fn test_lint_runner() { let params = vec![ConstitutionalParameter { name: "TEST_PARAM".to_string(), value: "42".to_string(), rust_type: "u64".to_string(), clause: "TEST_CLAUSE".to_string(), }]; let clauses = vec!["TEST_CLAUSE".to_string()]; let obligations = vec![]; let runner = LintRunner::new(params, clauses, obligations); let source = "let x = 42;"; let violations = runner.run(source, "test.rs"); assert_eq!(violations.len(), 1); } }