Warn when calling functions before defining them.
This commit is contained in:
parent
43bb6a20ad
commit
81388cefd2
|
@ -308,6 +308,7 @@ isBraceExpansion t = case t of T_BraceExpansion {} -> True; _ -> False
|
|||
|
||||
-- Get the lists of commands from tokens that contain them, such as
|
||||
-- the body of while loops or branches of if statements.
|
||||
getCommandSequences :: Token -> [[Token]]
|
||||
getCommandSequences t =
|
||||
case t of
|
||||
T_Script _ _ cmds -> [cmds]
|
||||
|
@ -318,6 +319,7 @@ getCommandSequences t =
|
|||
T_ForIn _ _ _ cmds -> [cmds]
|
||||
T_ForArithmetic _ _ _ _ cmds -> [cmds]
|
||||
T_IfExpression _ thens elses -> map snd thens ++ [elses]
|
||||
T_Annotation _ _ t -> getCommandSequences t
|
||||
_ -> []
|
||||
|
||||
-- Get a list of names of associative arrays
|
||||
|
|
|
@ -63,6 +63,7 @@ treeChecks = [
|
|||
,checkUnassignedReferences
|
||||
,checkUncheckedCdPushdPopd
|
||||
,checkArrayAssignmentIndices
|
||||
,checkUseBeforeDefinition
|
||||
]
|
||||
|
||||
runAnalytics :: AnalysisSpec -> [TokenComment]
|
||||
|
@ -1522,7 +1523,7 @@ prop_subshellAssignmentCheck19 = verifyNotTree subshellAssignmentCheck "#!/bin/b
|
|||
subshellAssignmentCheck params t =
|
||||
let flow = variableFlow params
|
||||
check = findSubshelled flow [("oops",[])] Map.empty
|
||||
in snd $ runWriter check
|
||||
in execWriter check
|
||||
|
||||
|
||||
findSubshelled [] _ _ = return ()
|
||||
|
@ -2832,5 +2833,36 @@ checkPipeToNowhere _ t =
|
|||
T_FdRedirect _ _ T_HereString {} -> True
|
||||
_ -> False
|
||||
|
||||
prop_checkUseBeforeDefinition1 = verifyTree checkUseBeforeDefinition "f; f() { true; }"
|
||||
prop_checkUseBeforeDefinition2 = verifyNotTree checkUseBeforeDefinition "f() { true; }; f"
|
||||
prop_checkUseBeforeDefinition3 = verifyNotTree checkUseBeforeDefinition "if ! mycmd --version; then mycmd() { true; }; fi"
|
||||
prop_checkUseBeforeDefinition4 = verifyNotTree checkUseBeforeDefinition "mycmd || mycmd() { f; }"
|
||||
checkUseBeforeDefinition _ t =
|
||||
execWriter $ evalStateT (mapM_ examine $ revCommands) Map.empty
|
||||
where
|
||||
examine t = case t of
|
||||
T_Pipeline _ _ [T_Redirecting _ _ (T_Function _ _ _ name _)] ->
|
||||
modify $ Map.insert name t
|
||||
T_Annotation _ _ w -> examine w
|
||||
T_Pipeline _ _ cmds -> do
|
||||
m <- get
|
||||
unless (Map.null m) $
|
||||
mapM_ (checkUsage m) $ concatMap recursiveSequences cmds
|
||||
_ -> return ()
|
||||
|
||||
checkUsage map cmd = potentially $ do
|
||||
name <- getCommandName cmd
|
||||
def <- Map.lookup name map
|
||||
return $
|
||||
err (getId cmd) 2218
|
||||
"This function is only defined later. Move the definition up."
|
||||
|
||||
revCommands = reverse $ concat $ getCommandSequences t
|
||||
recursiveSequences x =
|
||||
let list = concat $ getCommandSequences x in
|
||||
if null list
|
||||
then [x]
|
||||
else concatMap recursiveSequences list
|
||||
|
||||
return []
|
||||
runTests = $( [| $(forAllProperties) (quickCheckWithResult (stdArgs { maxSuccess = 1 }) ) |])
|
||||
|
|
Loading…
Reference in New Issue