Merge branch 'jabberabbe-iss1724-builtin-support'

This commit is contained in:
Vidar Holen 2019-12-21 18:50:52 -08:00
commit ce60a1764f
5 changed files with 20 additions and 3 deletions

View File

@ -3,6 +3,8 @@
- `-f diff` no longer claims that it found more issues when it didn't - `-f diff` no longer claims that it found more issues when it didn't
- Known empty variables now correctly trigger SC2086 - Known empty variables now correctly trigger SC2086
- ShellCheck should now be compatible with Cabal 3 - ShellCheck should now be compatible with Cabal 3
- SC2154 and all command-specific checks now trigger for builtins
called with `builtin`
### Added ### Added
- SC2254: Suggest quoting expansions in case statements - SC2254: Suggest quoting expansions in case statements

View File

@ -2189,6 +2189,7 @@ prop_checkUnassignedReferences35= verifyNotTree checkUnassignedReferences "echo
prop_checkUnassignedReferences36= verifyNotTree checkUnassignedReferences "read -a foo -r <<<\"foo bar\"; echo \"$foo\"" prop_checkUnassignedReferences36= verifyNotTree checkUnassignedReferences "read -a foo -r <<<\"foo bar\"; echo \"$foo\""
prop_checkUnassignedReferences37= verifyNotTree checkUnassignedReferences "var=howdy; printf -v 'array[0]' %s \"$var\"; printf %s \"${array[0]}\";" prop_checkUnassignedReferences37= verifyNotTree checkUnassignedReferences "var=howdy; printf -v 'array[0]' %s \"$var\"; printf %s \"${array[0]}\";"
prop_checkUnassignedReferences38= verifyTree (checkUnassignedReferences' True) "echo $VAR" prop_checkUnassignedReferences38= verifyTree (checkUnassignedReferences' True) "echo $VAR"
prop_checkUnassignedReferences39= verifyNotTree checkUnassignedReferences "builtin export var=4; echo $var"
checkUnassignedReferences = checkUnassignedReferences' False checkUnassignedReferences = checkUnassignedReferences' False
checkUnassignedReferences' includeGlobals params t = warnings checkUnassignedReferences' includeGlobals params t = warnings

View File

@ -567,9 +567,11 @@ getReferencedVariableCommand _ = []
-- VariableName :: String, -- The variable name, i.e. foo -- VariableName :: String, -- The variable name, i.e. foo
-- VariableValue :: DataType -- A description of the value being assigned, i.e. "Literal string with value foo" -- VariableValue :: DataType -- A description of the value being assigned, i.e. "Literal string with value foo"
-- ) -- )
getModifiedVariableCommand base@(T_SimpleCommand _ _ (T_NormalWord _ (T_Literal _ x:_):rest)) = getModifiedVariableCommand base@(T_SimpleCommand id cmdPrefix (T_NormalWord _ (T_Literal _ x:_):rest)) =
filter (\(_,_,s,_) -> not ("-" `isPrefixOf` s)) $ filter (\(_,_,s,_) -> not ("-" `isPrefixOf` s)) $
case x of case x of
"builtin" ->
getModifiedVariableCommand $ T_SimpleCommand id cmdPrefix rest
"read" -> "read" ->
let params = map getLiteral rest let params = map getLiteral rest
readArrayVars = getReadArrayVariables rest readArrayVars = getReadArrayVariables rest

View File

@ -122,12 +122,16 @@ buildCommandMap = foldl' addCheck Map.empty
checkCommand :: Map.Map CommandName (Token -> Analysis) -> Token -> Analysis checkCommand :: Map.Map CommandName (Token -> Analysis) -> Token -> Analysis
checkCommand map t@(T_SimpleCommand id _ (cmd:rest)) = fromMaybe (return ()) $ do checkCommand map t@(T_SimpleCommand id cmdPrefix (cmd:rest)) = fromMaybe (return ()) $ do
name <- getLiteralString cmd name <- getLiteralString cmd
return $ return $
if '/' `elem` name if '/' `elem` name
then then
Map.findWithDefault nullCheck (Basename $ basename name) map t Map.findWithDefault nullCheck (Basename $ basename name) map t
else if name == "builtin" && not (null rest) then
let t' = T_SimpleCommand id cmdPrefix rest
selectedBuiltin = fromMaybe "" $ getLiteralString . head $ rest
in Map.findWithDefault nullCheck (Exactly selectedBuiltin) map t'
else do else do
Map.findWithDefault nullCheck (Exactly name) map t Map.findWithDefault nullCheck (Exactly name) map t
Map.findWithDefault nullCheck (Basename name) map t Map.findWithDefault nullCheck (Basename name) map t

View File

@ -246,6 +246,10 @@ addParseNote n = do
parseNotes = n : parseNotes state parseNotes = n : parseNotes state
} }
ignoreProblemsOf p = do
systemState <- lift . lift $ Ms.get
p <* (lift . lift . Ms.put $ systemState)
shouldIgnoreCode code = do shouldIgnoreCode code = do
context <- getCurrentContexts context <- getCurrentContexts
checkSourced <- Mr.asks checkSourced checkSourced <- Mr.asks checkSourced
@ -2049,7 +2053,11 @@ readSimpleCommand = called "simple command" $ do
Just cmd -> do Just cmd -> do
validateCommand cmd validateCommand cmd
suffix <- option [] $ getParser readCmdSuffix cmd [ -- We have to ignore possible parsing problems from the lookAhead parser
firstArgument <- ignoreProblemsOf . optionMaybe . try . lookAhead $ readCmdWord
suffix <- option [] $ getParser readCmdSuffix
-- If `export` or other modifier commands are called with `builtin` we have to look at the first argument
(if isCommand ["builtin"] cmd && isJust firstArgument then fromJust firstArgument else cmd) [
(["declare", "export", "local", "readonly", "typeset"], readModifierSuffix), (["declare", "export", "local", "readonly", "typeset"], readModifierSuffix),
(["time"], readTimeSuffix), (["time"], readTimeSuffix),
(["let"], readLetSuffix), (["let"], readLetSuffix),