shuck-linter 0.1.0

Lint rule engine and checker for shell scripts
Documentation
use shuck_ast::Assignment;

#[cfg(test)]
use shuck_ast::{SimpleCommand, static_word_text};

#[cfg(test)]
fn simple_command_name(command: &SimpleCommand, source: &str) -> Option<String> {
    static_word_text(&command.name, source).map(|text| text.into_owned())
}

pub fn assignment_target_name(assignment: &Assignment) -> &str {
    assignment.target.name.as_str()
}

#[cfg(test)]
mod tests {
    use shuck_ast::{Command, DeclOperand};
    use shuck_parser::parser::Parser;

    use super::{assignment_target_name, simple_command_name};

    fn parse_first_command(source: &str) -> Command {
        let output = Parser::new(source).parse().unwrap();
        output.file.body.stmts.into_iter().next().unwrap().command
    }

    #[test]
    fn simple_command_name_returns_static_command_name() {
        let source = "printf '%s\\n' hello\n";
        let command = parse_first_command(source);
        let Command::Simple(command) = command else {
            panic!("expected simple command");
        };

        assert_eq!(
            simple_command_name(&command, source).as_deref(),
            Some("printf")
        );
    }

    #[test]
    fn simple_command_name_returns_none_for_dynamic_command_name() {
        let source = "\"$tool\" --help\n";
        let command = parse_first_command(source);
        let Command::Simple(command) = command else {
            panic!("expected simple command");
        };

        assert_eq!(simple_command_name(&command, source), None);
    }

    #[test]
    fn assignment_target_name_returns_assignment_name() {
        let source = "export PS1='$PWD'\n";
        let command = parse_first_command(source);
        let Command::Decl(command) = command else {
            panic!("expected declaration command");
        };
        let DeclOperand::Assignment(assignment) = &command.operands[0] else {
            panic!("expected declaration assignment");
        };

        assert_eq!(assignment_target_name(assignment), "PS1");
    }
}