Allow to customize the TODO marker string
This commit is contained in:
parent
461f34a100
commit
4514d0f120
5 changed files with 61 additions and 28 deletions
21
README.md
21
README.md
|
|
@ -46,11 +46,13 @@ A tool to semi-automatically add Coverity source-code annotations based on found
|
||||||
|
|
||||||
-v --verbose be more verbose, pass multiple times to increase verbosity
|
-v --verbose be more verbose, pass multiple times to increase verbosity
|
||||||
-i --inplace replace source-file after inserting annotations
|
-i --inplace replace source-file after inserting annotations
|
||||||
-V --version show version
|
-V --version show full version information
|
||||||
--short-version show version
|
--short-version show just the version number
|
||||||
-h --help show usage information
|
-h --help show usage information
|
||||||
-a --all handle all defects not just Newest
|
-a --all handle all defects not just Newest
|
||||||
-C[NUM] --context[=NUM] specify how much context should be shown around a violation
|
-C[NUM] --context[=NUM] specify how much context should be shown around a violation
|
||||||
|
-t[STRING] --todo-marker[=STRING] override the default TODO marker with a custom string
|
||||||
|
-A FILE --annotations=FILE load automatic annotation rules
|
||||||
```
|
```
|
||||||
|
|
||||||
### In-place annotations
|
### In-place annotations
|
||||||
|
|
@ -65,3 +67,18 @@ By default the annotator will only handle *Newest* violations and not those that
|
||||||
are already contained within the Coverity database for some reason. However,
|
are already contained within the Coverity database for some reason. However,
|
||||||
it's still possible to process all found violations by passing `-a` or `--all`
|
it's still possible to process all found violations by passing `-a` or `--all`
|
||||||
on the command-line.
|
on the command-line.
|
||||||
|
|
||||||
|
### Insert annotations automatically
|
||||||
|
|
||||||
|
In case you have violations that always result in the same annotation over and
|
||||||
|
over again, you can supply one or more files that contain automatic decisions.
|
||||||
|
|
||||||
|
Each line may be one of the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
Intentional (Rule "autosar_cpp14_a18_9_1") "reason why it's intentional"
|
||||||
|
FalsePositive (Rule "autosar_cpp14_a18_9_1") "reason why it's a false-positive"
|
||||||
|
ToDo (Rule "autosar_cpp14_a18_9_1")
|
||||||
|
```
|
||||||
|
|
||||||
|
Lines may be disabled by prefixing them with `#` or `--`.
|
||||||
|
|
|
||||||
|
|
@ -1 +1,4 @@
|
||||||
Intentional (Rule "autosar_cpp14_a18_9_1") "Test auto"
|
Intentional (Rule "autosar_cpp14_a18_9_1") "Test intentional auto"
|
||||||
|
--FalsePositive (Rule "autosar_cpp14_a18_9_2") "Test false auto"
|
||||||
|
ToDo (Rule "autosar_cpp14_a18_9_3")
|
||||||
|
#ToDo (Rule "autosar_cpp14_a18_9_4")
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import Annotator.Rule
|
||||||
import Annotator.Annotation
|
import Annotator.Annotation
|
||||||
|
|
||||||
version :: Vsn.Version
|
version :: Vsn.Version
|
||||||
version = Vsn.makeVersion [0,0,3,0]
|
version = Vsn.makeVersion [0,0,4,0]
|
||||||
|
|
||||||
type App a = ReaderT Options IO a
|
type App a = ReaderT Options IO a
|
||||||
|
|
||||||
|
|
@ -54,6 +54,7 @@ data Options = Options
|
||||||
, onlyNewest :: Bool
|
, onlyNewest :: Bool
|
||||||
, annotationFiles :: [FilePath]
|
, annotationFiles :: [FilePath]
|
||||||
, autoAnnotations :: [Annotation]
|
, autoAnnotations :: [Annotation]
|
||||||
|
, todoMarker :: String
|
||||||
}
|
}
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
|
@ -67,6 +68,7 @@ defaultOptions = Options
|
||||||
, onlyNewest = True
|
, onlyNewest = True
|
||||||
, annotationFiles = []
|
, annotationFiles = []
|
||||||
, autoAnnotations = []
|
, autoAnnotations = []
|
||||||
|
, todoMarker = "TODO"
|
||||||
}
|
}
|
||||||
|
|
||||||
options :: [OptDescr (Options -> Options)]
|
options :: [OptDescr (Options -> Options)]
|
||||||
|
|
@ -90,11 +92,22 @@ options =
|
||||||
(NoArg (\opts -> opts { onlyNewest = False}))
|
(NoArg (\opts -> opts { onlyNewest = False}))
|
||||||
"handle all defects not just Newest"
|
"handle all defects not just Newest"
|
||||||
, Option ['C'] ["context"]
|
, Option ['C'] ["context"]
|
||||||
(OptArg ((\f opts -> opts { contextLines = fromMaybe 0 $ readMaybe f }) . fromMaybe "0") "NUM")
|
(OptArg (\f opts -> opts { contextLines = fromMaybe 0 (f >>= readMaybe) }) "NUM")
|
||||||
"specify how much context should be shown around a violation"
|
"specify how much context should be shown around a violation"
|
||||||
|
, Option ['t'] ["todo-marker"]
|
||||||
|
(OptArg (\f opts -> opts { todoMarker = fromMaybe "TODO" f }) "STRING")
|
||||||
|
"override the default TODO marker with a custom string"
|
||||||
, Option ['A'] ["annotations"]
|
, Option ['A'] ["annotations"]
|
||||||
(ReqArg (\f opts -> opts { annotationFiles = (nub $ annotationFiles opts ++ [f]) }) "FILE")
|
(ReqArg (\f opts -> opts { annotationFiles = (nub $ annotationFiles opts ++ [f]) }) "FILE")
|
||||||
"load automatic annotation rules"
|
(unlines [ "load automatic annotation rules"
|
||||||
|
, " some examples:"
|
||||||
|
, " " <> show (Intentional (Rule "rule_1") "some reason")
|
||||||
|
, " " <> show (FalsePositive (Rule "rule_1") "some reason")
|
||||||
|
, " " <> show (ToDo (Rule "rule_1"))
|
||||||
|
, " # a comment"
|
||||||
|
, " -- another comment"
|
||||||
|
]
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
readMaybe :: (Read a) => String -> Maybe a
|
readMaybe :: (Read a) => String -> Maybe a
|
||||||
|
|
@ -230,6 +243,7 @@ handleViolations violations = do
|
||||||
opts <- ask
|
opts <- ask
|
||||||
let fname = filename $ NE.head violations
|
let fname = filename $ NE.head violations
|
||||||
fname' = fname <> ".fix"
|
fname' = fname <> ".fix"
|
||||||
|
todo = todoMarker opts
|
||||||
header' = "Processing " <> (show $ NE.length violations) <> " violation(s) in file " <> fname
|
header' = "Processing " <> (show $ NE.length violations) <> " violation(s) in file " <> fname
|
||||||
header = unlines
|
header = unlines
|
||||||
[ header'
|
[ header'
|
||||||
|
|
@ -252,7 +266,7 @@ handleViolations violations = do
|
||||||
|
|
||||||
annotations <- (catMaybes . NE.toList) <$> mapM (handleViolation content) violations
|
annotations <- (catMaybes . NE.toList) <$> mapM (handleViolation content) violations
|
||||||
|
|
||||||
let annotatedLines = sortBy (comparing fst) $ fmap annotationToLine annotations
|
let annotatedLines = sortBy (comparing fst) $ fmap (annotationToLine todo) annotations
|
||||||
newContent = unlines . map snd $ mergeLines annotatedLines numberedContent
|
newContent = unlines . map snd $ mergeLines annotatedLines numberedContent
|
||||||
|
|
||||||
liftIO $ writeFile fname' newContent
|
liftIO $ writeFile fname' newContent
|
||||||
|
|
@ -261,10 +275,14 @@ handleViolations violations = do
|
||||||
else do
|
else do
|
||||||
verbose Low $ "skipping non-existent file " <> fname
|
verbose Low $ "skipping non-existent file " <> fname
|
||||||
where
|
where
|
||||||
annotationToLine :: AnnotatedViolation -> (Int, String)
|
annotationToLine :: String -> AnnotatedViolation -> (Int, String)
|
||||||
annotationToLine (AnnotatedViolation Violation{..} a indent) =
|
annotationToLine todo (AnnotatedViolation Violation{..} a indent) =
|
||||||
(line, indent ++ showAnnotation a description)
|
(line, indent ++ showAnnotation todo a description)
|
||||||
|
|
||||||
|
showAnnotation :: String -> Annotation -> String -> String
|
||||||
|
showAnnotation _ (Intentional (Rule rule) reason) _ = mconcat ["// ", "coverity[", rule, "_violation", "] ", reason]
|
||||||
|
showAnnotation _ (FalsePositive (Rule rule) reason) _ = mconcat ["// ", "coverity[", rule, "_violation", " : FALSE", "] ", reason]
|
||||||
|
showAnnotation todo (ToDo (Rule rule)) description = "// " <> todo <> " " <> rule <> ": " <> description
|
||||||
|
|
||||||
data UserChoice = Abort
|
data UserChoice = Abort
|
||||||
| Annotate Annotation
|
| Annotate Annotation
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
module Annotator.Annotation (Annotation(..), showAnnotation, fromFile) where
|
module Annotator.Annotation (Annotation(..), fromFile) where
|
||||||
|
|
||||||
|
import Data.Char (isSpace)
|
||||||
import Annotator.Rule
|
import Annotator.Rule
|
||||||
import Data.Monoid
|
|
||||||
|
|
||||||
data Annotation = Intentional !Rule !String
|
data Annotation = Intentional !Rule !String
|
||||||
| FalsePositive !Rule !String
|
| FalsePositive !Rule !String
|
||||||
| ToDo !Rule
|
| ToDo !Rule
|
||||||
deriving (Show, Read, Eq)
|
deriving (Show, Read, Eq)
|
||||||
|
|
||||||
showAnnotation :: Annotation -> String -> String
|
|
||||||
showAnnotation (Intentional (Rule rule) reason) _ = mconcat ["// ", "coverity[", rule, "_violation", "] ", reason]
|
|
||||||
showAnnotation (FalsePositive (Rule rule) reason) _ = mconcat ["// ", "coverity[", rule, "_violation", " : FALSE", "] ", reason]
|
|
||||||
showAnnotation (ToDo (Rule rule)) description = "// FIXME violation " <> rule <> ": " <> description
|
|
||||||
|
|
||||||
fromFile :: FilePath -> IO [Either String Annotation]
|
fromFile :: FilePath -> IO [Either String Annotation]
|
||||||
fromFile fn = fmap safeRead . removeBoring . lines <$> readFile fn
|
fromFile fn = fmap safeRead . removeBoring . lines <$> readFile fn
|
||||||
where
|
where
|
||||||
removeBoring :: [String] -> [String]
|
removeBoring :: [String] -> [String]
|
||||||
removeBoring = filter (const True)
|
removeBoring = filter (not . isBoring)
|
||||||
|
|
||||||
|
isBoring x = isComment x || isEmpty x
|
||||||
|
isComment x = take 1 x == "#" || take 2 x == "--"
|
||||||
|
isEmpty = null . dropWhile isSpace
|
||||||
|
|
||||||
safeRead :: String -> Either String Annotation
|
safeRead :: String -> Either String Annotation
|
||||||
safeRead s = case reads s of
|
safeRead s = case reads s of
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,4 @@
|
||||||
module Annotator.Rule where
|
module Annotator.Rule where
|
||||||
|
|
||||||
newtype Rule = Rule String
|
newtype Rule = Rule String
|
||||||
deriving (Eq, Read)
|
deriving (Eq, Read, Show)
|
||||||
|
|
||||||
instance Show Rule where
|
|
||||||
show :: Rule -> String
|
|
||||||
show (Rule r) = r
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue