dotenv_analyzer/
lint_kind.rs1use std::{fmt, str::FromStr};
2
3#[derive(Debug, PartialEq, Eq, Clone, Copy)]
4pub enum LintKind {
5 DuplicatedKey,
6 EndingBlankLine,
7 ExtraBlankLine,
8 IncorrectDelimiter,
9 KeyWithoutValue,
10 LeadingCharacter,
11 LowercaseKey,
12 QuoteCharacter,
13 SpaceCharacter,
14 SubstitutionKey,
15 TrailingWhitespace,
16 UnorderedKey,
17 ValueWithoutQuotes,
18 SchemaViolation,
19}
20
21impl FromStr for LintKind {
22 type Err = ();
23
24 fn from_str(s: &str) -> Result<Self, Self::Err> {
25 match s {
26 "DuplicatedKey" => Ok(LintKind::DuplicatedKey),
27 "EndingBlankLine" => Ok(LintKind::EndingBlankLine),
28 "ExtraBlankLine" => Ok(LintKind::ExtraBlankLine),
29 "IncorrectDelimiter" => Ok(LintKind::IncorrectDelimiter),
30 "KeyWithoutValue" => Ok(LintKind::KeyWithoutValue),
31 "LeadingCharacter" => Ok(LintKind::LeadingCharacter),
32 "LowercaseKey" => Ok(LintKind::LowercaseKey),
33 "QuoteCharacter" => Ok(LintKind::QuoteCharacter),
34 "SpaceCharacter" => Ok(LintKind::SpaceCharacter),
35 "SubstitutionKey" => Ok(LintKind::SubstitutionKey),
36 "TrailingWhitespace" => Ok(LintKind::TrailingWhitespace),
37 "UnorderedKey" => Ok(LintKind::UnorderedKey),
38 "ValueWithoutQuotes" => Ok(LintKind::ValueWithoutQuotes),
39 _ => Err(()),
40 }
41 }
42}
43
44impl fmt::Display for LintKind {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 write!(f, "{}", format!("{self:?}").replace("LintKind", ""))
47 }
48}
49
50#[cfg(feature = "clap")]
51impl clap::ValueEnum for LintKind {
52 fn value_variants<'a>() -> &'a [Self] {
53 &[
54 LintKind::DuplicatedKey,
55 LintKind::EndingBlankLine,
56 LintKind::ExtraBlankLine,
57 LintKind::IncorrectDelimiter,
58 LintKind::KeyWithoutValue,
59 LintKind::LeadingCharacter,
60 LintKind::LowercaseKey,
61 LintKind::QuoteCharacter,
62 LintKind::SpaceCharacter,
63 LintKind::SubstitutionKey,
64 LintKind::TrailingWhitespace,
65 LintKind::UnorderedKey,
66 LintKind::ValueWithoutQuotes,
67 LintKind::SchemaViolation,
68 ]
69 }
70
71 fn to_possible_value<'a>(&self) -> Option<clap::builder::PossibleValue> {
72 Some(match self {
73 LintKind::DuplicatedKey => clap::builder::PossibleValue::new("DuplicatedKey"),
74 LintKind::EndingBlankLine => clap::builder::PossibleValue::new("EndingBlankLine"),
75 LintKind::ExtraBlankLine => clap::builder::PossibleValue::new("ExtraBlankLine"),
76 LintKind::IncorrectDelimiter => clap::builder::PossibleValue::new("IncorrectDelimiter"),
77 LintKind::KeyWithoutValue => clap::builder::PossibleValue::new("KeyWithoutValue"),
78 LintKind::LeadingCharacter => clap::builder::PossibleValue::new("LeadingCharacter"),
79 LintKind::LowercaseKey => clap::builder::PossibleValue::new("LowercaseKey"),
80 LintKind::QuoteCharacter => clap::builder::PossibleValue::new("QuoteCharacter"),
81 LintKind::SpaceCharacter => clap::builder::PossibleValue::new("SpaceCharacter"),
82 LintKind::SubstitutionKey => clap::builder::PossibleValue::new("SubstitutionKey"),
83 LintKind::TrailingWhitespace => clap::builder::PossibleValue::new("TrailingWhitespace"),
84 LintKind::UnorderedKey => clap::builder::PossibleValue::new("UnorderedKey"),
85 LintKind::ValueWithoutQuotes => clap::builder::PossibleValue::new("ValueWithoutQuotes"),
86 LintKind::SchemaViolation => clap::builder::PossibleValue::new("SchemaViolation"),
87 })
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_str_to_lint_variant_conversion() {
97 let expected = <LintKind as FromStr>::from_str("DuplicatedKey").expect("parse lint");
98 assert_eq!(expected, LintKind::DuplicatedKey);
99 }
100
101 #[test]
102 fn test_invalid_lint_str_variant() {
103 assert_eq!(Err(()), <LintKind as FromStr>::from_str("FooBarLint"));
104 }
105
106 #[test]
107 fn test_lint_variant_display_output() {
108 let one = LintKind::EndingBlankLine;
109 let two = LintKind::DuplicatedKey;
110 let three = LintKind::SubstitutionKey;
111
112 assert_eq!(
113 "EndingBlankLine DuplicatedKey SubstitutionKey",
114 format!("{one} {two} {three}")
115 );
116 }
117}