{-# OPTIONS_GHC -fno-warn-deprecations #-}
module Test.Tasty.Sugar.Analysis
(
checkRoots
)
where
import Control.Monad.Logic
import Data.Bifunctor ( bimap )
import Data.Function ( on )
import qualified Data.List as L
import Data.Maybe ( catMaybes )
import Data.Ord ( comparing )
import qualified System.FilePath.GlobPattern as FPGP
import Test.Tasty.Sugar.ExpectCheck
import Test.Tasty.Sugar.RootCheck
import Test.Tasty.Sugar.ParamCheck ( pmatchCmp )
import Test.Tasty.Sugar.Types
checkRoots :: CUBE -> [CandidateFile]
-> (Int, [([Sweets], [SweetExplanation])])
checkRoots :: CUBE -> [CandidateFile] -> (Int, [([Sweets], [SweetExplanation])])
checkRoots CUBE
pat [CandidateFile]
allFiles =
let isRootMatch :: CandidateFile -> Bool
isRootMatch CandidateFile
n = CandidateFile -> FilePath
candidateFile CandidateFile
n FilePath -> FilePath -> Bool
FPGP.~~ (CUBE -> FilePath
rootName CUBE
pat)
roots :: [CandidateFile]
roots = forall a. (a -> Bool) -> [a] -> [a]
filter CandidateFile -> Bool
isRootMatch [CandidateFile]
allFiles
checked :: [([Sweets], [SweetExplanation])]
checked = forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst)
((CUBE
-> [CandidateFile]
-> CandidateFile
-> ([Sweets], [SweetExplanation])
checkRoot CUBE
pat [CandidateFile]
allFiles) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [CandidateFile]
roots)
in (forall (t :: * -> *) a. Foldable t => t a -> Int
length [([Sweets], [SweetExplanation])]
checked, [([Sweets], [SweetExplanation])]
checked)
checkRoot :: CUBE
-> [CandidateFile]
-> CandidateFile
-> ([Sweets], [SweetExplanation])
checkRoot :: CUBE
-> [CandidateFile]
-> CandidateFile
-> ([Sweets], [SweetExplanation])
checkRoot CUBE
pat [CandidateFile]
allFiles CandidateFile
rootF =
let seps :: FilePath
seps = CUBE -> FilePath
separators CUBE
pat
params :: [ParameterPattern]
params = CUBE -> [ParameterPattern]
validParams CUBE
pat
combineExpRes :: (a, a) -> p [a] [a] -> p [a] [a]
combineExpRes (a
swts, a
expl) = forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap (a
swts forall a. a -> [a] -> [a]
:) (a
expl forall a. a -> [a] -> [a]
:)
mergeSweets :: t (Sweets, SweetExplanation) -> [(Sweets, SweetExplanation)]
mergeSweets t (Sweets, SweetExplanation)
swl =
let combineIfRootsMatch :: (Sweets, SweetExplanation)
-> [(Sweets, SweetExplanation)] -> [(Sweets, SweetExplanation)]
combineIfRootsMatch (Sweets, SweetExplanation)
s [(Sweets, SweetExplanation)]
sl =
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (forall a b c. (a -> b -> c) -> b -> a -> c
flip (:))
( forall {t :: * -> *}.
Foldable t =>
(Sweets, SweetExplanation)
-> t (Sweets, SweetExplanation) -> (Sweets, SweetExplanation)
combineSweets (Sweets, SweetExplanation)
s forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. (a -> Bool) -> [a] -> ([a], [a])
L.partition (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {b}. (Sweets, b) -> (Sweets, b) -> Bool
isRootMatch (Sweets, SweetExplanation)
s) [(Sweets, SweetExplanation)]
sl)
isRootMatch :: (Sweets, b) -> (Sweets, b) -> Bool
isRootMatch = forall a. Eq a => a -> a -> Bool
(==) forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (Sweets -> FilePath
rootMatchName forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst)
combineSweets :: (Sweets, SweetExplanation)
-> t (Sweets, SweetExplanation) -> (Sweets, SweetExplanation)
combineSweets (Sweets, SweetExplanation)
s t (Sweets, SweetExplanation)
slm =
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Sweets, SweetExplanation)
-> (Sweets, SweetExplanation) -> (Sweets, SweetExplanation)
chooseOrCombineExpectations (Sweets, SweetExplanation)
s t (Sweets, SweetExplanation)
slm
chooseOrCombineExpectations :: (Sweets, SweetExplanation)
-> (Sweets, SweetExplanation) -> (Sweets, SweetExplanation)
chooseOrCombineExpectations (Sweets
s,SweetExplanation
e) (Sweets
sm,SweetExplanation
sme) =
case forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing Sweets -> FilePath
rootBaseName Sweets
s Sweets
sm of
Ordering
GT -> (Sweets
s,SweetExplanation
e)
Ordering
LT -> (Sweets
sm, SweetExplanation
sme)
Ordering
EQ -> forall {b}.
(Sweets, SweetExplanation)
-> (Sweets, b) -> (Sweets, SweetExplanation)
bestExpectations (Sweets
s,SweetExplanation
e) (Sweets
sm,SweetExplanation
sme)
bestExpectations :: (Sweets, SweetExplanation)
-> (Sweets, b) -> (Sweets, SweetExplanation)
bestExpectations (Sweets
s,SweetExplanation
e) (Sweets
sm,b
_sme) =
let swts :: Sweets
swts = Sweets
s { expected :: [Expectation]
expected =
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Expectation -> [Expectation] -> [Expectation]
mergeExp (Sweets -> [Expectation]
expected Sweets
s) (Sweets -> [Expectation]
expected Sweets
sm)
}
mergeExp :: Expectation -> [Expectation] -> [Expectation]
mergeExp Expectation
oneExp [Expectation]
exps =
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Int -> [a] -> [a]
take Int
1)
forall a b. (a -> b) -> a -> b
$ forall a. (a -> a -> Bool) -> [a] -> [[a]]
L.groupBy (forall a. Eq a => a -> a -> Bool
(==) forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on`
(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ParamMatch -> Maybe FilePath
getParamVal) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expectation -> [NamedParamMatch]
expParamsMatch))
forall a b. (a -> b) -> a -> b
$ forall a. (a -> a -> Ordering) -> [a] -> [a]
L.sortBy ([NamedParamMatch] -> [NamedParamMatch] -> Ordering
pmatchCmp forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Expectation -> [NamedParamMatch]
expParamsMatch)
forall a b. (a -> b) -> a -> b
$ Expectation
oneExp forall a. a -> [a] -> [a]
: [Expectation]
exps
in ( Sweets
swts, SweetExplanation
e { results :: Sweets
results = Sweets
swts } )
in forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Sweets, SweetExplanation)
-> [(Sweets, SweetExplanation)] -> [(Sweets, SweetExplanation)]
combineIfRootsMatch [] t (Sweets, SweetExplanation)
swl
in forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall {p :: * -> * -> *} {a} {a}.
Bifunctor p =>
(a, a) -> p [a] [a] -> p [a] [a]
combineExpRes ([], []) forall a b. (a -> b) -> a -> b
$
forall {t :: * -> *}.
Foldable t =>
t (Sweets, SweetExplanation) -> [(Sweets, SweetExplanation)]
mergeSweets forall a b. (a -> b) -> a -> b
$
forall a. [Maybe a] -> [a]
catMaybes forall a b. (a -> b) -> a -> b
$
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (CUBE
-> CandidateFile
-> [CandidateFile]
-> ([NamedParamMatch], CandidateFile, FilePath)
-> Maybe (Sweets, SweetExplanation)
findExpectation CUBE
pat CandidateFile
rootF [CandidateFile]
allFiles) forall a b. (a -> b) -> a -> b
$
forall a. Logic a -> [a]
observeAll forall a b. (a -> b) -> a -> b
$
CandidateFile
-> FilePath
-> [ParameterPattern]
-> FilePath
-> Logic ([NamedParamMatch], CandidateFile, FilePath)
rootMatch CandidateFile
rootF FilePath
seps [ParameterPattern]
params (CUBE -> FilePath
rootName CUBE
pat)