From 5242e384a11ce6855a4be8b23944634ee60fccfd Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Sun, 23 Jun 2019 13:47:35 -0700 Subject: [PATCH] Fix error spans for shebang warnings (fixes #1620) --- src/ShellCheck/AST.hs | 2 +- src/ShellCheck/Analytics.hs | 4 ++-- src/ShellCheck/AnalyzerLib.hs | 4 ++-- src/ShellCheck/Parser.hs | 24 ++++++++++++++---------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/ShellCheck/AST.hs b/src/ShellCheck/AST.hs index eb236ca..d8faec6 100644 --- a/src/ShellCheck/AST.hs +++ b/src/ShellCheck/AST.hs @@ -121,7 +121,7 @@ data Token = | T_Rbrace Id | T_Redirecting Id [Token] Token | T_Rparen Id - | T_Script Id String [Token] + | T_Script Id Token [Token] -- Shebang T_Literal, followed by script. | T_Select Id | T_SelectIn Id String [Token] [Token] | T_Semi Id diff --git a/src/ShellCheck/Analytics.hs b/src/ShellCheck/Analytics.hs index c2bcc78..e1523fd 100644 --- a/src/ShellCheck/Analytics.hs +++ b/src/ShellCheck/Analytics.hs @@ -534,7 +534,7 @@ indexOfSublists sub = f 0 prop_checkShebangParameters1 = verifyTree checkShebangParameters "#!/usr/bin/env bash -x\necho cow" prop_checkShebangParameters2 = verifyNotTree checkShebangParameters "#! /bin/sh -l " checkShebangParameters p (T_Annotation _ _ t) = checkShebangParameters p t -checkShebangParameters _ (T_Script id sb _) = +checkShebangParameters _ (T_Script _ (T_Literal id sb) _) = [makeComment ErrorC id 2096 "On most OS, shebangs can only specify a single parameter." | length (words sb) > 2] prop_checkShebang1 = verifyNotTree checkShebang "#!/usr/bin/env bash -x\necho cow" @@ -554,7 +554,7 @@ checkShebang params (T_Annotation _ list t) = where isOverride (ShellOverride _) = True isOverride _ = False -checkShebang params (T_Script id sb _) = execWriter $ do +checkShebang params (T_Script _ (T_Literal id sb) _) = execWriter $ do unless (shellTypeSpecified params) $ do when (sb == "") $ err id 2148 "Tips depend on target shell and yours is unknown. Add a shebang." diff --git a/src/ShellCheck/AnalyzerLib.hs b/src/ShellCheck/AnalyzerLib.hs index d99ea98..388f871 100644 --- a/src/ShellCheck/AnalyzerLib.hs +++ b/src/ShellCheck/AnalyzerLib.hs @@ -206,7 +206,7 @@ containsSetE root = isNothing $ doAnalysis (guard . not . isSetE) root where isSetE t = case t of - T_Script _ str _ -> str `matches` re + T_Script _ (T_Literal _ str) _ -> str `matches` re T_SimpleCommand {} -> t `isUnqualifiedCommand` "set" && ("errexit" `elem` oversimplify t || @@ -252,7 +252,7 @@ determineShell fallbackShell t = fromMaybe Bash $ do getCandidates (T_Annotation _ annotations s) = map forAnnotation annotations ++ [Just $ fromShebang s] - fromShebang (T_Script _ s t) = executableFromShebang s + fromShebang (T_Script _ (T_Literal _ s) _) = executableFromShebang s -- Given a string like "/bin/bash" or "/usr/bin/env dash", -- return the shell basename like "bash" or "dash" diff --git a/src/ShellCheck/Parser.hs b/src/ShellCheck/Parser.hs index c09d64c..cd4bc8f 100644 --- a/src/ShellCheck/Parser.hs +++ b/src/ShellCheck/Parser.hs @@ -2790,10 +2790,11 @@ readAssignmentWordExt lenient = try $ do string "=" >> return Assign ] - readEmptyLiteral = do - start <- startSpan - id <- endSpan start - return $ T_Literal id "" + +readEmptyLiteral = do + start <- startSpan + id <- endSpan start + return $ T_Literal id "" readArrayIndex = do start <- startSpan @@ -2941,12 +2942,14 @@ prop_readShebang5 = isWarning readShebang "\n#!/bin/sh" prop_readShebang6 = isWarning readShebang " # Copyright \n!#/bin/bash" prop_readShebang7 = isNotOk readShebang "# Copyright \nfoo\n#!/bin/bash" readShebang = do + start <- startSpan anyShebang <|> try readMissingBang <|> withHeader many linewhitespace str <- many $ noneOf "\r\n" + id <- endSpan start optional carriageReturn optional linefeed - return str + return $ T_Literal id str where anyShebang = choice $ map try [ readCorrect, @@ -3077,7 +3080,8 @@ readScriptFile sourced = do readUtf8Bom parseProblem ErrorC 1082 "This file has a UTF-8 BOM. Remove it with: LC_CTYPE=C sed '1s/^...//' < yourscript ." - sb <- option "" readShebang + shebang <- readShebang <|> readEmptyLiteral + let (T_Literal _ shebangString) = shebang allspacing annotationStart <- startSpan fileAnnotations <- readAnnotations @@ -3094,19 +3098,19 @@ readScriptFile sourced = do let ignoreShebang = shellAnnotationSpecified || shellFlagSpecified unless ignoreShebang $ - verifyShebang pos (getShell sb) - if ignoreShebang || isValidShell (getShell sb) /= Just False + verifyShebang pos (getShell shebangString) + if ignoreShebang || isValidShell (getShell shebangString) /= Just False then do commands <- withAnnotations annotations readCompoundListOrEmpty id <- endSpan start verifyEof let script = T_Annotation annotationId annotations $ - T_Script id sb commands + T_Script id shebang commands reparseIndices script else do many anyChar id <- endSpan start - return $ T_Script id sb [] + return $ T_Script id shebang [] where basename s = reverse . takeWhile (/= '/') . reverse $ s