From 1a3f6aadafd48c35198a4ed055706e608831a4b8 Mon Sep 17 00:00:00 2001 From: Vidar Holen Date: Sun, 22 Jun 2014 10:35:45 -0700 Subject: [PATCH] Support indices in array declarations --- ShellCheck/AST.hs | 4 ++++ ShellCheck/Analytics.hs | 4 ++++ ShellCheck/Parser.hs | 20 ++++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ShellCheck/AST.hs b/ShellCheck/AST.hs index b82f775..91337b5 100644 --- a/ShellCheck/AST.hs +++ b/ShellCheck/AST.hs @@ -47,6 +47,8 @@ data Token = | T_AndIf Id (Token) (Token) | T_Arithmetic Id Token | T_Array Id [Token] + | T_IndexedElement Id Token Token + | T_ Id [Token] | T_Assignment Id AssignmentMode String (Maybe Token) Token | T_Backgrounded Id Token | T_Backticked Id [Token] @@ -177,6 +179,7 @@ analyze f g i = b <- round value return $ T_Assignment id mode var a b delve (T_Array id t) = dl t $ T_Array id + delve (T_IndexedElement id t1 t2) = d2 t1 t2 $ T_IndexedElement id delve (T_Redirecting id redirs cmd) = do a <- roundAll redirs b <- round cmd @@ -294,6 +297,7 @@ getId t = case t of T_FdRedirect id _ _ -> id T_Assignment id _ _ _ _ -> id T_Array id _ -> id + T_IndexedElement id _ _ -> id T_Redirecting id _ _ -> id T_SimpleCommand id _ _ -> id T_Pipeline id _ _ -> id diff --git a/ShellCheck/Analytics.hs b/ShellCheck/Analytics.hs index abd6043..7ed43be 100644 --- a/ShellCheck/Analytics.hs +++ b/ShellCheck/Analytics.hs @@ -1229,10 +1229,13 @@ prop_checkCommarrays1 = verify checkCommarrays "a=(1, 2)" prop_checkCommarrays2 = verify checkCommarrays "a+=(1,2,3)" prop_checkCommarrays3 = verifyNot checkCommarrays "cow=(1 \"foo,bar\" 3)" prop_checkCommarrays4 = verifyNot checkCommarrays "cow=('one,' 'two')" +prop_checkCommarrays5 = verify checkCommarrays "a=([a]=b, [c]=d)" +prop_checkCommarrays6 = verify checkCommarrays "a=([a]=b,[c]=d,[e]=f)" checkCommarrays _ (T_Array id l) = when (any (isCommaSeparated . literal) l) $ warn id 2054 "Use spaces, not commas, to separate array elements." where + literal (T_IndexedElement _ _ l) = literal l literal (T_NormalWord _ l) = concatMap literal l literal (T_Literal _ str) = str literal _ = "str" @@ -2261,6 +2264,7 @@ prop_checkUnused14= verifyNotTree checkUnusedAssignments "x=(1); n=0; echo ${x[n prop_checkUnused15= verifyNotTree checkUnusedAssignments "x=(1); n=0; (( x[n] ))" prop_checkUnused16= verifyNotTree checkUnusedAssignments "foo=5; declare -x foo" prop_checkUnused17= verifyNotTree checkUnusedAssignments "read -i 'foo' -e -p 'Input: ' bar; $bar;" +prop_checkUnused18= verifyNotTree checkUnusedAssignments "a=1; arr=( [$a]=42 ); echo \"${arr[@]}\"" checkUnusedAssignments params t = snd $ runWriter (mapM_ checkAssignment flow) where flow = variableFlow params diff --git a/ShellCheck/Parser.hs b/ShellCheck/Parser.hs index 5e04ced..4aa18f8 100644 --- a/ShellCheck/Parser.hs +++ b/ShellCheck/Parser.hs @@ -1791,7 +1791,8 @@ prop_readAssignmentWord6 = isWarning readAssignmentWord "b += (1 2 3)" prop_readAssignmentWord7 = isOk readAssignmentWord "a[3$n'']=42" prop_readAssignmentWord8 = isOk readAssignmentWord "a[4''$(cat foo)]=42" prop_readAssignmentWord9 = isOk readAssignmentWord "IFS= " -prop_readAssignmentWord0 = isWarning readAssignmentWord "foo$n=42" +prop_readAssignmentWord10= isWarning readAssignmentWord "foo$n=42" +prop_readAssignmentWord11= isOk readAssignmentWord "foo=([a]=b [c] [d]= [e f )" readAssignmentWord = try $ do id <- getNextId pos <- getPosition @@ -1842,9 +1843,24 @@ readArray = called "array assignment" $ do id <- getNextId char '(' allspacing - words <- (readNormalWord `thenSkip` allspacing) `reluctantlyTill` char ')' + words <- readElement `reluctantlyTill` char ')' char ')' return $ T_Array id words + where + readElement = (readIndexed <|> readRegular) `thenSkip` allspacing + readIndexed = do + id <- getNextId + index <- try $ do + x <- readArrayIndex + char '=' + return x + value <- readNormalWord <|> nothing + return $ T_IndexedElement id index value + readRegular = readNormalWord + + nothing = do + id <- getNextId + return $ T_Literal id "" tryToken s t = try $ do id <- getNextId