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
31
README.md
31
README.md
|
|
@ -44,13 +44,15 @@ Usage: annotator [OPTIONS] files...
|
|||
A tool to semi-automatically add Coverity source-code annotations based on found defects.
|
||||
|
||||
|
||||
-v --verbose be more verbose, pass multiple times to increase verbosity
|
||||
-i --inplace replace source-file after inserting annotations
|
||||
-V --version show version
|
||||
--short-version show version
|
||||
-h --help show usage information
|
||||
-a --all handle all defects not just Newest
|
||||
-C[NUM] --context[=NUM] specify how much context should be shown around a violation
|
||||
-v --verbose be more verbose, pass multiple times to increase verbosity
|
||||
-i --inplace replace source-file after inserting annotations
|
||||
-V --version show full version information
|
||||
--short-version show just the version number
|
||||
-h --help show usage information
|
||||
-a --all handle all defects not just Newest
|
||||
-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
|
||||
|
|
@ -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,
|
||||
it's still possible to process all found violations by passing `-a` or `--all`
|
||||
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
|
||||
|
||||
version :: Vsn.Version
|
||||
version = Vsn.makeVersion [0,0,3,0]
|
||||
version = Vsn.makeVersion [0,0,4,0]
|
||||
|
||||
type App a = ReaderT Options IO a
|
||||
|
||||
|
|
@ -54,6 +54,7 @@ data Options = Options
|
|||
, onlyNewest :: Bool
|
||||
, annotationFiles :: [FilePath]
|
||||
, autoAnnotations :: [Annotation]
|
||||
, todoMarker :: String
|
||||
}
|
||||
deriving (Show, Eq)
|
||||
|
||||
|
|
@ -67,6 +68,7 @@ defaultOptions = Options
|
|||
, onlyNewest = True
|
||||
, annotationFiles = []
|
||||
, autoAnnotations = []
|
||||
, todoMarker = "TODO"
|
||||
}
|
||||
|
||||
options :: [OptDescr (Options -> Options)]
|
||||
|
|
@ -90,11 +92,22 @@ options =
|
|||
(NoArg (\opts -> opts { onlyNewest = False}))
|
||||
"handle all defects not just Newest"
|
||||
, 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"
|
||||
, 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"]
|
||||
(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
|
||||
|
|
@ -230,6 +243,7 @@ handleViolations violations = do
|
|||
opts <- ask
|
||||
let fname = filename $ NE.head violations
|
||||
fname' = fname <> ".fix"
|
||||
todo = todoMarker opts
|
||||
header' = "Processing " <> (show $ NE.length violations) <> " violation(s) in file " <> fname
|
||||
header = unlines
|
||||
[ header'
|
||||
|
|
@ -252,7 +266,7 @@ handleViolations violations = do
|
|||
|
||||
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
|
||||
|
||||
liftIO $ writeFile fname' newContent
|
||||
|
|
@ -261,10 +275,14 @@ handleViolations violations = do
|
|||
else do
|
||||
verbose Low $ "skipping non-existent file " <> fname
|
||||
where
|
||||
annotationToLine :: AnnotatedViolation -> (Int, String)
|
||||
annotationToLine (AnnotatedViolation Violation{..} a indent) =
|
||||
(line, indent ++ showAnnotation a description)
|
||||
annotationToLine :: String -> AnnotatedViolation -> (Int, String)
|
||||
annotationToLine todo (AnnotatedViolation Violation{..} a indent) =
|
||||
(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
|
||||
| Annotate Annotation
|
||||
|
|
|
|||
|
|
@ -1,24 +1,23 @@
|
|||
{-# LANGUAGE LambdaCase #-}
|
||||
module Annotator.Annotation (Annotation(..), showAnnotation, fromFile) where
|
||||
module Annotator.Annotation (Annotation(..), fromFile) where
|
||||
|
||||
import Data.Char (isSpace)
|
||||
import Annotator.Rule
|
||||
import Data.Monoid
|
||||
|
||||
data Annotation = Intentional !Rule !String
|
||||
| FalsePositive !Rule !String
|
||||
| ToDo !Rule
|
||||
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 fn = fmap safeRead . removeBoring . lines <$> readFile fn
|
||||
where
|
||||
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 s = case reads s of
|
||||
|
|
|
|||
|
|
@ -3,8 +3,4 @@
|
|||
module Annotator.Rule where
|
||||
|
||||
newtype Rule = Rule String
|
||||
deriving (Eq, Read)
|
||||
|
||||
instance Show Rule where
|
||||
show :: Rule -> String
|
||||
show (Rule r) = r
|
||||
deriving (Eq, Read, Show)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue