use super::*;
pub(crate) const ARCHITECTURE_RULES: &[RuleDefinition] = &[
rule_definition!(
"architecture.large-module",
"Large module",
Pillar::Design,
RuleKind::Project,
Severity::Advisory,
Confidence::High,
ARCHITECTURE_LARGE_MODULE_THRESHOLD,
"Flags modules with more indexed items than the configured threshold.",
),
rule_definition!(
"architecture.module-fan-out",
"Module fan-out",
Pillar::Design,
RuleKind::Project,
Severity::Advisory,
Confidence::High,
ARCHITECTURE_MODULE_FAN_OUT_THRESHOLD,
"Flags files that declare many child modules.",
),
rule_definition!(
"architecture.public-api-surface",
"Public API surface",
Pillar::Design,
RuleKind::Project,
Severity::Advisory,
Confidence::High,
ARCHITECTURE_PUBLIC_API_SURFACE_THRESHOLD,
"Flags modules with many public exports.",
),
];
pub(crate) const COMPLEXITY_RULES: &[RuleDefinition] = &[
rule_definition!(
"complexity.cognitive",
"Cognitive complexity",
Pillar::Complexity,
RuleKind::Rust,
Severity::Warning,
Confidence::High,
COMPLEXITY_COGNITIVE_THRESHOLD,
"Flags functions with high cognitive complexity.",
false_positives: &[
FalsePositiveShape {
shape: "Match-heavy dispatch functions whose cognitive load is one nested `match` per CLI subcommand or AST node.",
mitigation: "Raise `rules.complexity.cognitive.threshold` in `.gruff-rs.yaml`, or extract per-arm helpers.",
},
],
related: &[
"complexity.cyclomatic",
"complexity.nesting-depth",
],
),
rule_definition!(
"complexity.cyclomatic",
"Cyclomatic complexity",
Pillar::Complexity,
RuleKind::Rust,
Severity::Warning,
Confidence::High,
COMPLEXITY_CYCLOMATIC_THRESHOLD,
"Flags functions with high branch and decision complexity.",
),
rule_definition!(
"complexity.nesting-depth",
"Nesting depth",
Pillar::Complexity,
RuleKind::Rust,
Severity::Warning,
Confidence::High,
COMPLEXITY_NESTING_DEPTH_THRESHOLD,
"Flags functions with deeply nested control flow.",
),
];
pub(crate) const DEAD_CODE_RULES: &[RuleDefinition] = &[
rule_definition!(
"dead-code.unused-private-function",
"Unused private function",
Pillar::DeadCode,
RuleKind::Rust,
Severity::Advisory,
Confidence::Low,
None,
"Flags private functions with no same-file call sites.",
),
rule_definition!(
"dead-code.unused-private-item-candidate",
"Unused private item candidate",
Pillar::DeadCode,
RuleKind::Project,
Severity::Advisory,
Confidence::Medium,
None,
"Flags private items whose names are not referenced elsewhere in discovered Rust sources.",
false_positives: &[
FalsePositiveShape {
shape: "Items referenced only via macros or via a build-script-generated file the discovery layer did not see (e.g. proc-macro-generated names).",
mitigation: "Add the generating path to `paths.ignore` in `.gruff-rs.yaml`, or document with an `exclude:` entry naming the path.",
},
FalsePositiveShape {
shape: "Narrow path or diff runs that do not cover every discoverable Rust source under the selected project root cannot prove an item is unused across the crate.",
mitigation: "The rule is suppressed on partial-context runs with a `partial-context-rule-suppressed` diagnostic; run `gruff-rs analyse .` from the selected project root for authoritative dead-code signal.",
},
FalsePositiveShape {
shape: "Items exported through FFI/plugin attributes or explicitly kept with `#[allow(dead_code)]`.",
mitigation: "The rule skips `#[no_mangle]`, `#[export_name]`, `#[pymodule]`, `#[pyfunction]`, and explicit `allow(dead_code)` contexts; use those only where the external entry point or macro contract is real.",
},
],
related: &["dead-code.unused-private-function"],
),
];
pub(crate) const DEPENDENCY_RULES: &[RuleDefinition] = &[
rule_definition!(
"dependency.duplicate-locked-version",
"Duplicate locked dependency version",
Pillar::Security,
RuleKind::Project,
Severity::Advisory,
Confidence::High,
DEPENDENCY_DUPLICATE_LOCKED_VERSION_THRESHOLD,
"Flags packages locked at more versions than the configured threshold.",
),
rule_definition!(
"dependency.git-source",
"Git dependency source",
Pillar::Security,
RuleKind::Project,
Severity::Warning,
Confidence::High,
None,
"Flags dependencies sourced directly from git repositories.",
),
rule_definition!(
"dependency.git-unpinned-revision",
"Git dependency without fixed revision",
Pillar::Security,
RuleKind::Project,
Severity::Warning,
Confidence::High,
None,
"Flags git dependencies that do not pin a fixed rev.",
),
rule_definition!(
"dependency.missing-package-metadata",
"Missing package metadata",
Pillar::Documentation,
RuleKind::Project,
Severity::Advisory,
Confidence::High,
None,
"Flags packages missing description or license metadata.",
),
rule_definition!(
"dependency.path-source",
"Path dependency source",
Pillar::Security,
RuleKind::Project,
Severity::Advisory,
Confidence::High,
None,
"Flags dependencies sourced from local filesystem paths.",
),
rule_definition!(
"dependency.wildcard-version",
"Wildcard dependency version",
Pillar::Security,
RuleKind::Project,
Severity::Warning,
Confidence::High,
None,
"Flags dependency requirements that use wildcard versions.",
),
];
pub(crate) const DOCUMENTATION_AND_DESIGN_RULES: &[RuleDefinition] = &[
rule_definition!(
"docs.missing-public-doc",
"Missing public documentation",
Pillar::Documentation,
RuleKind::Rust,
Severity::Advisory,
Confidence::Medium,
None,
"Flags public Rust API items without doc comments.",
),
rule_definition!(
"docs.missing-readme",
"Missing README",
Pillar::Documentation,
RuleKind::Project,
Severity::Advisory,
Confidence::High,
None,
"Flags projects without a root README file.",
),
rule_definition!(
"docs.stale-todo",
"Stale TODO marker",
Pillar::Documentation,
RuleKind::Rust,
Severity::Advisory,
Confidence::High,
None,
"Flags TODO/FIXME/HACK/XXX comments without an owner, issue reference, or reason.",
),
rule_definition!(
"docs.commented-out-code",
"Commented-out code",
Pillar::Documentation,
RuleKind::Rust,
Severity::Advisory,
Confidence::Medium,
None,
"Flags comments whose payload looks like a disabled Rust statement or item.",
),
rule_definition!(
"docs.weak-safety-rationale",
"Weak SAFETY rationale",
Pillar::Documentation,
RuleKind::Rust,
Severity::Advisory,
Confidence::Medium,
None,
"Flags unsafe blocks whose nearby SAFETY: rationale is too short or vague.",
),
rule_definition!(
"docs.missing-errors-section",
"Missing # Errors rustdoc section",
Pillar::Documentation,
RuleKind::Rust,
Severity::Advisory,
Confidence::High,
None,
"Flags externally public functions returning Result without a # Errors rustdoc section.",
),
rule_definition!(
"docs.missing-panics-section",
"Missing # Panics rustdoc section",
Pillar::Documentation,
RuleKind::Rust,
Severity::Advisory,
Confidence::High,
None,
"Flags public functions containing panic!/unwrap/expect without a # Panics rustdoc section.",
),
rule_definition!(
"docs.missing-safety-section",
"Missing # Safety rustdoc section",
Pillar::Documentation,
RuleKind::Rust,
Severity::Warning,
Confidence::High,
None,
"Flags public `unsafe fn` / `unsafe trait` items without a # Safety rustdoc section.",
),
rule_definition!(
"docs.missing-param-doc",
"Missing parameter rustdoc",
Pillar::Documentation,
RuleKind::Rust,
Severity::Advisory,
Confidence::Medium,
None,
"Flags public functions whose rustdoc lacks per-parameter documentation.",
),
rule_definition!(
"docs.missing-return-doc",
"Missing return rustdoc",
Pillar::Documentation,
RuleKind::Rust,
Severity::Advisory,
Confidence::Medium,
None,
"Flags public functions returning a value whose rustdoc lacks a Returns description.",
),
];
pub(crate) const CONCURRENCY_RULES: &[RuleDefinition] = &[
rule_definition!(
"concurrency.blocking-call-in-async",
"Blocking call in async function",
Pillar::Maintainability,
RuleKind::Rust,
Severity::Warning,
Confidence::Medium,
None,
"Flags narrow blocking call patterns inside async functions.",
),
rule_definition!(
"concurrency.lock-across-await",
"Lock guard across await",
Pillar::Maintainability,
RuleKind::Rust,
Severity::Warning,
Confidence::Medium,
None,
"Flags lock guard bindings that appear to live across an await point.",
false_positives: &[
FalsePositiveShape {
shape: "Bindings that extract a value from the guard immediately, such as `.lock().await.take()`, before any later await.",
mitigation: "Keep the extraction chained on the lock expression or explicitly drop the guard before awaiting; the rule only tracks bindings that still represent the guard.",
},
],
related: &["concurrency.blocking-call-in-async", "concurrency.unbounded-channel"],
),
rule_definition!(
"concurrency.unbounded-channel",
"Unbounded channel",
Pillar::Maintainability,
RuleKind::Rust,
Severity::Advisory,
Confidence::Medium,
None,
"Flags unbounded channel constructors in production code.",
),
];
pub(crate) const ERROR_HANDLING_RULES: &[RuleDefinition] = &[
rule_definition!(
"error-handling.production-panic",
"Production panic",
Pillar::Maintainability,
RuleKind::Rust,
Severity::Warning,
Confidence::High,
None,
"Flags panic! calls in non-test functions without a local invariant comment.",
),
rule_definition!(
"error-handling.public-unwrap",
"Public API unwrap",
Pillar::Maintainability,
RuleKind::Rust,
Severity::Warning,
Confidence::High,
None,
"Flags unwrap or expect calls in public non-test functions.",
),
rule_definition!(
"error-handling.unimplemented-placeholder",
"Unimplemented placeholder",
Pillar::Maintainability,
RuleKind::Rust,
Severity::Warning,
Confidence::High,
None,
"Flags todo! and unimplemented! placeholders in non-test functions.",
),
];