mirror of
https://github.com/koalaman/shellcheck.git
synced 2025-08-10 20:23:26 +08:00
More robust fi/done mixup reporting
This commit is contained in:
@@ -152,6 +152,9 @@ reluctantlyTill1 p end = do
|
|||||||
attempting rest branch = do
|
attempting rest branch = do
|
||||||
((try branch) >> rest) <|> rest
|
((try branch) >> rest) <|> rest
|
||||||
|
|
||||||
|
orFail parser stuff = do
|
||||||
|
try (disregard parser) <|> (disregard stuff >> fail "nope")
|
||||||
|
|
||||||
wasIncluded p = option False (p >> return True)
|
wasIncluded p = option False (p >> return True)
|
||||||
|
|
||||||
acceptButWarn parser level note = do
|
acceptButWarn parser level note = do
|
||||||
@@ -887,11 +890,11 @@ readIfClause = do
|
|||||||
(condition, action) <- readIfPart
|
(condition, action) <- readIfPart
|
||||||
elifs <- many readElifPart
|
elifs <- many readElifPart
|
||||||
elses <- option [] readElsePart
|
elses <- option [] readElsePart
|
||||||
g_Fi <|> (do
|
|
||||||
eof
|
g_Fi `orFail` do
|
||||||
parseProblemAt pos ErrorC "Can't find 'fi' for this if. Make sure it's preceeded by a ; or \\n."
|
parseProblemAt pos ErrorC "Couldn't find 'fi' for this 'if'."
|
||||||
fail "lol"
|
parseProblem ErrorC "Expected 'fi' matching previously mentioned 'if'."
|
||||||
)
|
|
||||||
return $ T_IfExpression id ((condition, action):elifs) elses
|
return $ T_IfExpression id ((condition, action):elifs) elses
|
||||||
|
|
||||||
readIfPart = do
|
readIfPart = do
|
||||||
@@ -899,7 +902,9 @@ readIfPart = do
|
|||||||
allspacing
|
allspacing
|
||||||
pos <- getPosition
|
pos <- getPosition
|
||||||
condition <- readTerm
|
condition <- readTerm
|
||||||
g_Then
|
g_Then `attempting` (do
|
||||||
|
try . lookAhead $ g_Do
|
||||||
|
parseProblem ErrorC "Perhaps you meant 'then'?")
|
||||||
acceptButWarn g_Semi ErrorC "No semicolons directly after 'then'."
|
acceptButWarn g_Semi ErrorC "No semicolons directly after 'then'."
|
||||||
allspacing
|
allspacing
|
||||||
action <- readTerm
|
action <- readTerm
|
||||||
@@ -963,34 +968,19 @@ readUntilClause = do
|
|||||||
|
|
||||||
readDoGroup = do
|
readDoGroup = do
|
||||||
pos <- getPosition
|
pos <- getPosition
|
||||||
g_Do
|
optional (do
|
||||||
allspacing
|
try . lookAhead $ g_Then
|
||||||
(eof >> return []) <|>
|
parseProblem ErrorC "Perhaps you meant 'do'.")
|
||||||
do
|
|
||||||
commands <- readCompoundList
|
|
||||||
disregard g_Done <|> (do
|
|
||||||
eof
|
|
||||||
case hasFinal "done" commands of
|
|
||||||
Nothing -> parseProblemAt pos ErrorC "Couldn't find a 'done' for this 'do'."
|
|
||||||
Just (id) -> addNoteFor id $ Note ErrorC "Put a ; or \\n before the done."
|
|
||||||
)
|
|
||||||
return commands
|
|
||||||
<|> do
|
|
||||||
parseProblemAt pos ErrorC "Can't find the 'done' for this 'do'."
|
|
||||||
fail "No done"
|
|
||||||
|
|
||||||
hasFinal s [] = Nothing
|
g_Do
|
||||||
hasFinal s f =
|
acceptButWarn g_Semi ErrorC "No semicolons directly after 'do'."
|
||||||
case last f of
|
allspacing
|
||||||
T_Pipeline _ m@(_:_) ->
|
|
||||||
case last m of
|
commands <- readCompoundList
|
||||||
T_Redirecting _ [] (T_SimpleCommand _ _ m@(_:_)) ->
|
g_Done `orFail` do
|
||||||
case last m of
|
parseProblemAt pos ErrorC "Couldn't find 'done' for this 'do'."
|
||||||
T_NormalWord _ [T_Literal id str] ->
|
parseProblem ErrorC "Expected 'done' matching previously mentioned 'do'."
|
||||||
if str == s then Just id else Nothing
|
return commands
|
||||||
_ -> Nothing
|
|
||||||
_ -> Nothing
|
|
||||||
_ -> Nothing
|
|
||||||
|
|
||||||
|
|
||||||
prop_readForClause = isOk readForClause "for f in *; do rm \"$f\"; done"
|
prop_readForClause = isOk readForClause "for f in *; do rm \"$f\"; done"
|
||||||
@@ -1233,7 +1223,7 @@ getStringFromParsec errors =
|
|||||||
Message s -> (4, "Message: " ++ s)
|
Message s -> (4, "Message: " ++ s)
|
||||||
wut "" = "eof"
|
wut "" = "eof"
|
||||||
wut x = x
|
wut x = x
|
||||||
unexpected s = "Aborting due to unexpected " ++ (wut s) ++ ". Is this even valid?"
|
unexpected s = "Aborting due to unexpected " ++ (wut s) ++ ". Fix any mentioned problems and try again."
|
||||||
|
|
||||||
parseShell filename contents = do
|
parseShell filename contents = do
|
||||||
case rp (parseWithNotes readScript) filename contents of
|
case rp (parseWithNotes readScript) filename contents of
|
||||||
|
Reference in New Issue
Block a user