Skip to main content

miniextendr_lint/
lint_code.rs

1//! Stable lint rule identifiers.
2//!
3//! Each rule has a code like `MXL008` that is grep-able and CI-friendly.
4
5use std::fmt;
6
7/// Stable lint rule identifier.
8///
9/// Display format is `MXL###`, derived directly from the variant name.
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
11pub enum LintCode {
12    // region: Source-side validation
13    /// Trait impl class system incompatible with inherent impl class system.
14    MXL008,
15    /// Multiple impl blocks for one type without labels.
16    MXL009,
17    /// Duplicate labels on impl blocks for one type.
18    MXL010,
19    // endregion
20
21    // region: P0: High Impact
22    /// Registered top-level function is not `pub`.
23    MXL106,
24    /// Parameter name is an R reserved word; codegen will produce invalid R syntax.
25    MXL110,
26    /// `s4_*` method name on `#[miniextendr(s4)]` impl — codegen auto-prepends `s4_`.
27    MXL111,
28    /// Explicit lifetime parameter on `#[miniextendr]` fn or impl — use owned types instead.
29    MXL112,
30    /// vctrs constructor returns `Self` / named type, or impl has an instance-method receiver.
31    ///
32    /// Mirror: `miniextendr-macros/src/miniextendr_impl.rs` (proc-macro hard error).
33    /// Both checks must fire on the same source; keep them in sync.
34    MXL120,
35    // endregion
36
37    // region: P1: Important
38    /// `internal` + `noexport` redundancy.
39    MXL203,
40    // endregion
41
42    // region: P2: Safety
43    /// Direct `Rf_error`/`Rf_errorcall` call in user code.
44    MXL300,
45    /// `_unchecked` FFI call outside guard context.
46    MXL301,
47    /// Non-doc attribute interrupts a doc-comment stream on a `#[miniextendr]` item.
48    ///
49    /// When a `#[cfg(...)]`, `#[deprecated]`, or other non-doc attribute splits two
50    /// `///` runs, trailing prose can be incorrectly concatenated into the preceding
51    /// `@examples` / `@details` / `@return` block, producing corrupted Rd output.
52    /// The macro now resets multiline-continuation context at the interruption point,
53    /// but the warning guides users to move all `///` comments above such attributes.
54    MXL302,
55    // endregion
56}
57
58impl fmt::Display for LintCode {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        // Variant names are already `MXL###`, so Debug output works.
61        fmt::Debug::fmt(self, f)
62    }
63}
64
65impl LintCode {
66    /// Default severity for this rule.
67    pub fn default_severity(self) -> super::diagnostic::Severity {
68        use super::diagnostic::Severity;
69        match self {
70            // Source-side checks are errors (CI-blocking).
71            Self::MXL008 | Self::MXL009 | Self::MXL010 => Severity::Error,
72
73            // Codegen-breaking: reserved words produce syntactically invalid R wrappers.
74            Self::MXL110 => Severity::Error,
75
76            // Runtime-breaking: vctrs constructors returning Self produce EXTPTRSXP
77            // which vctrs::new_vctr() rejects; instance-method receivers panic at runtime.
78            Self::MXL120 => Severity::Error,
79
80            // Everything else is a warning.
81            Self::MXL106
82            | Self::MXL111
83            | Self::MXL112
84            | Self::MXL203
85            | Self::MXL300
86            | Self::MXL301
87            | Self::MXL302 => Severity::Warning,
88        }
89    }
90}