{-# LANGUAGE CPP                        #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE RecordWildCards            #-}
{-# LANGUAGE ScopedTypeVariables        #-}
{-# LANGUAGE UndecidableInstances       #-}
module Language.Haskell.Homplexity.RecordFieldsCount(
    RecordFieldsCount
  , recordFieldsCountT
  ) where

--import Data.Maybe
import           Data.Proxy
import           Language.Haskell.Exts.SrcLoc
import           Language.Haskell.Exts.Syntax
import           Language.Haskell.Homplexity.CodeFragment
import           Language.Haskell.Homplexity.Metric
import           Language.Haskell.Homplexity.Utilities

newtype RecordFieldsCount = RecordFieldsCount { RecordFieldsCount -> Int
unFieldCount :: Int }
  deriving (RecordFieldsCount -> RecordFieldsCount -> Bool
(RecordFieldsCount -> RecordFieldsCount -> Bool)
-> (RecordFieldsCount -> RecordFieldsCount -> Bool)
-> Eq RecordFieldsCount
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RecordFieldsCount -> RecordFieldsCount -> Bool
== :: RecordFieldsCount -> RecordFieldsCount -> Bool
$c/= :: RecordFieldsCount -> RecordFieldsCount -> Bool
/= :: RecordFieldsCount -> RecordFieldsCount -> Bool
Eq, Eq RecordFieldsCount
Eq RecordFieldsCount
-> (RecordFieldsCount -> RecordFieldsCount -> Ordering)
-> (RecordFieldsCount -> RecordFieldsCount -> Bool)
-> (RecordFieldsCount -> RecordFieldsCount -> Bool)
-> (RecordFieldsCount -> RecordFieldsCount -> Bool)
-> (RecordFieldsCount -> RecordFieldsCount -> Bool)
-> (RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> Ord RecordFieldsCount
RecordFieldsCount -> RecordFieldsCount -> Bool
RecordFieldsCount -> RecordFieldsCount -> Ordering
RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RecordFieldsCount -> RecordFieldsCount -> Ordering
compare :: RecordFieldsCount -> RecordFieldsCount -> Ordering
$c< :: RecordFieldsCount -> RecordFieldsCount -> Bool
< :: RecordFieldsCount -> RecordFieldsCount -> Bool
$c<= :: RecordFieldsCount -> RecordFieldsCount -> Bool
<= :: RecordFieldsCount -> RecordFieldsCount -> Bool
$c> :: RecordFieldsCount -> RecordFieldsCount -> Bool
> :: RecordFieldsCount -> RecordFieldsCount -> Bool
$c>= :: RecordFieldsCount -> RecordFieldsCount -> Bool
>= :: RecordFieldsCount -> RecordFieldsCount -> Bool
$cmax :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
max :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
$cmin :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
min :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
Ord, Int -> RecordFieldsCount
RecordFieldsCount -> Int
RecordFieldsCount -> [RecordFieldsCount]
RecordFieldsCount -> RecordFieldsCount
RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount]
RecordFieldsCount
-> RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount]
(RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount)
-> (Int -> RecordFieldsCount)
-> (RecordFieldsCount -> Int)
-> (RecordFieldsCount -> [RecordFieldsCount])
-> (RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount])
-> (RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount])
-> (RecordFieldsCount
    -> RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount])
-> Enum RecordFieldsCount
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: RecordFieldsCount -> RecordFieldsCount
succ :: RecordFieldsCount -> RecordFieldsCount
$cpred :: RecordFieldsCount -> RecordFieldsCount
pred :: RecordFieldsCount -> RecordFieldsCount
$ctoEnum :: Int -> RecordFieldsCount
toEnum :: Int -> RecordFieldsCount
$cfromEnum :: RecordFieldsCount -> Int
fromEnum :: RecordFieldsCount -> Int
$cenumFrom :: RecordFieldsCount -> [RecordFieldsCount]
enumFrom :: RecordFieldsCount -> [RecordFieldsCount]
$cenumFromThen :: RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount]
enumFromThen :: RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount]
$cenumFromTo :: RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount]
enumFromTo :: RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount]
$cenumFromThenTo :: RecordFieldsCount
-> RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount]
enumFromThenTo :: RecordFieldsCount
-> RecordFieldsCount -> RecordFieldsCount -> [RecordFieldsCount]
Enum, Integer -> RecordFieldsCount
RecordFieldsCount -> RecordFieldsCount
RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
(RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount)
-> (Integer -> RecordFieldsCount)
-> Num RecordFieldsCount
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
+ :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
$c- :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
- :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
$c* :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
* :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
$cnegate :: RecordFieldsCount -> RecordFieldsCount
negate :: RecordFieldsCount -> RecordFieldsCount
$cabs :: RecordFieldsCount -> RecordFieldsCount
abs :: RecordFieldsCount -> RecordFieldsCount
$csignum :: RecordFieldsCount -> RecordFieldsCount
signum :: RecordFieldsCount -> RecordFieldsCount
$cfromInteger :: Integer -> RecordFieldsCount
fromInteger :: Integer -> RecordFieldsCount
Num, Num RecordFieldsCount
Ord RecordFieldsCount
Num RecordFieldsCount
-> Ord RecordFieldsCount
-> (RecordFieldsCount -> Rational)
-> Real RecordFieldsCount
RecordFieldsCount -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
$ctoRational :: RecordFieldsCount -> Rational
toRational :: RecordFieldsCount -> Rational
Real, Enum RecordFieldsCount
Real RecordFieldsCount
Real RecordFieldsCount
-> Enum RecordFieldsCount
-> (RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount)
-> (RecordFieldsCount
    -> RecordFieldsCount -> (RecordFieldsCount, RecordFieldsCount))
