{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Argon.Results (order, filterResults, filterNulls, exportStream) where import Data.Ord (comparing) import Data.List (sortBy) import Data.String (IsString) #if __GLASGOW_HASKELL__ < 710 import Control.Applicative ((<*), (*>)) #endif import Data.Aeson (encode) import Pipes import Pipes.Group import qualified Pipes.Prelude as P import qualified Pipes.ByteString as PB import Lens.Simple ((^.)) import Argon.Formatters import Argon.Types -- sortOn is built-in only in base 4.8.0.0 onwards sortOn :: Ord b => (a -> b) -> [a] -> [a] sortOn f = map snd . sortBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x)) -- | Order a list of blocks. Ordering is done with respect to: -- -- 1. complexity (descending) -- 2. line number (ascending) -- 3. function name (alphabetically) order :: [ComplexityBlock] -> [ComplexityBlock] order = sortOn (\(CC ((l, _), f, cc)) -> (-cc, l, f)) -- | A result is discarded if it correspond to a successful analysis and there -- are no blocks to show filterNulls :: (FilePath, AnalysisResult) -> Bool filterNulls (_, r) = case r of Left _ -> True Right [] -> False _ -> True -- | Filter the results of the analysis, with respect to the given -- 'Config'. filterResults :: Config -> (FilePath, AnalysisResult) -> (FilePath, AnalysisResult) filterResults _ (s, Left err) = (s, Left err) filterResults o (s, Right rs) = (s, Right $ order [r | r@(CC (_, _, cc)) <- rs, cc >= minCC o]) -- | Export analysis' results. How to export the data is defined by the -- 'Config' parameter. exportStream :: (MonadIO m) => Config -> Producer (FilePath, AnalysisResult) m () -> Effect m () exportStream conf source = case outputMode conf of BareText -> source >-> bareTextFormatter >-> P.stdoutLn Colored -> source >-> coloredTextFormatter >-> P.stdoutLn JSON -> jsonStream (source >-> P.map encode) >-> for cat (\i -> PB.fromLazy i >-> PB.stdout) jsonStream :: (MonadIO m) => IsString a => Producer a m () -> Producer a m () jsonStream source = yield "[" *> intersperse' "," source <* yield "]\n" intersperse' :: Monad m => a -> Producer a m r -> Producer a m r intersperse' a producer = intercalates (yield a) (producer ^. chunksOf 1)