Warn when shell functions blatantly recurse (fixes #1994)
This commit is contained in:
parent
cc81bdee31
commit
1ac2c31728
|
@ -3,6 +3,7 @@
|
||||||
- SC2259/SC2260: Warn when redirections override pipes
|
- SC2259/SC2260: Warn when redirections override pipes
|
||||||
- SC2261: Warn about multiple competing redirections
|
- SC2261: Warn about multiple competing redirections
|
||||||
- SC2262/SC2263: Warn about aliases declared and used in the same parsing unit
|
- SC2262/SC2263: Warn about aliases declared and used in the same parsing unit
|
||||||
|
- SC2264: Warn about wrapper functions that blatantly recurse
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- SC1072/SC1073 now respond to disable annotations, though ignoring parse errors
|
- SC1072/SC1073 now respond to disable annotations, though ignoring parse errors
|
||||||
|
|
|
@ -191,6 +191,7 @@ nodeChecks = [
|
||||||
,checkUselessBang
|
,checkUselessBang
|
||||||
,checkTranslatedStringVariable
|
,checkTranslatedStringVariable
|
||||||
,checkModifiedArithmeticInRedirection
|
,checkModifiedArithmeticInRedirection
|
||||||
|
,checkBlatantRecursion
|
||||||
]
|
]
|
||||||
|
|
||||||
optionalChecks = map fst optionalTreeChecks
|
optionalChecks = map fst optionalTreeChecks
|
||||||
|
@ -3824,5 +3825,41 @@ groupByLink f list =
|
||||||
else (reverse $ current:span) : g next [] rest
|
else (reverse $ current:span) : g next [] rest
|
||||||
g current span [] = [reverse (current:span)]
|
g current span [] = [reverse (current:span)]
|
||||||
|
|
||||||
|
|
||||||
|
prop_checkBlatantRecursion1 = verify checkBlatantRecursion ":(){ :|:& };:"
|
||||||
|
prop_checkBlatantRecursion2 = verify checkBlatantRecursion "f() { f; }"
|
||||||
|
prop_checkBlatantRecursion3 = verifyNot checkBlatantRecursion "f() { command f; }"
|
||||||
|
prop_checkBlatantRecursion4 = verify checkBlatantRecursion "cd() { cd \"$lol/$1\" || exit; }"
|
||||||
|
prop_checkBlatantRecursion5 = verifyNot checkBlatantRecursion "cd() { [ -z \"$1\" ] || cd \"$1\"; }"
|
||||||
|
prop_checkBlatantRecursion6 = verifyNot checkBlatantRecursion "cd() { something; cd $1; }"
|
||||||
|
prop_checkBlatantRecursion7 = verifyNot checkBlatantRecursion "cd() { builtin cd $1; }"
|
||||||
|
checkBlatantRecursion :: Parameters -> Token -> Writer [TokenComment] ()
|
||||||
|
checkBlatantRecursion params t =
|
||||||
|
case t of
|
||||||
|
T_Function _ _ _ name body ->
|
||||||
|
case getCommandSequences body of
|
||||||
|
[first : _] -> checkList name first
|
||||||
|
_ -> return ()
|
||||||
|
_ -> return ()
|
||||||
|
where
|
||||||
|
checkList :: String -> Token -> Writer [TokenComment] ()
|
||||||
|
checkList name t =
|
||||||
|
case t of
|
||||||
|
T_Backgrounded _ t -> checkList name t
|
||||||
|
T_AndIf _ lhs _ -> checkList name lhs
|
||||||
|
T_OrIf _ lhs _ -> checkList name lhs
|
||||||
|
T_Pipeline _ _ cmds -> mapM_ (checkCommand name) cmds
|
||||||
|
_ -> return ()
|
||||||
|
|
||||||
|
checkCommand :: String -> Token -> Writer [TokenComment] ()
|
||||||
|
checkCommand name cmd = sequence_ $ do
|
||||||
|
let (invokedM, t) = getCommandNameAndToken True cmd
|
||||||
|
invoked <- invokedM
|
||||||
|
guard $ name == invoked
|
||||||
|
return $
|
||||||
|
errWithFix (getId t) 2264
|
||||||
|
("This function unconditionally re-invokes itself. Missing 'command'?")
|
||||||
|
(fixWith [replaceStart (getId t) params 0 $ "command "])
|
||||||
|
|
||||||
return []
|
return []
|
||||||
runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])
|
runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])
|
||||||
|
|
|
@ -163,6 +163,8 @@ err id code str = addComment $ makeComment ErrorC id code str
|
||||||
info id code str = addComment $ makeComment InfoC id code str
|
info id code str = addComment $ makeComment InfoC id code str
|
||||||
style id code str = addComment $ makeComment StyleC id code str
|
style id code str = addComment $ makeComment StyleC id code str
|
||||||
|
|
||||||
|
errWithFix :: MonadWriter [TokenComment] m => Id -> Code -> String -> Fix -> m ()
|
||||||
|
errWithFix = addCommentWithFix ErrorC
|
||||||
warnWithFix :: MonadWriter [TokenComment] m => Id -> Code -> String -> Fix -> m ()
|
warnWithFix :: MonadWriter [TokenComment] m => Id -> Code -> String -> Fix -> m ()
|
||||||
warnWithFix = addCommentWithFix WarningC
|
warnWithFix = addCommentWithFix WarningC
|
||||||
styleWithFix :: MonadWriter [TokenComment] m => Id -> Code -> String -> Fix -> m ()
|
styleWithFix :: MonadWriter [TokenComment] m => Id -> Code -> String -> Fix -> m ()
|
||||||
|
|
Loading…
Reference in New Issue