use crate::linter::{Diagnostic, LintResult, Severity, Span};
pub fn check(source: &str) -> LintResult {
let mut result = LintResult::new();
if let Some(first_line) = source.lines().next() {
if first_line.trim().is_empty() {
return result;
}
if !first_line.starts_with("#!") {
let diagnostic = Diagnostic::new(
"SC2148",
Severity::Info,
"Add a shebang to indicate which interpreter should be used".to_string(),
Span::new(1, 1, 1, first_line.len() + 1),
);
result.add(diagnostic);
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sc2148_missing_shebang() {
let code = r#"echo "Hello World""#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 1);
assert!(result.diagnostics[0].message.contains("shebang"));
}
#[test]
fn test_sc2148_with_shebang_bash_ok() {
let code = r#"#!/bin/bash
echo "Hello World""#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 0);
}
#[test]
fn test_sc2148_with_shebang_sh_ok() {
let code = r#"#!/bin/sh
echo "Hello World""#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 0);
}
#[test]
fn test_sc2148_with_env_shebang_ok() {
let code = r#"#!/usr/bin/env bash
echo "Hello World""#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 0);
}
#[test]
fn test_sc2148_comment_not_shebang() {
let code = r#"# This is a script
echo "Hello""#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 1);
}
#[test]
fn test_sc2148_empty_file() {
let code = "";
let result = check(code);
assert_eq!(result.diagnostics.len(), 0);
}
#[test]
fn test_sc2148_blank_first_line() {
let code = r#"
echo "Hello""#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 0);
}
#[test]
fn test_sc2148_python_shebang_ok() {
let code = r#"#!/usr/bin/env python3
print("Hello")"#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 0);
}
#[test]
fn test_sc2148_variable_assignment_without_shebang() {
let code = r#"FOO=bar
echo "$FOO""#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 1);
}
#[test]
fn test_sc2148_function_without_shebang() {
let code = r#"foo() {
echo "bar"
}"#;
let result = check(code);
assert_eq!(result.diagnostics.len(), 1);
}
}