{-# LANGUAGE OverloadedStrings #-} module Tokstyle.C.Linter ( analyse , allWarnings ) where import Data.Text (Text) import qualified Data.Text as Text import Language.C.Analysis.AstAnalysis (analyseAST) import Language.C.Analysis.SemRep (GlobalDecls) import Language.C.Analysis.TravMonad (CLanguage (..), Trav, TravOptions (..), modifyOptions, runTrav) import Language.C.Syntax.AST (CTranslUnit) import Tokstyle.C.Env (Env, defaultEnv) import qualified Tokstyle.C.Linter.BoolConversion as BoolConversion import qualified Tokstyle.C.Linter.CallbackParams as CallbackParams import qualified Tokstyle.C.Linter.Cast as Cast import qualified Tokstyle.C.Linter.Conversion as Conversion import qualified Tokstyle.C.Linter.Memset as Memset import qualified Tokstyle.C.Linter.SizeArg as SizeArg import qualified Tokstyle.C.Linter.Sizeof as Sizeof import qualified Tokstyle.C.Linter.VoidCall as VoidCall linters :: [(Text, GlobalDecls -> Trav Env ())] linters :: [(Text, GlobalDecls -> Trav Env ())] linters = [ (Text "bool-conversion" , GlobalDecls -> Trav Env () BoolConversion.analyse ) , (Text "callback-params" , GlobalDecls -> Trav Env () CallbackParams.analyse ) , (Text "cast" , GlobalDecls -> Trav Env () Cast.analyse ) , (Text "conversion" , GlobalDecls -> Trav Env () Conversion.analyse ) , (Text "memset" , GlobalDecls -> Trav Env () Memset.analyse ) , (Text "size-arg" , GlobalDecls -> Trav Env () SizeArg.analyse ) , (Text "sizeof" , GlobalDecls -> Trav Env () Sizeof.analyse ) , (Text "void-call" , GlobalDecls -> Trav Env () VoidCall.analyse ) ] runLinters :: [Text] -> GlobalDecls -> Trav Env () runLinters :: [Text] -> GlobalDecls -> Trav Env () runLinters [Text] flags GlobalDecls tu = ((Text, GlobalDecls -> Trav Env ()) -> Trav Env ()) -> [(Text, GlobalDecls -> Trav Env ())] -> Trav Env () forall (t :: * -> *) (m :: * -> *) a b. (Foldable t, Monad m) => (a -> m b) -> t a -> m () mapM_ (\(Text _, GlobalDecls -> Trav Env () f) -> GlobalDecls -> Trav Env () f GlobalDecls tu) ([(Text, GlobalDecls -> Trav Env ())] -> Trav Env ()) -> ([(Text, GlobalDecls -> Trav Env ())] -> [(Text, GlobalDecls -> Trav Env ())]) -> [(Text, GlobalDecls -> Trav Env ())] -> Trav Env () forall b c a. (b -> c) -> (a -> b) -> a -> c . ((Text, GlobalDecls -> Trav Env ()) -> Bool) -> [(Text, GlobalDecls -> Trav Env ())] -> [(Text, GlobalDecls -> Trav Env ())] forall a. (a -> Bool) -> [a] -> [a] filter ((Text -> [Text] -> Bool forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool `elem` [Text] flags) (Text -> Bool) -> ((Text, GlobalDecls -> Trav Env ()) -> Text) -> (Text, GlobalDecls -> Trav Env ()) -> Bool forall b c a. (b -> c) -> (a -> b) -> a -> c . (Text, GlobalDecls -> Trav Env ()) -> Text forall a b. (a, b) -> a fst) ([(Text, GlobalDecls -> Trav Env ())] -> Trav Env ()) -> [(Text, GlobalDecls -> Trav Env ())] -> Trav Env () forall a b. (a -> b) -> a -> b $ [(Text, GlobalDecls -> Trav Env ())] linters analyse :: [Text] -> CTranslUnit -> [Text] analyse :: [Text] -> CTranslUnit -> [Text] analyse [Text] enabled CTranslUnit tu = case Either [CError] ((), TravState Identity Env) analysis of Left [CError] errs -> (CError -> Text) -> [CError] -> [Text] forall a b. (a -> b) -> [a] -> [b] map (String -> Text Text.pack (String -> Text) -> (CError -> String) -> CError -> Text forall b c a. (b -> c) -> (a -> b) -> a -> c . CError -> String forall a. Show a => a -> String show) [CError] errs Right ((), TravState Identity Env) _ -> [] where analysis :: Either [CError] ((), TravState Identity Env) analysis = Env -> Trav Env () -> Either [CError] ((), TravState Identity Env) forall s a. s -> Trav s a -> Either [CError] (a, TravState Identity s) runTrav Env defaultEnv (Trav Env () -> Either [CError] ((), TravState Identity Env)) -> Trav Env () -> Either [CError] ((), TravState Identity Env) forall a b. (a -> b) -> a -> b $ do (TravOptions -> TravOptions) -> Trav Env () forall s. (TravOptions -> TravOptions) -> Trav s () modifyOptions (\TravOptions opts -> TravOptions opts { language :: CLanguage language = CLanguage GNU99 }) GlobalDecls decls <- CTranslUnit -> TravT Env Identity GlobalDecls forall (m :: * -> *). MonadTrav m => CTranslUnit -> m GlobalDecls analyseAST CTranslUnit tu [Text] -> GlobalDecls -> Trav Env () runLinters [Text] enabled GlobalDecls decls allWarnings :: [Text] allWarnings :: [Text] allWarnings = ((Text, GlobalDecls -> Trav Env ()) -> Text) -> [(Text, GlobalDecls -> Trav Env ())] -> [Text] forall a b. (a -> b) -> [a] -> [b] map (Text, GlobalDecls -> Trav Env ()) -> Text forall a b. (a, b) -> a fst [(Text, GlobalDecls -> Trav Env ())] linters