From b5ffafce9375e8e0dc87b3de9910888bb4755e94 Mon Sep 17 00:00:00 2001 From: Eljees <3.14hell@gmail.com> Date: Sun, 9 Aug 2026 16:22:25 +0000 Subject: [PATCH] Treat compgen -V as assigning to an array compgen -V arr (bash 5.3) stores the completions in the array arr instead of printing them, but getModifiedVariableCommand did not know about it, so `compgen -V files -G '*'` followed by "${files[@]}" produced a spurious SC2154 "files is referenced but not assigned". Add a compgen entry next to mapfile/readarray and a helper shaped like the existing getPrintfVariable/getWaitVariable: parse the flags, take the argument of -V and record it as DataArray. Fixes #3466 --- src/ShellCheck/Analytics.hs | 2 ++ src/ShellCheck/AnalyzerLib.hs | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/ShellCheck/Analytics.hs b/src/ShellCheck/Analytics.hs index f6208e72b..2b15e368c 100644 --- a/src/ShellCheck/Analytics.hs +++ b/src/ShellCheck/Analytics.hs @@ -2534,6 +2534,8 @@ prop_checkUnassignedReferences50 = verifyNotTree checkUnassignedReferences "echo prop_checkUnassignedReferences51 = verifyNotTree checkUnassignedReferences "echo ${foo:+$foo}" prop_checkUnassignedReferences52 = verifyNotTree checkUnassignedReferences "wait -p pid; echo $pid" prop_checkUnassignedReferences53 = verifyTree checkUnassignedReferences "x=($foo)" +prop_checkUnassignedReferences54 = verifyNotTree checkUnassignedReferences "compgen -V files -G '*'; echo \"${files[@]}\"" +prop_checkUnassignedReferences55 = verifyNotTree checkUnassignedReferences "compgen -A function -V funcs; echo \"${funcs[@]}\"" checkUnassignedReferences = checkUnassignedReferences' False checkUnassignedReferences' includeGlobals params t = warnings diff --git a/src/ShellCheck/AnalyzerLib.hs b/src/ShellCheck/AnalyzerLib.hs index f6d7defd7..7beb7f78d 100644 --- a/src/ShellCheck/AnalyzerLib.hs +++ b/src/ShellCheck/AnalyzerLib.hs @@ -683,6 +683,7 @@ getModifiedVariableCommand base@(T_SimpleCommand id cmdPrefix (T_NormalWord _ (T "mapfile" -> maybeToList $ getMapfileArray base rest "readarray" -> maybeToList $ getMapfileArray base rest + "compgen" -> maybeToList $ getCompgenArray rest "DEFINE_boolean" -> maybeToList $ getFlagVariable rest "DEFINE_float" -> maybeToList $ getFlagVariable rest @@ -742,6 +743,14 @@ getModifiedVariableCommand base@(T_SimpleCommand id cmdPrefix (T_NormalWord _ (T getPrintfVariable list = getFlagAssignedVariable "v" (SourceFrom list) $ getBsdOpts "v:" list getWaitVariable list = getFlagAssignedVariable "p" SourceInteger $ return $ getGenericOpts list + -- compgen -V arr stores the completions in the array arr rather than printing them + getCompgenArray list = do + flags <- getGnuOpts "abcdefgjksuvo:A:C:F:G:P:S:V:W:X:" list + (_, (_, value)) <- find ((== "V") . fst) flags + name <- getLiteralString value + guard $ isVariableName name + return (base, value, name, DataArray SourceExternal) + getFlagAssignedVariable str dataSource maybeFlags = do flags <- maybeFlags (_, (flag, value)) <- find ((== str) . fst) flags