Suggest using `$((..))` in `[ 2*3 -eq 6 ]` (fixes #1641)

This commit is contained in:
Vidar Holen 2019-10-12 19:55:20 -07:00
parent de9ab4e6ef
commit afea62de4e
3 changed files with 28 additions and 2 deletions

View File

@ -4,6 +4,7 @@
### Added ### Added
- SC2254: Suggest quoting expansions in case statements - SC2254: Suggest quoting expansions in case statements
- SC2255: Suggest using `$((..))` in `[ 2*3 -eq 6 ]`
## v0.7.0 - 2019-07-28 ## v0.7.0 - 2019-07-28
### Added ### Added

View File

@ -1044,7 +1044,7 @@ checkNumberComparisons params (TC_Binary id typ op lhs rhs) = do
Dash -> err id 2073 $ "Escape \\" ++ op ++ " to prevent it redirecting." Dash -> err id 2073 $ "Escape \\" ++ op ++ " to prevent it redirecting."
_ -> err id 2073 $ "Escape \\" ++ op ++ " to prevent it redirecting (or switch to [[ .. ]])." _ -> err id 2073 $ "Escape \\" ++ op ++ " to prevent it redirecting (or switch to [[ .. ]])."
when (op `elem` ["-lt", "-gt", "-le", "-ge", "-eq"]) $ do when (op `elem` arithmeticBinaryTestOps) $ do
mapM_ checkDecimals [lhs, rhs] mapM_ checkDecimals [lhs, rhs]
when (typ == SingleBracket) $ when (typ == SingleBracket) $
checkStrings [lhs, rhs] checkStrings [lhs, rhs]
@ -1193,7 +1193,7 @@ checkConstantIfs _ (TC_Binary id typ op lhs rhs) | not isDynamic =
else checkUnmatchable id op lhs rhs else checkUnmatchable id op lhs rhs
where where
isDynamic = isDynamic =
op `elem` [ "-lt", "-gt", "-le", "-ge", "-eq", "-ne" ] op `elem` arithmeticBinaryTestOps
&& typ == DoubleBracket && typ == DoubleBracket
|| op `elem` [ "-nt", "-ot", "-ef"] || op `elem` [ "-nt", "-ot", "-ef"]
@ -2700,6 +2700,10 @@ prop_checkTestArgumentSplitting15 = verifyNot checkTestArgumentSplitting "[[ \"$
prop_checkTestArgumentSplitting16 = verifyNot checkTestArgumentSplitting "[[ -v foo[123] ]]" prop_checkTestArgumentSplitting16 = verifyNot checkTestArgumentSplitting "[[ -v foo[123] ]]"
prop_checkTestArgumentSplitting17 = verifyNot checkTestArgumentSplitting "#!/bin/ksh\n[ -e foo* ]" prop_checkTestArgumentSplitting17 = verifyNot checkTestArgumentSplitting "#!/bin/ksh\n[ -e foo* ]"
prop_checkTestArgumentSplitting18 = verify checkTestArgumentSplitting "#!/bin/ksh\n[ -d foo* ]" prop_checkTestArgumentSplitting18 = verify checkTestArgumentSplitting "#!/bin/ksh\n[ -d foo* ]"
prop_checkTestArgumentSplitting19 = verifyNot checkTestArgumentSplitting "[[ var[x] -eq 2*3 ]]"
prop_checkTestArgumentSplitting20 = verify checkTestArgumentSplitting "[ var[x] -eq 2 ]"
prop_checkTestArgumentSplitting21 = verify checkTestArgumentSplitting "[ 6 -eq 2*3 ]"
prop_checkTestArgumentSplitting22 = verify checkTestArgumentSplitting "[ foo -eq 'y' ]"
checkTestArgumentSplitting :: Parameters -> Token -> Writer [TokenComment] () checkTestArgumentSplitting :: Parameters -> Token -> Writer [TokenComment] ()
checkTestArgumentSplitting params t = checkTestArgumentSplitting params t =
case t of case t of
@ -2729,6 +2733,18 @@ checkTestArgumentSplitting params t =
(TC_Unary _ typ op token) -> checkAll typ token (TC_Unary _ typ op token) -> checkAll typ token
(TC_Binary _ typ op lhs rhs) | op `elem` arithmeticBinaryTestOps ->
if typ == DoubleBracket
then
mapM_ (\c -> do
checkArrays typ c
checkBraces typ c) [lhs, rhs]
else
mapM_ (\c -> do
checkNumericalGlob typ c
checkArrays typ c
checkBraces typ c) [lhs, rhs]
(TC_Binary _ typ op lhs rhs) -> (TC_Binary _ typ op lhs rhs) ->
if op `elem` ["=", "==", "!=", "=~"] if op `elem` ["=", "==", "!=", "=~"]
then do then do
@ -2761,6 +2777,11 @@ checkTestArgumentSplitting params t =
then warn (getId token) 2202 "Globs don't work as operands in [ ]. Use a loop." then warn (getId token) 2202 "Globs don't work as operands in [ ]. Use a loop."
else err (getId token) 2203 "Globs are ignored in [[ ]] except right of =/!=. Use a loop." else err (getId token) 2203 "Globs are ignored in [[ ]] except right of =/!=. Use a loop."
checkNumericalGlob SingleBracket token =
-- var[x] and x*2 look like globs
when (shellType params /= Ksh && isGlob token) $
err (getId token) 2255 "[ ] does not apply arithmetic evaluation. Evaluate with $((..)) for numbers, or use string comparator for strings."
prop_checkMaskedReturns1 = verify checkMaskedReturns "f() { local a=$(false); }" prop_checkMaskedReturns1 = verify checkMaskedReturns "f() { local a=$(false); }"
prop_checkMaskedReturns2 = verify checkMaskedReturns "declare a=$(false)" prop_checkMaskedReturns2 = verify checkMaskedReturns "declare a=$(false)"

View File

@ -114,6 +114,10 @@ binaryTestOps = [
"-gt", "-ge", "=~", ">", "<", "=", "\\<", "\\>", "\\<=", "\\>=" "-gt", "-ge", "=~", ">", "<", "=", "\\<", "\\>", "\\<=", "\\>="
] ]
arithmeticBinaryTestOps = [
"-eq", "-ne", "-lt", "-le", "-gt", "-ge"
]
unaryTestOps = [ unaryTestOps = [
"!", "-a", "-b", "-c", "-d", "-e", "-f", "-g", "-h", "-L", "-k", "-p", "!", "-a", "-b", "-c", "-d", "-e", "-f", "-g", "-h", "-L", "-k", "-p",
"-r", "-s", "-S", "-t", "-u", "-w", "-x", "-O", "-G", "-N", "-z", "-n", "-r", "-s", "-S", "-t", "-u", "-w", "-x", "-O", "-G", "-N", "-z", "-n",