Skip to main content

ferrous_forge/standards/
implementation.rs

1//! Implementation of coding standards methods
2
3use super::types::*;
4use crate::Result;
5
6impl CodingStandards {
7    /// Load standards from configuration
8    ///
9    /// # Errors
10    ///
11    /// Currently infallible, but returns `Result` for future configuration loading.
12    pub fn load() -> Result<Self> {
13        // For now, return defaults
14        // TODO: Load from configuration file or remote source
15        Ok(Self::default())
16    }
17
18    /// Save standards to configuration
19    ///
20    /// # Errors
21    ///
22    /// Currently infallible, but returns `Result` for future configuration saving.
23    pub fn save(&self) -> Result<()> {
24        // TODO: Save to configuration file
25        Ok(())
26    }
27
28    /// Get all clippy rules based on these standards
29    pub fn get_clippy_rules(&self) -> Vec<String> {
30        let mut rules = vec!["-D warnings".to_string()];
31
32        if self.banned_patterns.ban_unwrap {
33            rules.push("-D clippy::unwrap_used".to_string());
34        }
35
36        if self.banned_patterns.ban_expect {
37            rules.push("-D clippy::expect_used".to_string());
38        }
39
40        if self.banned_patterns.ban_panic {
41            rules.push("-D clippy::panic".to_string());
42        }
43
44        if self.banned_patterns.ban_todo {
45            rules.push("-D clippy::todo".to_string());
46        }
47
48        if self.banned_patterns.ban_unimplemented {
49            rules.push("-D clippy::unimplemented".to_string());
50        }
51
52        if self.documentation.require_public_docs {
53            rules.push("-D missing_docs".to_string());
54        }
55
56        if self.security.ban_unsafe {
57            // `-D` (deny), not `-F` (forbid), so FFI crates (napi-rs, wasm-bindgen, PyO3)
58            // can `#[allow(unsafe_code)]` where macros require it. forbid breaks E0453.
59            rules.push("-D unsafe_code".to_string());
60        }
61
62        // Add performance and style lints
63        rules.extend([
64            "-W clippy::pedantic".to_string(),
65            "-W clippy::nursery".to_string(),
66            "-W clippy::cargo".to_string(),
67            "-D clippy::dbg_macro".to_string(),
68            "-D clippy::print_stdout".to_string(),
69            "-D clippy::print_stderr".to_string(),
70        ]);
71
72        rules
73    }
74
75    /// Generate clippy.toml configuration
76    pub fn generate_clippy_config(&self) -> String {
77        format!(
78            r#"# Ferrous Forge - Rust Standards Enforcement
79# Generated automatically - do not edit manually
80
81msrv = "{}"
82max-fn-params-bools = 2
83max-struct-bools = 2
84max-trait-bounds = 2
85max-include-file-size = {}
86min-ident-chars-threshold = 2
87literal-representation-threshold = 1000
88check-private-items = {}
89missing-docs-allow-unused = false
90allow-comparison-to-zero = false
91allow-mixed-uninlined-format-args = false
92allow-one-hash-in-raw-strings = false
93allow-useless-vec-in-tests = false
94allow-indexing-slicing-in-tests = false
95allowed-idents-below-min-chars = ["i", "j", "x", "y", "z"]
96allowed-wildcard-imports = []
97allow-exact-repetitions = false
98allow-private-module-inception = false
99too-large-for-stack = 100
100upper-case-acronyms-aggressive = true
101allowed-scripts = ["Latin"]
102disallowed-names = ["foo", "bar", "baz", "qux", "quux", "test", "tmp", "temp"]
103unreadable-literal-lint-fractions = true
104semicolon-inside-block-ignore-singleline = false
105semicolon-outside-block-ignore-multiline = false
106arithmetic-side-effects-allowed = []
107"#,
108            self.edition.min_rust_version,
109            self.file_limits.max_lines * 1000, // Convert to bytes approximation
110            self.documentation.require_private_docs,
111        )
112    }
113
114    /// Check if a project complies with these standards
115    ///
116    /// # Errors
117    ///
118    /// Returns an error if reading `Cargo.toml` fails.
119    pub async fn check_compliance(&self, project_path: &std::path::Path) -> Result<Vec<String>> {
120        let mut violations = Vec::new();
121
122        // Check Cargo.toml for edition
123        let cargo_toml = project_path.join("Cargo.toml");
124        if cargo_toml.exists() {
125            let content = tokio::fs::read_to_string(&cargo_toml).await?;
126            if !content.contains(&format!(r#"edition = "{}""#, self.edition.required_edition)) {
127                violations.push(format!(
128                    "Project must use Rust Edition {}",
129                    self.edition.required_edition
130                ));
131            }
132        }
133
134        // Additional compliance checks would go here
135
136        Ok(violations)
137    }
138}