{-# 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
    -- Semantic formatters:
    , ([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")