{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Tokstyle.Linter
( analyse
, analyseLocal
, analyseGlobal
, analyseText
, analyseLocalText
, analyseGlobalText
, allWarnings
, markdown
, diagToText
) where
import Control.Parallel.Strategies (parMap, rpar)
import qualified Data.List as List
import Data.Text (Text)
import qualified Data.Text as Text
import Language.Cimple (Lexeme, Node)
import Language.Cimple.Diagnostics (CimplePos, Diagnostic (..),
diagToText)
import qualified Tokstyle.Linter.Assert as Assert
import qualified Tokstyle.Linter.BooleanReturn as BooleanReturn
import qualified Tokstyle.Linter.Booleans as Booleans
import qualified Tokstyle.Linter.CallbackNames as CallbackNames
import qualified Tokstyle.Linter.CallocArgs as CallocArgs
import qualified Tokstyle.Linter.CallocType as CallocType
import qualified Tokstyle.Linter.CompoundInit as CompoundInit
import qualified Tokstyle.Linter.Constness as Constness
import qualified Tokstyle.Linter.EnumDefines as EnumDefines
import qualified Tokstyle.Linter.EnumNames as EnumNames
import qualified Tokstyle.Linter.FuncPrototypes as FuncPrototypes
import qualified Tokstyle.Linter.FuncScopes as FuncScopes
import qualified Tokstyle.Linter.GlobalFuncs as GlobalFuncs
import qualified Tokstyle.Linter.LoggerCalls as LoggerCalls
import qualified Tokstyle.Linter.LoggerConst as LoggerConst
import qualified Tokstyle.Linter.LoggerNoEscapes as LoggerNoEscapes
import qualified Tokstyle.Linter.MallocCall as MallocCall
import qualified Tokstyle.Linter.MallocType as MallocType
import qualified Tokstyle.Linter.MemcpyStructs as MemcpyStructs
import qualified Tokstyle.Linter.Nesting as Nesting
import qualified Tokstyle.Linter.Nullability as Nullability
import qualified Tokstyle.Linter.NulTerminated as NulTerminated
import qualified Tokstyle.Linter.OwnershipDecls as OwnershipDecls
import qualified Tokstyle.Linter.Parens as Parens
import qualified Tokstyle.Linter.PartialFailure as PartialFailure
import qualified Tokstyle.Linter.SwitchIf as SwitchIf
import qualified Tokstyle.Linter.TaggedUnion as TaggedUnion
import qualified Tokstyle.Linter.TypedefName as TypedefName
import qualified Tokstyle.Linter.UnsafeFunc as UnsafeFunc
import qualified Tokstyle.Linter.VarUnusedInScope as VarUnusedInScope
import qualified Tokstyle.Linter.Callgraph as Callgraph
import qualified Tokstyle.Linter.DanglingField as DanglingField
import qualified Tokstyle.Linter.DeclaredOnce as DeclaredOnce
import qualified Tokstyle.Linter.DeclsHaveDefns as DeclsHaveDefns
import qualified Tokstyle.Linter.DocComments as DocComments
import qualified Tokstyle.Linter.MemoryLifetime as MemoryLifetime
import qualified Tokstyle.Linter.TypeCheck as TypeCheck
import qualified Tokstyle.Linter.UnboundedGrowth as UnboundedGrowth
import qualified Tokstyle.SemFmt.EnumFromInt as EnumFromInt
import qualified Tokstyle.SemFmt.EnumToString as EnumToString
import qualified Tokstyle.SemFmt.EnumUnpack as EnumUnpack
import qualified Tokstyle.SemFmt.StructPack as StructPack
type TranslationUnit = (FilePath, [Node (Lexeme Text)])
run :: [(t -> [Diagnostic CimplePos], (Text, Text))] -> [Text] -> t -> [Diagnostic CimplePos]
run :: forall t.
[(t -> [Diagnostic CimplePos], (Text, Text))]
-> [Text] -> t -> [Diagnostic CimplePos]
run [(t -> [Diagnostic CimplePos], (Text, Text))]
linters [Text]
flags t
tu =
[[Diagnostic CimplePos]] -> [Diagnostic CimplePos]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Diagnostic CimplePos]] -> [Diagnostic CimplePos])
-> ([(t -> [Diagnostic CimplePos], (Text, Text))]
-> [[Diagnostic CimplePos]])
-> [(t -> [Diagnostic CimplePos], (Text, Text))]
-> [Diagnostic CimplePos]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Strategy [Diagnostic CimplePos]
-> ((t -> [Diagnostic CimplePos], (Text, Text))
-> [Diagnostic CimplePos])
-> [(t -> [Diagnostic CimplePos], (Text, Text))]
-> [[Diagnostic CimplePos]]
forall b a. Strategy b -> (a -> b) -> [a] -> [b]
parMap Strategy [Diagnostic CimplePos]
forall a. Strategy a
rpar (t -> [Diagnostic CimplePos], (Text, Text))
-> [Diagnostic CimplePos]
forall {pos} {b}.
(t -> [Diagnostic pos], (Text, b)) -> [Diagnostic pos]
apply ([(t -> [Diagnostic CimplePos], (Text, Text))]
-> [[Diagnostic CimplePos]])
-> ([(t -> [Diagnostic CimplePos], (Text, Text))]
-> [(t -> [Diagnostic CimplePos], (Text, Text))])
-> [(t -> [Diagnostic CimplePos], (Text, Text))]
-> [[Diagnostic CimplePos]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((t -> [Diagnostic CimplePos], (Text, Text)) -> Bool)
-> [(t -> [Diagnostic CimplePos], (Text, Text))]
-> [(t -> [Diagnostic CimplePos], (Text, Text))]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Text]
flags) (Text -> Bool)
-> ((t -> [Diagnostic CimplePos], (Text, Text)) -> Text)
-> (t -> [Diagnostic CimplePos], (Text, Text))
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text, Text) -> Text
forall a b. (a, b) -> a
fst ((Text, Text) -> Text)
-> ((t -> [Diagnostic CimplePos], (Text, Text)) -> (Text, Text))
-> (t -> [Diagnostic CimplePos], (Text, Text))
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (t -> [Diagnostic CimplePos], (Text, Text)) -> (Text, Text)
forall a b. (a, b) -> b
snd) ([(t -> [Diagnostic CimplePos], (Text, Text))]
-> [Diagnostic CimplePos])
-> [(t -> [Diagnostic CimplePos], (Text, Text))]
-> [Diagnostic CimplePos]
forall a b. (a -> b) -> a -> b
$ [(t -> [Diagnostic CimplePos], (Text, Text))]
linters
where
apply :: (t -> [Diagnostic pos], (Text, b)) -> [Diagnostic pos]
apply (t -> [Diagnostic pos]
f, (Text
flag, b
_)) = (Diagnostic pos -> Diagnostic pos)
-> [Diagnostic pos] -> [Diagnostic pos]
forall a b. (a -> b) -> [a] -> [b]
map (\Diagnostic pos
d -> Diagnostic pos
d{diagFlag = Just flag}) ([Diagnostic pos] -> [Diagnostic pos])
-> [Diagnostic pos] -> [Diagnostic pos]
forall a b. (a -> b) -> a -> b
$ t -> [Diagnostic pos]
f t
tu
type LocalLinter = (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
localLinters :: [LocalLinter]
localLinters :: [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))]
localLinters =
[ (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
Assert.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
Booleans.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
BooleanReturn.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
CallbackNames.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
CallocArgs.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
CallocType.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
CompoundInit.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
Constness.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
EnumDefines.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
EnumNames.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
FuncPrototypes.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
FuncScopes.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
GlobalFuncs.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
LoggerCalls.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
LoggerConst.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
LoggerNoEscapes.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
MallocCall.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
MallocType.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
MemcpyStructs.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
Nesting.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
Parens.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
SwitchIf.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
TypedefName.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
UnsafeFunc.descr
, (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
VarUnusedInScope.descr
]
type GlobalLinter = ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
globalLinters :: [GlobalLinter]
globalLinters :: [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
globalLinters =
[ ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
Callgraph.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
DeclaredOnce.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
DanglingField.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
DeclsHaveDefns.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
DocComments.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
MemoryLifetime.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
Nullability.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
NulTerminated.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
OwnershipDecls.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
PartialFailure.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
TypeCheck.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
TaggedUnion.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
UnboundedGrowth.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
EnumFromInt.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
EnumToString.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
EnumUnpack.descr
, ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
StructPack.descr
]
analyseLocal :: [Text] -> TranslationUnit -> [Diagnostic CimplePos]
analyseLocal :: [Text] -> TranslationUnit -> [Diagnostic CimplePos]
analyseLocal = [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))]
-> [Text] -> TranslationUnit -> [Diagnostic CimplePos]
forall t.
[(t -> [Diagnostic CimplePos], (Text, Text))]
-> [Text] -> t -> [Diagnostic CimplePos]
run [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))]
localLinters
analyseLocalText :: [Text] -> TranslationUnit -> [Text]
analyseLocalText :: [Text] -> TranslationUnit -> [Text]
analyseLocalText [Text]
flags TranslationUnit
tu = (Diagnostic CimplePos -> Text) -> [Diagnostic CimplePos] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Diagnostic CimplePos -> Text
forall pos. IsPosition pos => Diagnostic pos -> Text
diagToText ([Text] -> TranslationUnit -> [Diagnostic CimplePos]
analyseLocal [Text]
flags TranslationUnit
tu)
analyseGlobal :: [Text] -> [TranslationUnit] -> [Diagnostic CimplePos]
analyseGlobal :: [Text] -> [TranslationUnit] -> [Diagnostic CimplePos]
analyseGlobal [Text]
linters [TranslationUnit]
tus = [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
-> [Text] -> [TranslationUnit] -> [Diagnostic CimplePos]
forall t.
[(t -> [Diagnostic CimplePos], (Text, Text))]
-> [Text] -> t -> [Diagnostic CimplePos]
run [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
globalLinters [Text]
linters ([TranslationUnit] -> [TranslationUnit]
sortTUs [TranslationUnit]
tus)
analyseGlobalText :: [Text] -> [TranslationUnit] -> [Text]
analyseGlobalText :: [Text] -> [TranslationUnit] -> [Text]
analyseGlobalText [Text]
flags [TranslationUnit]
tus = (Diagnostic CimplePos -> Text) -> [Diagnostic CimplePos] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Diagnostic CimplePos -> Text
forall pos. IsPosition pos => Diagnostic pos -> Text
diagToText ([Text] -> [TranslationUnit] -> [Diagnostic CimplePos]
analyseGlobal [Text]
flags [TranslationUnit]
tus)
sortTUs :: [TranslationUnit] -> [TranslationUnit]
sortTUs :: [TranslationUnit] -> [TranslationUnit]
sortTUs = (TranslationUnit -> TranslationUnit -> Ordering)
-> [TranslationUnit] -> [TranslationUnit]
forall a. (a -> a -> Ordering) -> [a] -> [a]
List.sortBy TranslationUnit -> TranslationUnit -> Ordering
forall {b} {b}. ([Char], b) -> ([Char], b) -> Ordering
compareTUs
where
compareTUs :: ([Char], b) -> ([Char], b) -> Ordering
compareTUs ([Char]
fp1, b
_) ([Char]
fp2, b
_) =
case ([Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
List.isSuffixOf [Char]
".h" [Char]
fp1, [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
List.isSuffixOf [Char]
".h" [Char]
fp2) of
(Bool
True, Bool
False) -> Ordering
LT
(Bool
False, Bool
True) -> Ordering
GT
(Bool, Bool)
_ -> [Char] -> [Char] -> Ordering
forall a. Ord a => a -> a -> Ordering
compare [Char]
fp1 [Char]
fp2
analyse :: [Text] -> [TranslationUnit] -> [Diagnostic CimplePos]
analyse :: [Text] -> [TranslationUnit] -> [Diagnostic CimplePos]
analyse [Text]
linters [TranslationUnit]
tus = [[Diagnostic CimplePos]] -> [Diagnostic CimplePos]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Diagnostic CimplePos]] -> [Diagnostic CimplePos])
-> [[Diagnostic CimplePos]] -> [Diagnostic CimplePos]
forall a b. (a -> b) -> a -> b
$ [Text] -> [TranslationUnit] -> [Diagnostic CimplePos]
analyseGlobal [Text]
linters [TranslationUnit]
tus [Diagnostic CimplePos]
-> [[Diagnostic CimplePos]] -> [[Diagnostic CimplePos]]
forall a. a -> [a] -> [a]
: Strategy [Diagnostic CimplePos]
-> (TranslationUnit -> [Diagnostic CimplePos])
-> [TranslationUnit]
-> [[Diagnostic CimplePos]]
forall b a. Strategy b -> (a -> b) -> [a] -> [b]
parMap Strategy [Diagnostic CimplePos]
forall a. Strategy a
rpar ([Text] -> TranslationUnit -> [Diagnostic CimplePos]
analyseLocal [Text]
linters) [TranslationUnit]
tus
analyseText :: [Text] -> [TranslationUnit] -> [Text]
analyseText :: [Text] -> [TranslationUnit] -> [Text]
analyseText [Text]
flags [TranslationUnit]
tus = (Diagnostic CimplePos -> Text) -> [Diagnostic CimplePos] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Diagnostic CimplePos -> Text
forall pos. IsPosition pos => Diagnostic pos -> Text
diagToText ([Text] -> [TranslationUnit] -> [Diagnostic CimplePos]
analyse [Text]
flags [TranslationUnit]
tus)
allWarnings :: [Text]
allWarnings :: [Text]
allWarnings = ((TranslationUnit -> [Diagnostic CimplePos], (Text, Text)) -> Text)
-> [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))]
-> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ((Text, Text) -> Text
forall a b. (a, b) -> a
fst ((Text, Text) -> Text)
-> ((TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
-> (Text, Text))
-> (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
-> (Text, Text)
forall a b. (a, b) -> b
snd) [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))]
localLinters [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
-> Text)
-> [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
-> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ((Text, Text) -> Text
forall a b. (a, b) -> a
fst ((Text, Text) -> Text)
-> (([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
-> (Text, Text))
-> ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
-> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
-> (Text, Text)
forall a b. (a, b) -> b
snd) [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
globalLinters
class LinterType a where
linterType :: a -> Text
instance LinterType LocalLinter where linterType :: (TranslationUnit -> [Diagnostic CimplePos], (Text, Text)) -> Text
linterType = Text
-> (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
-> Text
forall a b. a -> b -> a
const Text
""
instance LinterType GlobalLinter where linterType :: ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text)) -> Text
linterType = Text
-> ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
-> Text
forall a b. a -> b -> a
const Text
" (global)"
markdown :: Text
markdown :: Text
markdown = Text -> [Text] -> Text
Text.intercalate Text
"\n" ([Text] -> Text)
-> ([(Text, Text)] -> [Text]) -> [(Text, Text)] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Text]
prelude [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++) ([Text] -> [Text])
-> ([(Text, Text)] -> [Text]) -> [(Text, Text)] -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Text, Text) -> Text) -> [(Text, Text)] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text, Text) -> Text
forall a b. (a, b) -> b
snd ([(Text, Text)] -> [Text])
-> ([(Text, Text)] -> [(Text, Text)]) -> [(Text, Text)] -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Text, Text)] -> [(Text, Text)]
forall a. Ord a => [a] -> [a]
List.sort ([(Text, Text)] -> Text) -> [(Text, Text)] -> Text
forall a b. (a -> b) -> a -> b
$ ((TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
-> (Text, Text))
-> [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))]
-> [(Text, Text)]
forall a b. (a -> b) -> [a] -> [b]
map (TranslationUnit -> [Diagnostic CimplePos], (Text, Text))
-> (Text, Text)
forall {a}.
LinterType (a, (Text, Text)) =>
(a, (Text, Text)) -> (Text, Text)
mkDoc [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))]
localLinters [(Text, Text)] -> [(Text, Text)] -> [(Text, Text)]
forall a. [a] -> [a] -> [a]
++ (([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
-> (Text, Text))
-> [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
-> [(Text, Text)]
forall a b. (a -> b) -> [a] -> [b]
map ([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))
-> (Text, Text)
forall {a}.
LinterType (a, (Text, Text)) =>
(a, (Text, Text)) -> (Text, Text)
mkDoc [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
globalLinters
where
prelude :: [Text]
prelude =
[ Text
"# Cimple-based linters (`check-cimple`)"
, Text
""
, Text
"There are currently " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
Text.pack (Int -> [Char]
forall a. Show a => a -> [Char]
show (Int -> [Char]) -> Int -> [Char]
forall a b. (a -> b) -> a -> b
$ [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(TranslationUnit -> [Diagnostic CimplePos], (Text, Text))]
localLinters Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
-> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
globalLinters) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" linters implemented,"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" out of which " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
Text.pack (Int -> [Char]
forall a. Show a => a -> [Char]
show (Int -> [Char]) -> Int -> [Char]
forall a b. (a -> b) -> a -> b
$ [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
-> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [([TranslationUnit] -> [Diagnostic CimplePos], (Text, Text))]
globalLinters) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" perform global analyses."
, Text
"In the list below, the global ones are marked specially."
, Text
""
]
mkDoc :: (a, (Text, Text)) -> (Text, Text)
mkDoc (a, (Text, Text))
lnt =
let (Text
flag, Text
doc) = (a, (Text, Text)) -> (Text, Text)
forall a b. (a, b) -> b
snd (a, (Text, Text))
lnt in
(Text
flag, Text
"## `-W" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
flag Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"`" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (a, (Text, Text)) -> Text
forall a. LinterType a => a -> Text
linterType (a, (Text, Text))
lnt Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
Text.stripEnd Text
doc Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\n")