From aa33280cb043aa5bc84efef1fdfd1660775f15b0 Mon Sep 17 00:00:00 2001 From: Vidar Holen <spam@vidarholen.net> Date: Sat, 8 Jul 2017 14:00:02 -0700 Subject: [PATCH] Improve here doc diagnosis --- ShellCheck/Parser.hs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/ShellCheck/Parser.hs b/ShellCheck/Parser.hs index c490cf6..565cefd 100644 --- a/ShellCheck/Parser.hs +++ b/ShellCheck/Parser.hs @@ -1609,6 +1609,10 @@ prop_readHereDoc10= isOk readScript "if true; then cat << foo << bar; fi\nfoo\nb prop_readHereDoc11= isOk readScript "cat << foo $(\nfoo\n)lol\nfoo\n" prop_readHereDoc12= isOk readScript "cat << foo|cat\nbar\nfoo" prop_readHereDoc13= isOk readScript "cat <<'#!'\nHello World\n#!\necho Done" +prop_readHereDoc14= isWarning readScript "cat << foo\nbar\nfoo \n" +prop_readHereDoc15= isWarning readScript "cat <<foo\nbar\nfoo bar\n" +prop_readHereDoc16= isOk readScript "cat <<- ' foo'\nbar\n foo\n" +prop_readHereDoc17= isWarning readScript "cat <<- ' foo'\nbar\n foo\n" readHereDoc = called "here document" $ do fid <- getNextId pos <- getPosition @@ -1642,20 +1646,37 @@ readPendingHereDocs = do where readDoc (T_HereDoc id dashed quoted endToken _) = do pos <- getPosition - hereData <- anyChar `reluctantlyTill` do - many linewhitespace + hereData <- concat <$> rawLine `reluctantlyTill` do + linewhitespace `reluctantlyTill` string endToken string endToken - void (char '\n') <|> eof + void linewhitespace <|> void (oneOf "\n;&#)") <|> eof do - spaces <- many linewhitespace + spaces <- linewhitespace `reluctantlyTill` string endToken verifyHereDoc dashed quoted spaces hereData string endToken + trailingPos <- getPosition + trailers <- lookAhead $ many (noneOf "\n") + let ppt = parseProblemAt trailingPos ErrorC + unless (null trailers) $ + if all isSpace trailers + then ppt 1118 "Delete whitespace after the here-doc end token." + else case (head $ dropWhile isSpace trailers) of + ')' -> ppt 1119 $ "Add a linefeed between end token and terminating ')'." + '#' -> ppt 1120 "No comments allowed after here-doc token. Comment the next line instead." + c | c `elem` ";&" -> + ppt 1121 "Add ;/& terminators (and other syntax) on the line with the <<, not here." + _ -> ppt 1122 "Nothing allowed after end token. To continue a command, put it on the line with the <<." parsedData <- parseHereData quoted pos hereData list <- parseHereData quoted pos hereData addToHereDocMap id list `attempting` (eof >> debugHereDoc pos endToken hereData) + rawLine = do + c <- many $ noneOf "\n" + void (char '\n') <|> eof + return $ c ++ "\n" + parseHereData Quoted startPos hereData = do id <- getNextIdAt startPos return [T_Literal id hereData] @@ -1682,7 +1703,7 @@ readPendingHereDocs = do let lookAt line = when (endToken `isInfixOf` line) $ parseProblemAt pos ErrorC 1041 ("Close matches include '" ++ line ++ "' (!= '" ++ endToken ++ "').") in do - parseProblemAt pos ErrorC 1042 ("Found '" ++ endToken ++ "' further down, but not entirely by itself.") + parseProblemAt pos ErrorC 1042 ("Found '" ++ endToken ++ "' further down, but not on a separate line.") mapM_ lookAt (lines doc) | map toLower endToken `isInfixOf` map toLower doc = parseProblemAt pos ErrorC 1043 ("Found " ++ endToken ++ " further down, but with wrong casing.")