-> (RecordFieldsCount
    -> RecordFieldsCount -> (RecordFieldsCount, RecordFieldsCount))
-> (RecordFieldsCount -> Integer)
-> Integral RecordFieldsCount
RecordFieldsCount -> Integer
RecordFieldsCount
-> RecordFieldsCount -> (RecordFieldsCount, RecordFieldsCount)
RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
forall a.
Real a
-> Enum a
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
$cquot :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
quot :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
$crem :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
rem :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
$cdiv :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
div :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
$cmod :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
mod :: RecordFieldsCount -> RecordFieldsCount -> RecordFieldsCount
$cquotRem :: RecordFieldsCount
-> RecordFieldsCount -> (RecordFieldsCount, RecordFieldsCount)
quotRem :: RecordFieldsCount
-> RecordFieldsCount -> (RecordFieldsCount, RecordFieldsCount)
$cdivMod :: RecordFieldsCount
-> RecordFieldsCount -> (RecordFieldsCount, RecordFieldsCount)
divMod :: RecordFieldsCount
-> RecordFieldsCount -> (RecordFieldsCount, RecordFieldsCount)
$ctoInteger :: RecordFieldsCount -> Integer
toInteger :: RecordFieldsCount -> Integer
Integral)

recordFieldsCountT :: Proxy RecordFieldsCount
recordFieldsCountT :: Proxy RecordFieldsCount
recordFieldsCountT  = Proxy RecordFieldsCount
forall {k} (t :: k). Proxy t
Proxy

instance Metric RecordFieldsCount DataDef where
  measure :: DataDef -> RecordFieldsCount
measure DataDef { String
Either [QualConDecl SrcLoc] [GadtDecl SrcLoc]
dataDefName :: String
dataDefCtors :: Either [QualConDecl SrcLoc] [GadtDecl SrcLoc]
dataDefName :: DataDef -> String
dataDefCtors :: DataDef -> Either [QualConDecl SrcLoc] [GadtDecl SrcLoc]
.. } = Int -> RecordFieldsCount
RecordFieldsCount (Int -> RecordFieldsCount) -> Int -> RecordFieldsCount
forall a b. (a -> b) -> a -> b
$ ([QualConDecl SrcLoc] -> Int)
-> ([GadtDecl SrcLoc] -> Int)
-> Either [QualConDecl SrcLoc] [GadtDecl SrcLoc]
-> Int
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either [QualConDecl SrcLoc] -> Int
measureCons [GadtDecl SrcLoc] -> Int
measureGadts Either [QualConDecl SrcLoc] [GadtDecl SrcLoc]
dataDefCtors

measureCons :: [QualConDecl SrcLoc] -> Int
measureCons :: [QualConDecl SrcLoc] -> Int
measureCons = (QualConDecl SrcLoc -> Int) -> [QualConDecl SrcLoc] -> Int
forall a. (a -> Int) -> [a] -> Int
sumOf (\(QualConDecl SrcLoc
_ Maybe [TyVarBind SrcLoc]
_ Maybe (Context SrcLoc)
_ ConDecl SrcLoc
decl) -> ConDecl SrcLoc -> Int
forall {l}. ConDecl l -> Int
count ConDecl SrcLoc
decl)
  where
    count :: ConDecl l -> Int
count (ConDecl l
_ Name l
_ [Type l]
lst) = [Type l] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Type l]
lst
    count (RecDecl l
_ Name l
_ [FieldDecl l]
lst) = [FieldDecl l] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FieldDecl l]
lst
    count InfixConDecl {}   = Int
2

measureGadts :: [GadtDecl SrcLoc] -> Int
measureGadts :: [GadtDecl SrcLoc] -> Int
measureGadts = (GadtDecl SrcLoc -> Int) -> [GadtDecl SrcLoc] -> Int
forall a. (a -> Int) -> [a] -> Int
sumOf GadtDecl SrcLoc -> Int
forall {l}. GadtDecl l -> Int
count
  where
#if MIN_VERSION_haskell_src_exts(1,21,0)
    count :: GadtDecl l -> Int
count (GadtDecl l
_ Name l
_ Maybe [TyVarBind l]
_ Maybe (Context l)
_ Maybe [FieldDecl l]
maybeFields Type l
_) = Int -> ([FieldDecl l] -> Int) -> Maybe [FieldDecl l] -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
0 [FieldDecl l] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Maybe [FieldDecl l]
maybeFields
#else
    count (GadtDecl _ _     maybeFields _) = maybe 0 length maybeFields
#endif

instance Show RecordFieldsCount where
  showsPrec :: Int -> RecordFieldsCount -> ShowS
showsPrec Int
_ (RecordFieldsCount Int
rfc) = (String
"record fields count of " String -> ShowS
forall a. [a] -> [a] -> [a]
++)
                                      ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
forall a. Show a => a -> ShowS
shows Int
rfc