From 58783ab3cc11ff30466f185a88b1ebb2f1bf19f5 Mon Sep 17 00:00:00 2001
From: Vidar Holen <spam@vidarholen.net>
Date: Tue, 1 Sep 2020 16:22:15 -0700
Subject: [PATCH] Allow specifying ranges in disable directives

---
 CHANGELOG.md             |  1 +
 shellcheck.1.md          |  3 ++-
 src/ShellCheck/AST.hs    |  2 +-
 src/ShellCheck/ASTLib.hs |  2 +-
 src/ShellCheck/Parser.hs | 11 ++++++++---
 5 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5db445b..53f63da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
 ## Git
 ### Added
+- `disable` directives can now be a range, e.g. `disable=SC3000-SC4000`
 - SC2259/SC2260: Warn when redirections override pipes
 - SC2261: Warn about multiple competing redirections
 - SC2262/SC2263: Warn about aliases declared and used in the same parsing unit
diff --git a/shellcheck.1.md b/shellcheck.1.md
index 6d2a732..d038df2 100644
--- a/shellcheck.1.md
+++ b/shellcheck.1.md
@@ -232,7 +232,8 @@ Valid keys are:
 **disable**
 :   Disables a comma separated list of error codes for the following command.
     The command can be a simple command like `echo foo`, or a compound command
-    like a function definition, subshell block or loop.
+    like a function definition, subshell block or loop. A range can be
+    be specified with a dash, e.g. `disable=SC3000-SC4000` to exclude 3xxx.
 
 **enable**
 :   Enable an optional check by name, as listed with **--list-optional**.
diff --git a/src/ShellCheck/AST.hs b/src/ShellCheck/AST.hs
index d4151fe..52b6e17 100644
--- a/src/ShellCheck/AST.hs
+++ b/src/ShellCheck/AST.hs
@@ -145,7 +145,7 @@ data InnerToken t =
     deriving (Show, Eq, Functor, Foldable, Traversable)
 
 data Annotation =
-    DisableComment Integer
+    DisableComment Integer Integer -- [from, to)
     | EnableComment String
     | SourceOverride String
     | ShellOverride String
diff --git a/src/ShellCheck/ASTLib.hs b/src/ShellCheck/ASTLib.hs
index 29feb1e..0052ef5 100644
--- a/src/ShellCheck/ASTLib.hs
+++ b/src/ShellCheck/ASTLib.hs
@@ -567,5 +567,5 @@ isAnnotationIgnoringCode code t =
         T_Annotation _ anns _ -> any hasNum anns
         _ -> False
   where
-    hasNum (DisableComment ts) = code == ts
+    hasNum (DisableComment from to) = code >= from && code < to
     hasNum _                   = False
diff --git a/src/ShellCheck/Parser.hs b/src/ShellCheck/Parser.hs
index 4806b18..87efa25 100644
--- a/src/ShellCheck/Parser.hs
+++ b/src/ShellCheck/Parser.hs
@@ -270,7 +270,7 @@ contextItemDisablesCode alsoCheckSourced code = disabling alsoCheckSourced
             ContextAnnotation list -> any disabling' list
             ContextSource _ -> not $ checkSourced
             _ -> False
-    disabling' (DisableComment n) = code == n
+    disabling' (DisableComment n m) = code >= n && code < m
     disabling' _ = False
 
 
@@ -973,6 +973,7 @@ prop_readAnnotation3 = isOk readAnnotation "# shellcheck disable=SC1234 source=/
 prop_readAnnotation4 = isWarning readAnnotation "# shellcheck cats=dogs disable=SC1234\n"
 prop_readAnnotation5 = isOk readAnnotation "# shellcheck disable=SC2002 # All cats are precious\n"
 prop_readAnnotation6 = isOk readAnnotation "# shellcheck disable=SC1234 # shellcheck foo=bar\n"
+prop_readAnnotation7 = isOk readAnnotation "# shellcheck disable=SC1000,SC2000-SC3000,SC1001\n"
 readAnnotation = called "shellcheck directive" $ do
     try readAnnotationPrefix
     many1 linewhitespace
@@ -993,12 +994,16 @@ readAnnotationWithoutPrefix = do
         key <- many1 (letter <|> char '-')
         char '=' <|> fail "Expected '=' after directive key"
         annotations <- case key of
-            "disable" -> readCode `sepBy` char ','
+            "disable" -> readRange `sepBy` char ','
               where
+                readRange = do
+                    from <- readCode
+                    to <- choice [ char '-' *> readCode, return $ from+1 ]
+                    return $ DisableComment from to
                 readCode = do
                     optional $ string "SC"
                     int <- many1 digit
-                    return $ DisableComment (read int)
+                    return $ read int
 
             "enable" -> readName `sepBy` char ','
               where