Skip to content

Commit fe81dc1

Browse files
committed
Optionally suggest [[ over [ in Bash scripts (-o require-double-brackets) (fixes koalaman#887)
1 parent fbc8d2c commit fe81dc1

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- SC2286-SC2288: Warn when command name ends in a symbol like `/.)'"`
44
- SC2289: Warn when command name contains tabs or linefeeds
55
- SC2291: Warn about repeated unquoted spaces between words in echo
6+
- SC2292: Suggest [[ over [ in Bash/Ksh scripts (optional)
67

78
### Fixed
89
- SC2102 about repetitions in ranges no longer triggers on [[ -v arr[xx] ]]

src/ShellCheck/Analytics.hs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,13 @@ optionalTreeChecks = [
244244
cdPositive = "echo $VAR",
245245
cdNegative = "VAR=hello; echo $VAR"
246246
}, checkUnassignedReferences' True)
247+
248+
,(newCheckDescription {
249+
cdName = "require-double-brackets",
250+
cdDescription = "Require [[ and warn about [ in Bash/Ksh",
251+
cdPositive = "[ -e /etc/issue ]",
252+
cdNegative = "[[ -e /etc/issue ]]"
253+
}, checkRequireDoubleBracket)
247254
]
248255

249256
optionalCheckMap :: Map.Map String (Parameters -> Token -> [TokenComment])
@@ -4311,5 +4318,39 @@ checkCommandWithTrailingSymbol _ t =
43114318
'\"' -> "doublequote"
43124319
x -> '\'' : x : "\'"
43134320

4321+
4322+
prop_checkRequireDoubleBracket1 = verifyTree checkRequireDoubleBracket "[ -x foo ]"
4323+
prop_checkRequireDoubleBracket2 = verifyTree checkRequireDoubleBracket "[ foo -o bar ]"
4324+
prop_checkRequireDoubleBracket3 = verifyNotTree checkRequireDoubleBracket "#!/bin/sh\n[ -x foo ]"
4325+
prop_checkRequireDoubleBracket4 = verifyNotTree checkRequireDoubleBracket "[[ -x foo ]]"
4326+
checkRequireDoubleBracket params =
4327+
if isBashLike params
4328+
then nodeChecksToTreeCheck [check] params
4329+
else const []
4330+
where
4331+
check _ t = case t of
4332+
T_Condition id SingleBracket _ ->
4333+
styleWithFix id 2292 "Prefer [[ ]] over [ ] for tests in Bash/Ksh." (fixFor t)
4334+
_ -> return ()
4335+
4336+
fixFor t = fixWith $
4337+
if isSimple t
4338+
then
4339+
[
4340+
replaceStart (getId t) params 0 "[",
4341+
replaceEnd (getId t) params 0 "]"
4342+
]
4343+
else []
4344+
4345+
-- We don't tag operators like < and -o well enough to replace them,
4346+
-- so just handle the simple cases.
4347+
isSimple t = case t of
4348+
T_Condition _ _ s -> isSimple s
4349+
TC_Binary _ _ op _ _ -> not $ any (\x -> x `elem` op) "<>"
4350+
TC_Unary {} -> True
4351+
TC_Nullary {} -> True
4352+
_ -> False
4353+
4354+
43144355
return []
43154356
runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])

src/ShellCheck/AnalyzerLib.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ makeCommentWithFix :: Severity -> Id -> Code -> String -> Fix -> TokenComment
178178
makeCommentWithFix severity id code str fix =
179179
let comment = makeComment severity id code str
180180
withFix = comment {
181-
tcFix = Just fix
181+
-- If fix is empty, pretend it wasn't there.
182+
tcFix = if null (fixReplacements fix) then Nothing else Just fix
182183
}
183184
in force withFix
184185

0 commit comments

Comments
 (0)