lintje 0.11.2

Lintje is an opinionated linter for Git.
use core::ops::Range;

use crate::branch::Branch;
use crate::issue::{Context, Issue, Position};
use crate::rule::Rule;
use crate::rule::RuleValidator;
use crate::utils::display_width;

pub struct BranchNameLength {}

impl BranchNameLength {
    pub fn new() -> Self {
        Self {}
    }
}

impl RuleValidator<Branch> for BranchNameLength {
    fn validate(&self, branch: &Branch) -> Option<Vec<Issue>> {
        let name = &branch.name;
        let width = display_width(name);
        if width < 4 {
            let context = vec![Context::branch_error(
                name.to_string(),
                Range {
                    start: 0,
                    end: name.len(),
                },
                "Describe the change in more detail".to_string(),
            )];
            Some(vec![Issue::error(
                Rule::BranchNameLength,
                format!("Branch name of {} characters is too short", width),
                Position::Branch { column: 1 },
                context,
            )])
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::test::*;

    fn validate(branch: &Branch) -> Option<Vec<Issue>> {
        BranchNameLength::new().validate(branch)
    }

    fn assert_valid(name: &str) {
        assert_eq!(validate(&branch(name)), None);
    }

    fn assert_invalid(name: &str) {
        assert!(validate(&branch(name)).is_some());
    }

    #[test]
    fn valid_names() {
        let names = vec![
            "abcd".to_string(),
            "-_/!".to_string(),
            "a".repeat(5),
            "a".repeat(50),
            "".repeat(4),
            "".repeat(4),
        ];
        for name in names {
            assert_valid(&name);
        }
    }

    #[test]
    fn invalid_names() {
        let names = vec!["", "a", "ab", "abc"];
        for name in names {
            assert_invalid(name);
        }
    }

    #[test]
    fn too_short_name() {
        let issue = first_issue(validate(&branch("abc")));
        assert_eq!(issue.message, "Branch name of 3 characters is too short");
        assert_eq!(issue.position, Position::Branch { column: 1 });
        assert_contains_issue_output(
            &issue,
            "| abc\n\
             | ^^^ Describe the change in more detail",
        );
    }
}