lint 0.1.3

A versatile linting tool with CLI, MCP, and library interfaces
Documentation
use crate::language_rules::LanguageRule;
use crate::output::LintMessage;
use std::path::Path;

#[derive(Debug, Clone)]
pub struct ShellEchoRule;

impl LanguageRule for ShellEchoRule {
    fn name(&self) -> &str {
        "shell-echo-quote"
    }

    fn description(&self) -> &str {
        "Warns about unquoted variables in shell echo statements to prevent word splitting."
    }

    fn check(&self, content: &str, _file_path: &Path) -> Vec<LintMessage> {
        let mut messages = Vec::new();

        for (line_num, line) in content.lines().enumerate() {
            let trimmed = line.trim();
            if trimmed.starts_with("echo ")
                && !trimmed.starts_with("echo \"")
                && !trimmed.starts_with("echo '")
                && trimmed.contains('$')
                && !trimmed.contains('"')
            {
                messages.push(LintMessage::new(
                    line_num + 1,
                    line.find("echo").unwrap_or(0),
                    self.default_severity(),
                    "Unquoted variable in echo".to_string(),
                    self.name().to_string(),
                    Some(
                        "Quote variables: 'echo $VAR' → 'echo \"$VAR\"' to prevent word splitting"
                            .to_string(),
                    ),
                ));
            }
        }

        messages
    }

    fn supports_extension(&self, extension: &str) -> bool {
        matches!(extension, "sh" | "bash")
    }
}