Skip to main content

miniextendr_lint/
rules.rs

1//! Lint rule implementations.
2//!
3//! Each submodule contains one or more related lint checks. All rules operate
4//! on the shared [`CrateIndex`] and produce
5//! [`Diagnostic`] values.
6
7pub mod export_attrs;
8pub mod ffi_unchecked;
9pub mod fn_visibility;
10pub mod impl_validation;
11pub mod r_reserved_params;
12pub mod rf_error;
13pub mod s4_method_prefix;
14pub mod trait_tag_collision;
15pub mod vctrs_self_ctor;
16pub mod vec_into_sexp;
17
18use crate::crate_index::CrateIndex;
19use crate::diagnostic::Diagnostic;
20
21/// Run all lint rules against the crate index, collecting diagnostics.
22pub fn run_all_rules(index: &CrateIndex) -> Vec<Diagnostic> {
23    let mut diagnostics = Vec::new();
24
25    // Per-file impl validation (MXL008, MXL009, MXL010)
26    impl_validation::check(index, &mut diagnostics);
27
28    // Per-file: function visibility (MXL106)
29    fn_visibility::check(index, &mut diagnostics);
30
31    // Per-file: export attr redundancy (MXL203)
32    export_attrs::check(index, &mut diagnostics);
33
34    // Per-file: R reserved words as parameter names (MXL110)
35    r_reserved_params::check(index, &mut diagnostics);
36
37    // Per-file: direct Rf_error/Rf_errorcall usage (MXL300)
38    rf_error::check(index, &mut diagnostics);
39
40    // Per-file: sys::*_unchecked() usage (MXL301)
41    ffi_unchecked::check(index, &mut diagnostics);
42
43    // Per-file: into_sexp() inside a vec!/array literal (MXL302)
44    vec_into_sexp::check(index, &mut diagnostics);
45
46    // Per-file: s4_* method name on #[miniextendr(s4)] impl (MXL111)
47    s4_method_prefix::check(index, &mut diagnostics);
48
49    // Per-file: vctrs ctor returns Self / instance receiver on vctrs impl (MXL120)
50    vctrs_self_ctor::check(index, &mut diagnostics);
51
52    // Crate-wide: trait-impl vtable-symbol collisions via case-folding (MXL303)
53    trait_tag_collision::check(index, &mut diagnostics);
54
55    // Sort by path and line for deterministic output
56    diagnostics.sort_by(|a, b| {
57        a.path
58            .cmp(&b.path)
59            .then(a.line.cmp(&b.line))
60            .then(a.code.cmp(&b.code))
61    });
62
63    diagnostics
64}