diff --git a/CHANGELOG.md b/CHANGELOG.md index fbedc20..0617ab0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - SC1072/SC1073 now respond to disable annotations, though ignoring parse errors is still purely cosmetic and does not allow ShellCheck to continue. - Improved error reporting for trailing tokens after ]/]] and compound commands +- `#!/usr/bin/env -S shell` is now handled correctly ### Changed - Assignments are now parsed to spec, without leniency for leading $ or spaces diff --git a/src/ShellCheck/Analytics.hs b/src/ShellCheck/Analytics.hs index ef1ed2c..2e1adca 100644 --- a/src/ShellCheck/Analytics.hs +++ b/src/ShellCheck/Analytics.hs @@ -546,9 +546,14 @@ indexOfSublists sub = f 0 prop_checkShebangParameters1 = verifyTree checkShebangParameters "#!/usr/bin/env bash -x\necho cow" prop_checkShebangParameters2 = verifyNotTree checkShebangParameters "#! /bin/sh -l " +prop_checkShebangParameters3 = verifyNotTree checkShebangParameters "#!/usr/bin/env -S bash -x\necho cow" +prop_checkShebangParameters4 = verifyNotTree checkShebangParameters "#!/usr/bin/env --split-string bash -x\necho cow" checkShebangParameters p (T_Annotation _ _ t) = checkShebangParameters p t checkShebangParameters _ (T_Script _ (T_Literal id sb) _) = - [makeComment ErrorC id 2096 "On most OS, shebangs can only specify a single parameter." | length (words sb) > 2] + [makeComment ErrorC id 2096 "On most OS, shebangs can only specify a single parameter." | isMultiWord] + where + isMultiWord = length (words sb) > 2 && not (sb `matches` re) + re = mkRegex "env +(-S|--split-string)" prop_checkShebang1 = verifyNotTree checkShebang "#!/usr/bin/env bash -x\necho cow" prop_checkShebang2 = verifyNotTree checkShebang "#! /bin/sh -l " diff --git a/src/ShellCheck/AnalyzerLib.hs b/src/ShellCheck/AnalyzerLib.hs index dc081db..38e9c1d 100644 --- a/src/ShellCheck/AnalyzerLib.hs +++ b/src/ShellCheck/AnalyzerLib.hs @@ -238,6 +238,8 @@ prop_determineShell5 = determineShellTest "#shellcheck shell=sh\nfoo" == Sh prop_determineShell6 = determineShellTest "#! /bin/sh" == Sh prop_determineShell7 = determineShellTest "#! /bin/ash" == Dash prop_determineShell8 = determineShellTest' (Just Ksh) "#!/bin/sh" == Sh +prop_determineShell9 = determineShellTest "#!/bin/env -S dash -x" == Dash +prop_determineShell10 = determineShellTest "#!/bin/env --split-string= dash -x" == Dash determineShellTest = determineShellTest' Nothing determineShellTest' fallbackShell = determineShell fallbackShell . fromJust . prRoot . pScript @@ -256,10 +258,12 @@ determineShell fallbackShell t = fromMaybe Bash $ executableFromShebang :: String -> String executableFromShebang = shellFor where - shellFor s | "/env " `isInfixOf` s = headOrDefault "" (drop 1 $ words s) + shellFor s | "/env " `isInfixOf` s = fromMaybe "" $ do + [flag, shell] <- matchRegex re s + return shell shellFor s | ' ' `elem` s = shellFor $ takeWhile (/= ' ') s shellFor s = reverse . takeWhile (/= '/') . reverse $ s - + re = mkRegex "/env +(-S|--split-string=?)? *([^ ]*)" -- Given a root node, make a map from Id to parent Token.