Add support for basic shflags semantics
The shflags command-line flags library creates variables at runtime with a few well-defined functions. This causes shellcheck to spit out lots of warnings about unassigned variables, as well as miss warnings about unused flag variables. We can address this with two parts: 1. Pretend that the shflags global variables are predefined like other shell variables so that shellcheck doesn't expect users to set them. 2. Treat DEFINE_string, DEFINE_int, etc. as new commands that create variables, similar to the existing read, local, mapfile, etc. Part 1 can theoretically be addresssed without this by following sourced files, but that doesn't help if people are otherwise not following external sources. The new behavior is on by default, similar to automatic bats test behavior. Addresses #1597
This commit is contained in:
parent
c5aa171a5f
commit
f6ba500d6b
|
@ -9,6 +9,7 @@
|
||||||
- Source paths: Use `-P dir1:dir2` or a `source-path=dir1` directive
|
- Source paths: Use `-P dir1:dir2` or a `source-path=dir1` directive
|
||||||
to specify search paths for sourced files.
|
to specify search paths for sourced files.
|
||||||
- json1 format like --format=json but treats tabs as single characters
|
- json1 format like --format=json but treats tabs as single characters
|
||||||
|
- Recognize FLAGS variables created by the shflags library.
|
||||||
- SC2154: Also warn about unassigned uppercase variables (optional)
|
- SC2154: Also warn about unassigned uppercase variables (optional)
|
||||||
- SC2252: Warn about `[ $a != x ] || [ $a != y ]`, similar to SC2055
|
- SC2252: Warn about `[ $a != x ] || [ $a != y ]`, similar to SC2055
|
||||||
- SC2251: Inform about ineffectual ! in front of commands
|
- SC2251: Inform about ineffectual ! in front of commands
|
||||||
|
|
|
@ -2081,6 +2081,8 @@ prop_checkUnused38= verifyTree checkUnusedAssignments "(( a=42 ))"
|
||||||
prop_checkUnused39= verifyNotTree checkUnusedAssignments "declare -x -f foo"
|
prop_checkUnused39= verifyNotTree checkUnusedAssignments "declare -x -f foo"
|
||||||
prop_checkUnused40= verifyNotTree checkUnusedAssignments "arr=(1 2); num=2; echo \"${arr[@]:num}\""
|
prop_checkUnused40= verifyNotTree checkUnusedAssignments "arr=(1 2); num=2; echo \"${arr[@]:num}\""
|
||||||
prop_checkUnused41= verifyNotTree checkUnusedAssignments "@test 'foo' {\ntrue\n}\n"
|
prop_checkUnused41= verifyNotTree checkUnusedAssignments "@test 'foo' {\ntrue\n}\n"
|
||||||
|
prop_checkUnused42= verifyNotTree checkUnusedAssignments "DEFINE_string foo '' ''; echo \"${FLAGS_foo}\""
|
||||||
|
prop_checkUnused43= verifyTree checkUnusedAssignments "DEFINE_string foo '' ''"
|
||||||
checkUnusedAssignments params t = execWriter (mapM_ warnFor unused)
|
checkUnusedAssignments params t = execWriter (mapM_ warnFor unused)
|
||||||
where
|
where
|
||||||
flow = variableFlow params
|
flow = variableFlow params
|
||||||
|
|
|
@ -606,6 +606,11 @@ getModifiedVariableCommand base@(T_SimpleCommand _ _ (T_NormalWord _ (T_Literal
|
||||||
"mapfile" -> maybeToList $ getMapfileArray base rest
|
"mapfile" -> maybeToList $ getMapfileArray base rest
|
||||||
"readarray" -> maybeToList $ getMapfileArray base rest
|
"readarray" -> maybeToList $ getMapfileArray base rest
|
||||||
|
|
||||||
|
"DEFINE_boolean" -> maybeToList $ getFlagVariable rest
|
||||||
|
"DEFINE_float" -> maybeToList $ getFlagVariable rest
|
||||||
|
"DEFINE_integer" -> maybeToList $ getFlagVariable rest
|
||||||
|
"DEFINE_string" -> maybeToList $ getFlagVariable rest
|
||||||
|
|
||||||
_ -> []
|
_ -> []
|
||||||
where
|
where
|
||||||
flags = map snd $ getAllFlags base
|
flags = map snd $ getAllFlags base
|
||||||
|
@ -679,6 +684,12 @@ getModifiedVariableCommand base@(T_SimpleCommand _ _ (T_NormalWord _ (T_Literal
|
||||||
map (getLiteralArray . snd)
|
map (getLiteralArray . snd)
|
||||||
(filter (\(x,_) -> getLiteralString x == Just "-a") (zip (args) (tail args)))
|
(filter (\(x,_) -> getLiteralString x == Just "-a") (zip (args) (tail args)))
|
||||||
|
|
||||||
|
-- get the FLAGS_ variable created by a shflags DEFINE_ call
|
||||||
|
getFlagVariable (n:v:_) = return (base, n, flagName n, DataString $ SourceFrom [v])
|
||||||
|
where
|
||||||
|
flagName varName@(T_NormalWord _ _) = "FLAGS_" ++ (onlyLiteralString varName)
|
||||||
|
getFlagVariable _ = fail "Invalid flag definition"
|
||||||
|
|
||||||
getModifiedVariableCommand _ = []
|
getModifiedVariableCommand _ = []
|
||||||
|
|
||||||
getIndexReferences s = fromMaybe [] $ do
|
getIndexReferences s = fromMaybe [] $ do
|
||||||
|
|
|
@ -36,6 +36,11 @@ internalVariables = [
|
||||||
|
|
||||||
-- Ksh
|
-- Ksh
|
||||||
, ".sh.version"
|
, ".sh.version"
|
||||||
|
|
||||||
|
-- shflags
|
||||||
|
, "FLAGS_ARGC", "FLAGS_ARGV", "FLAGS_ERROR", "FLAGS_FALSE", "FLAGS_HELP",
|
||||||
|
"FLAGS_PARENT", "FLAGS_RESERVED", "FLAGS_TRUE", "FLAGS_VERSION",
|
||||||
|
"flags_error", "flags_return"
|
||||||
]
|
]
|
||||||
|
|
||||||
specialVariablesWithoutSpaces = [
|
specialVariablesWithoutSpaces = [
|
||||||
|
@ -45,6 +50,9 @@ variablesWithoutSpaces = specialVariablesWithoutSpaces ++ [
|
||||||
"BASHPID", "BASH_ARGC", "BASH_LINENO", "BASH_SUBSHELL", "EUID", "LINENO",
|
"BASHPID", "BASH_ARGC", "BASH_LINENO", "BASH_SUBSHELL", "EUID", "LINENO",
|
||||||
"OPTIND", "PPID", "RANDOM", "SECONDS", "SHELLOPTS", "SHLVL", "UID",
|
"OPTIND", "PPID", "RANDOM", "SECONDS", "SHELLOPTS", "SHLVL", "UID",
|
||||||
"COLUMNS", "HISTFILESIZE", "HISTSIZE", "LINES"
|
"COLUMNS", "HISTFILESIZE", "HISTSIZE", "LINES"
|
||||||
|
|
||||||
|
-- shflags
|
||||||
|
, "FLAGS_ERROR", "FLAGS_FALSE", "FLAGS_TRUE"
|
||||||
]
|
]
|
||||||
|
|
||||||
specialVariables = specialVariablesWithoutSpaces ++ ["@", "*"]
|
specialVariables = specialVariablesWithoutSpaces ++ ["@", "*"]
|
||||||
|
|
Loading…
Reference in New Issue