dotenv_analyzer/
lib.rs

1mod check;
2mod comment;
3mod fix;
4mod lint_kind;
5mod warning;
6
7pub use check::check;
8pub(crate) use comment::Comment;
9pub use fix::fix;
10pub use lint_kind::LintKind;
11pub use warning::Warning;
12
13const LF: &str = "\n";
14
15fn remove_invalid_leading_chars(string: &str) -> &str {
16    string.trim_start_matches(|c: char| !(c.is_alphabetic() || c == '_'))
17}
18
19#[cfg(test)]
20pub(crate) mod tests {
21    use dotenv_core::LineEntry;
22
23    use super::*;
24    use crate::check::Check;
25
26    /**
27    Helper function for testing `Check` implementations.
28
29    A `Check` implementation can be used against a number of &str inputs
30    and optional `Warning` messages respectively.
31
32    This function construct `LineEntry`s and optional `Warning`s,
33    if required, in order to assert that the `Check` implementation is creating
34    the correct `Warning` and not just the correct message.
35
36    # Example
37
38    ```no_run
39    #[test]
40    fn with_one_duplicated_test_key() {
41        check_test(&mut DuplicatedKeyChecker::default(),
42            [
43                ("FOO=BAR", None),
44                ("FOO=BAR", Some("The FOO key is duplicated")),
45            ],
46        );
47    }
48    ```
49    The above will assert that on the first line "FOO=BAR" does not cause
50    any warnings, hence the `None`.
51
52    The second line however, should expect a `Warning` with a message of
53    "The FOO key is duplicated".
54    */
55    pub fn check_test<'test, T, U>(checker: &mut T, asserts: U)
56    where
57        T: Check,
58        U: AsRef<[(&'test str, Option<&'test str>)]>,
59    {
60        let asserts = asserts.as_ref();
61        let mut line_number = 1;
62        let total = asserts.len();
63
64        for (input, expected) in asserts {
65            let line = line_entry(line_number, total, input);
66            line_number += 1;
67
68            let result = checker.run(&line);
69            let expected = expected.map(|e| Warning::new(line.number, checker.name(), e));
70
71            assert_eq!(result, expected);
72        }
73    }
74
75    pub fn blank_line_entry(number: usize, total_lines: usize) -> LineEntry {
76        LineEntry::new(number, "\n", total_lines == number)
77    }
78
79    pub fn line_entry(number: usize, total_lines: usize, raw_string: &str) -> LineEntry {
80        LineEntry::new(number, raw_string, total_lines == number)
81    }
82
83    #[test]
84    fn remove_invalid_leading_chars_test() {
85        let string = "-1&*FOO";
86        assert_eq!("FOO", remove_invalid_leading_chars(string));
87
88        let string = "***FOO-BAR";
89        assert_eq!("FOO-BAR", remove_invalid_leading_chars(string));
90    }
91}