bashrs 6.66.0

Rust-to-Shell transpiler for deterministic bootstrap scripts
// SC2130: -e is only valid with 'if' or 'while', not with [ ]
#[allow(unused_imports)]
//
// The -e test flag checks if file exists. In [ ], use -e or -f.
// Don't confuse -e (file exists) with -e shell option (exit on error).
//
// Examples:
// Bad:
//   set -e                   // Shell option (correct context)
//   [ -e file ]              // File test (correct - this is OK!)
//
// Note: This rule actually flags incorrect usage patterns.
// The -e flag is VALID in [ ] for file tests.
//
// Good:
//   [ -e /path/to/file ]     // Correct file existence test
//   [ -f /path/to/file ]     // Correct file test
//   set -e                   // Correct shell option
//
// Impact: Clarification of -e usage contexts
use crate::linter::{Diagnostic, LintResult, Severity, Span};

// NOTE: This rule is actually about detecting misuse of -e in wrong contexts.
// The -e flag is VALID in [ ] for file existence tests.
// We'll check for the shell option usage pattern instead.

pub fn check(source: &str) -> LintResult {
    // This rule is tricky - -e is actually VALID in [ ] for file tests
    // The issue is when people confuse shell -e option with test -e flag
    // For now, we'll skip implementation as the rule description is unclear

    // The real issue SC2130 catches is using -e outside of test contexts,
    // but -e is primarily a shell option (set -e), not a standalone flag

    LintResult::new()
}

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

    #[test]
    fn test_sc2130_e_flag_in_test_ok() {
        let code = "[ -e /path/to/file ]";
        let result = check(code);
        // -e in [ ] is correct for file existence test
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_set_e_ok() {
        let code = "set -e";
        let result = check(code);
        // set -e is correct shell option
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_if_e_ok() {
        let code = "if [ -e file ]; then";
        let result = check(code);
        // -e in if test is correct
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_while_e_ok() {
        let code = "while [ -e file ]; do";
        let result = check(code);
        // -e in while test is correct
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_f_flag_ok() {
        let code = "[ -f /path/to/file ]";
        let result = check(code);
        // -f is file test flag
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_d_flag_ok() {
        let code = "[ -d /path/to/dir ]";
        let result = check(code);
        // -d is directory test flag
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_comment_ok() {
        let code = "# [ -e file ]";
        let result = check(code);
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_multiline_ok() {
        let code = r#"
if [ -e "$file" ]; then
    echo "File exists"
fi
"#;
        let result = check(code);
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_bash_e_option_ok() {
        let code = "#!/bin/bash\nset -e";
        let result = check(code);
        assert_eq!(result.diagnostics.len(), 0);
    }

    #[test]
    fn test_sc2130_shopt_ok() {
        let code = "shopt -s -e";
        let result = check(code);
        assert_eq!(result.diagnostics.len(), 0);
    }
}