diff --git a/CHANGELOG.md b/CHANGELOG.md index 558d239..0dc5bb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Files containing Bats tests can now be checked - Directory wide directives can now be placed in a `.shellcheckrc` - Verbose mode: Use `-S verbose` for especially pedantic suggestions +- SC2249: Warn about `case` with missing default case (verbose) - SC2248: Warn about unquoted variables without special chars (verbose) - SC2247: Warn about $"(cmd)" and $"{var}" - SC2246: Warn if a shebang's interpreter ends with / diff --git a/src/ShellCheck/Analytics.hs b/src/ShellCheck/Analytics.hs index c6f61a4..fb7c0e0 100644 --- a/src/ShellCheck/Analytics.hs +++ b/src/ShellCheck/Analytics.hs @@ -172,6 +172,7 @@ nodeChecks = [ ,checkRedirectionToCommand ,checkNullaryExpansionTest ,checkDollarQuoteParen + ,checkDefaultCase ] @@ -3202,5 +3203,22 @@ checkDollarQuoteParen params t = where fix id = fixWith [replaceStart id params 2 "\"$"] +prop_checkDefaultCase1 = verify checkDefaultCase "case $1 in a) true ;; esac" +prop_checkDefaultCase2 = verify checkDefaultCase "case $1 in ?*?) true ;; *? ) true ;; esac" +prop_checkDefaultCase3 = verifyNot checkDefaultCase "case $1 in x|*) true ;; esac" +prop_checkDefaultCase4 = verifyNot checkDefaultCase "case $1 in **) true ;; esac" +checkDefaultCase _ t = + case t of + T_CaseExpression id _ list -> + unless (any canMatchAny list) $ + verbose id 2249 "Consider adding a default *) case, even if it just exits with error." + _ -> return () + where + canMatchAny (_, list, _) = any canMatchAny' list + -- hlint objects to 'pattern' as a variable name + canMatchAny' pat = fromMaybe False $ do + pg <- wordToExactPseudoGlob pat + return $ pseudoGlobIsSuperSetof pg [PGMany] + return [] runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |]) diff --git a/src/ShellCheck/AnalyzerLib.hs b/src/ShellCheck/AnalyzerLib.hs index e52f4e3..c4f7cfa 100644 --- a/src/ShellCheck/AnalyzerLib.hs +++ b/src/ShellCheck/AnalyzerLib.hs @@ -154,6 +154,7 @@ warn id code str = addComment $ makeComment WarningC id code str err id code str = addComment $ makeComment ErrorC id code str info id code str = addComment $ makeComment InfoC id code str style id code str = addComment $ makeComment StyleC id code str +verbose id code str = addComment $ makeComment VerboseC id code str warnWithFix :: MonadWriter [TokenComment] m => Id -> Code -> String -> Fix -> m () warnWithFix = addCommentWithFix WarningC