Add json1 format that ignores tabs

The new json1 format works just like json except that it treats tabs as
single characters instead of 8-character tabstops.

The main use case is to allow editors to pass -fjson1 so that they can
consume the json output in a character-oriented way without breaking
backwards compatibility.

Also addresses #1048.
This commit is contained in:
Benjamin Gordon 2019-05-07 15:49:34 -06:00
parent 5fb1da6814
commit 50af8aba29
5 changed files with 33 additions and 7 deletions

View File

@ -7,6 +7,7 @@
Enable with `-o` flags or `enable=name` directives
- Source paths: Use `-P dir1:dir2` or a `source-path=dir1` directive
to specify search paths for sourced files.
- json1 format like --format=json but treats tabs as single characters
- SC2249: Warn about `case` with missing default case (verbose)
- SC2248: Warn about unquoted variables without special chars (verbose)
- SC2247: Warn about $"(cmd)" and $"{var}"

View File

@ -153,7 +153,7 @@ not warn at all, as `ksh` supports decimals in arithmetic contexts.
: Json is a popular serialization format that is more suitable for web
applications. ShellCheck's json is compact and contains only the bare
minimum.
minimum. Tabs are 8 characters.
[
{
@ -167,6 +167,11 @@ not warn at all, as `ksh` supports decimals in arithmetic contexts.
...
]
**json1**
: This is the same as shellcheck's json format, but tabs are treated as
single characters instead of 8-character tabstops.
*quiet*
: Suppress all normal output. Exit with zero if no issues are found,

View File

@ -141,7 +141,8 @@ formats :: FormatterOptions -> Map.Map String (IO Formatter)
formats options = Map.fromList [
("checkstyle", ShellCheck.Formatter.CheckStyle.format),
("gcc", ShellCheck.Formatter.GCC.format),
("json", ShellCheck.Formatter.JSON.format),
("json", ShellCheck.Formatter.JSON.format False), -- JSON with 8-char tabs
("json1", ShellCheck.Formatter.JSON.format True), -- JSON with 1-char tabs
("tty", ShellCheck.Formatter.TTY.format options),
("quiet", ShellCheck.Formatter.Quiet.format options)
]

View File

@ -22,6 +22,7 @@ module ShellCheck.Formatter.Format where
import ShellCheck.Data
import ShellCheck.Interface
import ShellCheck.Fixer
import Control.Monad
import Data.Array
-- A formatter that carries along an arbitrary piece of data
@ -54,5 +55,10 @@ makeNonVirtual comments contents =
where
list = lines contents
arr = listArray (1, length list) list
fix c = removeTabStops c arr
untabbedFix f = newFix {
fixReplacements = map (\r -> removeTabStops r arr) (fixReplacements f)
}
fix c = (removeTabStops c arr) {
pcFix = liftM untabbedFix (pcFix c)
}

View File

@ -30,11 +30,12 @@ import GHC.Exts
import System.IO
import qualified Data.ByteString.Lazy.Char8 as BL
format = do
format :: Bool -> IO Formatter
format removeTabs = do
ref <- newIORef []
return Formatter {
header = return (),
onResult = collectResult ref,
onResult = collectResult removeTabs ref,
onFailure = outputError,
footer = finish ref
}
@ -96,8 +97,20 @@ instance ToJSON Fix where
]
outputError file msg = hPutStrLn stderr $ file ++ ": " ++ msg
collectResult ref result _ =
modifyIORef ref (\x -> crComments result ++ x)
collectResult removeTabs ref cr sys = mapM_ f groups
where
comments = crComments cr
groups = groupWith sourceFile comments
f :: [PositionedComment] -> IO ()
f group = do
let filename = sourceFile (head group)
result <- siReadFile sys filename
let contents = either (const "") id result
let comments' = if removeTabs
then makeNonVirtual comments contents
else comments
modifyIORef ref (\x -> comments' ++ x)
finish ref = do
list <- readIORef ref