Skip to main content

mib_rs/types/
diagcode.rs

1//! Diagnostic code definitions.
2//!
3//! Each [`DiagCode`] variant identifies a specific diagnostic condition with a
4//! fixed [`Severity`] and pipeline phase. Codes use stable kebab-case string
5//! representations for configuration and filtering.
6
7use super::Severity;
8
9macro_rules! diag_codes {
10    ( $( $phase:ident, $variant:ident, $code:literal, $severity:ident; )* ) => {
11        /// Identifies a specific diagnostic condition.
12        ///
13        /// Each code has a fixed [`Severity`] and belongs to a pipeline phase
14        /// (lexer, parser, lower, or resolver). Use [`DiagCode::as_code`] for the
15        /// stable kebab-case string representation.
16        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17        pub enum DiagCode {
18            $( $variant, )*
19        }
20
21        impl DiagCode {
22            /// Returns the stable kebab-case string representation (e.g. `"parse-error"`).
23            pub fn as_code(self) -> &'static str {
24                match self {
25                    $( DiagCode::$variant => $code, )*
26                }
27            }
28
29            /// Parses a kebab-case code string into a [`DiagCode`], returning `None` if unrecognized.
30            pub fn from_code(s: &str) -> Option<DiagCode> {
31                match s {
32                    $( $code => Some(DiagCode::$variant), )*
33                    _ => None,
34                }
35            }
36
37            /// Returns the fixed [`Severity`] for this diagnostic code.
38            pub fn severity(self) -> Severity {
39                match self {
40                    $( DiagCode::$variant => Severity::$severity, )*
41                }
42            }
43
44            /// Returns the pipeline phase that emits this diagnostic (e.g. `"lexer"`, `"resolver"`).
45            pub fn phase(self) -> &'static str {
46                match self {
47                    $( DiagCode::$variant => stringify!($phase), )*
48                }
49            }
50        }
51
52        /// All diagnostic codes in declaration order.
53        const ALL_CODES: &[DiagCode] = &[
54            $( DiagCode::$variant, )*
55        ];
56    };
57}
58
59diag_codes! {
60    // Lexer
61    lexer,      UnexpectedCharacter,        "unexpected-character",                  Error;
62    lexer,      UnterminatedString,         "unterminated-string",                   Error;
63    lexer,      UnterminatedHexBinStr,      "unterminated-hex-bin-string",           Error;
64    lexer,      MissingHexBinSuffix,        "missing-hex-bin-suffix",               Error;
65    lexer,      HexStringMul2,              "hex-string-mul2",                       Warning;
66    lexer,      BinStringMul8,              "bin-string-mul8",                       Warning;
67
68    // Parser
69    parser,     IdentifierUnderscore,       "identifier-underscore",                 Style;
70    parser,     IdentifierHyphenEnd,        "identifier-hyphen-end",                 Error;
71    parser,     IdentifierLength64,         "identifier-length-64",                  Error;
72    parser,     IdentifierLength32,         "identifier-length-32",                  Warning;
73    parser,     BadIdentifierCase,          "bad-identifier-case",                   Error;
74    parser,     ParseError,                 "parse-error",                           Error;
75    parser,     InvalidU32,                 "invalid-u32",                           Error;
76    parser,     InvalidI64,                 "invalid-i64",                           Error;
77    parser,     KeywordReserved,            "keyword-reserved",                      Severe;
78    parser,     InvalidHexRange,            "invalid-hex-range",                     Error;
79    parser,     NumberLeadingZero,          "number-leading-zero",                   Minor;
80    parser,     MissingComma,              "missing-comma",                         Minor;
81
82    // Lower
83    lower,      MissingModuleIdentity,      "missing-module-identity",               Warning;
84    lower,      RevisionLastUpdated,        "revision-last-updated",                 Minor;
85    lower,      RevisionNotDescending,      "revision-not-descending",               Minor;
86    lower,      RevisionAfterUpdate,        "revision-after-update",                 Minor;
87    lower,      DateCharacter,              "date-character",                        Error;
88    lower,      DateLength,                 "date-length",                           Error;
89    lower,      DateMonth,                  "date-month",                            Error;
90    lower,      DateDay,                    "date-day",                              Error;
91    lower,      DateHour,                   "date-hour",                             Error;
92    lower,      DateMinutes,               "date-minutes",                          Error;
93    lower,      DateValue,                  "date-value",                            Error;
94    lower,      DateYear2Digits,            "date-year-2digits",                     Warning;
95    lower,      DateInFuture,               "date-in-future",                        Style;
96    lower,      DateInPast,                 "date-in-past",                          Style;
97    lower,      UnknownDefinitionType,      "unknown-definition-type",               Warning;
98    lower,      UnknownTypeSyntax,          "unknown-type-syntax",                   Warning;
99    lower,      UnknownConstraintType,      "unknown-constraint-type",               Warning;
100    lower,      UnknownRangeValue,          "unknown-range-value",                   Warning;
101    lower,      UnknownOidComponent,        "unknown-oid-component-type",            Warning;
102    lower,      UnknownDefvalType,          "unknown-defval-type",                   Warning;
103    lower,      BitsNumberNegative,         "bits-number-negative",                  Error;
104    lower,      BitsNumberTooLarge,         "bits-number-too-large",                 Error;
105    lower,      BitsNumberLarge,            "bits-number-large",                     Style;
106    lower,      EnumZero,                   "enum-zero",                             Error;
107    lower,      EnumNameRedefinition,       "enum-name-redefinition",                Error;
108    lower,      EnumValueRedefinition,      "enum-value-redefinition",               Error;
109    lower,      BitsNameRedefinition,       "bits-name-redefinition",                Error;
110    lower,      BitsValueRedefinition,      "bits-value-redefinition",               Error;
111    lower,      ModuleIdentityNotFirst,     "module-identity-not-first",             Warning;
112    lower,      ModuleIdentityMultiple,     "module-identity-multiple",              Error;
113    lower,      MacroNotImported,           "macro-not-imported",                    Minor;
114    lower,      EmptyDescription,           "empty-description",                     Style;
115    lower,      EmptyReference,             "empty-reference",                       Style;
116    lower,      EmptyOrganization,          "empty-organization",                    Style;
117    lower,      EmptyContact,               "empty-contact",                         Style;
118    lower,      EmptyUnits,                 "empty-units",                           Style;
119    lower,      EmptyFormat,                "empty-format",                          Style;
120    lower,      ModuleNameSuffix,           "module-name-suffix",                    Style;
121    lower,      MacroNotAllowed,            "macro-not-allowed",                     Warning;
122    lower,      ChoiceNotAllowed,           "choice-not-allowed",                    Warning;
123    lower,      TaggedTypeNotAllowed,       "tagged-type-not-allowed",               Warning;
124
125    // Resolver
126    resolver,   ImportNotFound,             "import-not-found",                      Error;
127    resolver,   ImportModuleNotFound,       "import-module-not-found",               Error;
128    resolver,   TypeUnknown,                "type-unknown",                          Error;
129    resolver,   OidOrphan,                  "oid-orphan",                            Error;
130    resolver,   IndexUnresolved,            "index-unresolved",                      Error;
131    resolver,   ObjectsUnresolved,          "objects-unresolved",                    Error;
132    resolver,   IdentifierHyphenSMIv2,      "identifier-hyphen-smiv2",               Warning;
133    resolver,   GroupNotAccessible,          "group-not-accessible",                  Minor;
134    resolver,   NotifObjectNotObject,       "notification-object-not-object",        Minor;
135    resolver,   NotifObjectAccess,          "notification-object-access",            Minor;
136    resolver,   NotifNotReversible,         "notification-not-reversible",           Warning;
137    resolver,   NotifIdTooLarge,            "notification-id-too-large",             Warning;
138    resolver,   MalformedHexDefval,         "malformed-hex-defval",                  Warning;
139    resolver,   MalformedBinDefval,         "malformed-bin-defval",                  Warning;
140    resolver,   DefvalUnresolved,           "defval-unresolved",                     Warning;
141    resolver,   VariationAccessNotifOnly,   "variation-access-notification-only",    Minor;
142    resolver,   GroupMemberUnresolved,       "group-member-unresolved",              Error;
143    resolver,   IndexNotObject,             "index-not-object",                      Minor;
144    resolver,   AugmentsNotObject,          "augments-not-object",                   Minor;
145    resolver,   AugmentNested,              "augment-nested",                        Error;
146    resolver,   NotifNoOid,                 "notification-no-oid",                   Minor;
147    resolver,   PrimitiveTypeMissing,       "primitive-type-missing",                Error;
148    resolver,   IntegerInSMIv2,             "integer-in-smiv2",                      Warning;
149    resolver,   IndexIntegerNoRange,        "index-integer-no-range",                Error;
150    resolver,   IndexNegativeRange,         "index-negative-range",                  Error;
151    resolver,   DefvalBasetype,             "defval-basetype",                       Warning;
152    resolver,   DefvalRange,                "defval-range",                          Warning;
153    resolver,   DefvalEnum,                 "defval-enum",                           Warning;
154    resolver,   DefvalBits,                 "defval-bits",                           Warning;
155    resolver,   CounterDefvalIllegal,       "counter-defval-illegal",                Warning;
156    resolver,   IndexCounterIllegal,        "index-counter-illegal",                 Warning;
157    resolver,   RangeBounds,                "range-bounds",                          Error;
158    resolver,   RangeExchanged,             "range-exchanged",                       Error;
159    resolver,   RangeOverlap,               "range-overlap",                         Error;
160    resolver,   RangeAscending,             "range-ascending",                       Warning;
161    resolver,   SizeIllegal,                "size-illegal",                          Error;
162    resolver,   RangeIllegal,               "range-illegal",                         Error;
163    resolver,   CounterRangeIllegal,        "counter-range-illegal",                 Error;
164    resolver,   SubtypeEnumIllegal,         "subtype-enumeration-illegal",           Error;
165    resolver,   SubtypeBitsIllegal,         "subtype-bits-illegal",                  Error;
166    resolver,   ParentTable,                "parent-table",                          Error;
167    resolver,   ParentRow,                  "parent-row",                            Error;
168    resolver,   ParentColumn,               "parent-column",                         Error;
169    resolver,   ParentScalar,               "parent-scalar",                         Error;
170    resolver,   ParentNode,                 "parent-node",                           Error;
171    resolver,   ParentNotification,         "parent-notification",                   Error;
172    resolver,   ParentGroup,                "parent-group",                          Error;
173    resolver,   ParentCompliance,           "parent-compliance",                     Error;
174    resolver,   ParentCapabilities,         "parent-capabilities",                   Error;
175    resolver,   RowSubidentifierOne,        "row-node-subidentifier-one",            Error;
176    resolver,   IndexElementNoSize,         "index-element-no-size",                 Minor;
177    resolver,   IndexIllegalBasetype,       "index-illegal-basetype",                Severe;
178    resolver,   LastSubidZero,              "last-subid-zero",                       Severe;
179    resolver,   OidRecursive,               "oid-recursive",                         Error;
180    resolver,   OidRegistered,              "oid-registered",                        Severe;
181    resolver,   OidReuse,                   "oid-reuse",                             Warning;
182    resolver,   SequenceNoColumn,           "sequence-no-column",                    Minor;
183    resolver,   SequenceMissingColumn,      "sequence-missing-column",               Minor;
184    resolver,   SequenceOrder,              "sequence-order",                        Warning;
185    resolver,   SequenceTypeMismatch,       "sequence-type-mismatch",                Error;
186    resolver,   IndexExceedsTooLarge,       "index-exceeds-too-large",               Warning;
187    resolver,   AccessInvalidSMIv1,         "access-invalid-smiv1",                  Error;
188    resolver,   AccessWriteOnlySMIv2,       "access-write-only-smiv2",               Error;
189    resolver,   AccessTableIllegal,         "access-table-illegal",                  Minor;
190    resolver,   AccessRowIllegal,           "access-row-illegal",                    Minor;
191    resolver,   AccessCounterIllegal,       "access-counter-illegal",                Style;
192    resolver,   ScalarNotCreatable,         "scalar-not-creatable",                  Minor;
193    resolver,   MaxAccessInSMIv1,           "maxaccess-in-smiv1",                    Error;
194    resolver,   AccessInSMIv2,              "access-in-smiv2",                       Error;
195    resolver,   StatusInvalidSMIv1,         "status-invalid-smiv1",                  Error;
196    resolver,   StatusInvalidSMIv2,         "status-invalid-smiv2",                  Error;
197    resolver,   TypeStatusDeprecated,       "type-status-deprecated",                Warning;
198    resolver,   TypeStatusObsolete,         "type-status-obsolete",                  Warning;
199    resolver,   GroupMembership,            "group-membership",                      Minor;
200    resolver,   GroupMemberMixed,           "group-member-mixed",                    Minor;
201    resolver,   GroupObjectsNotification,   "group-objects-notification",             Error;
202    resolver,   GroupNotificationsObject,   "group-notifications-object",             Error;
203    resolver,   GroupObjectStatus,          "group-object-status",                   Warning;
204    resolver,   ComplianceGroupStatus,      "compliance-group-status",               Warning;
205    resolver,   ComplianceObjectStatus,     "compliance-object-status",              Warning;
206    resolver,   ComplianceGroupInvalid,     "compliance-group-invalid",              Warning;
207    resolver,   RefinementExists,           "refinement-exists",                     Warning;
208    resolver,   OptionalGroupExists,        "optional-group-exists",                 Warning;
209    resolver,   RefinementNotListed,        "refinement-not-listed",                 Warning;
210    resolver,   ComplianceMemberNotLocal,   "compliance-member-not-local",           Warning;
211    resolver,   TimeticksRangeIllegal,      "timeticks-range-illegal",               Error;
212    resolver,   StatusInvalidCapabilities,  "status-invalid-capabilities",           Error;
213    resolver,   ImportDuplicate,            "import-duplicate",                      Minor;
214    resolver,   ImportUnused,               "import-unused",                         Style;
215    resolver,   BasetypeNotImported,        "basetype-not-imported",                 Minor;
216    resolver,   DescriptionMissing,         "description-missing",                   Minor;
217    resolver,   TCNested,                   "textual-convention-nested",             Style;
218    resolver,   TypeAssignmentSMIv2,        "type-assignment-smiv2",                 Style;
219    resolver,   TableNameTable,             "table-name-table",                      Style;
220    resolver,   RowNameEntry,               "row-name-entry",                        Style;
221    resolver,   RowNameTableName,           "row-name-table-name",                   Style;
222    resolver,   NamedNumbersAscending,      "named-numbers-ascending",               Style;
223    resolver,   HyphenInLabel,              "hyphen-in-label",                       Style;
224    resolver,   OpaqueSMIv2,                "opaque-smiv2",                          Warning;
225    resolver,   InvalidFormat,              "invalid-format",                        Error;
226    resolver,   TypeWithoutFormat,          "type-without-format",                   Style;
227    resolver,   TypeUnreferenced,           "type-unref",                            Style;
228    resolver,   GroupUnreferenced,          "group-unref",                           Style;
229    resolver,   ObsoleteImport,             "obsolete-import",                       Warning;
230    resolver,   IdentifierCaseMatch,        "identifier-case-match",                 Style;
231    resolver,   TrapInSMIv2,               "trap-in-smiv2",                         Warning;
232    resolver,   NodeImplicit,               "node-implicit",                         Style;
233    resolver,   ModuleIdentityReg,          "module-identity-registration",          Warning;
234    resolver,   RowStatusDefault,           "rowstatus-default",                     Style;
235    resolver,   RowStatusAccess,            "rowstatus-access",                      Style;
236    resolver,   StorageTypeDefault,         "storagetype-default",                   Style;
237    resolver,   TAddressTDomain,            "taddress-tdomain",                      Warning;
238    resolver,   IndexAccessible,            "index-accessible",                      Minor;
239    resolver,   IndexNotAccessible,         "index-not-accessible",                  Minor;
240    resolver,   IndexDefval,                "index-defval",                          Warning;
241    resolver,   AccessWriteOnlySMIv1,       "access-write-only-smiv1",               Style;
242    resolver,   IpAddressInSyntax,          "ipaddress-in-syntax",                   Style;
243    resolver,   InetAddressPairing,         "inetaddress-inetaddresstype",           Warning;
244    resolver,   InetAddressTypeSubtyped,    "inetaddresstype-subtyped",              Warning;
245    resolver,   InetAddressSpecific,        "inetaddress-specific",                  Style;
246    resolver,   TransportAddressPairing,    "transportaddress-transportaddresstype", Warning;
247    resolver,   TransportAddressTypeSubtyped, "transportaddresstype-subtyped",       Warning;
248    resolver,   TransportAddressSpecific,   "transportaddress-specific",             Style;
249}
250
251impl std::fmt::Display for DiagCode {
252    /// Formats as the kebab-case code string (same as [`DiagCode::as_code`]).
253    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254        f.write_str(self.as_code())
255    }
256}
257
258/// Returns all known diagnostic codes in declaration order.
259pub fn all_diagnostic_codes() -> &'static [DiagCode] {
260    ALL_CODES
261}
262
263#[cfg(test)]
264mod tests {
265    use super::*;
266
267    #[test]
268    fn code_roundtrip() {
269        for &code in ALL_CODES {
270            let s = code.as_code();
271            let parsed = DiagCode::from_code(s).unwrap_or_else(|| panic!("failed to parse {s}"));
272            assert_eq!(parsed, code);
273        }
274    }
275
276    #[test]
277    fn all_codes_have_severity() {
278        for &code in ALL_CODES {
279            let _ = code.severity();
280        }
281    }
282
283    #[test]
284    fn all_codes_have_phase() {
285        for &code in ALL_CODES {
286            let phase = code.phase();
287            assert!(
288                ["lexer", "parser", "lower", "resolver"].contains(&phase),
289                "unknown phase {phase} for {code}"
290            );
291        }
292    }
293}