{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
module Test.Tasty.Sugar.Types where
import Data.Function ( on )
import qualified Data.List as L
import Data.Maybe ( catMaybes )
import Numeric.Natural
import System.FilePath
import qualified System.FilePath.GlobPattern as FPGP
#if MIN_VERSION_prettyprinter(1,7,0)
import Prettyprinter
#else
import Data.Text.Prettyprint.Doc
#endif
import Prelude hiding ( exp )
type FileSuffix = String
data CUBE = CUBE
{
CUBE -> String
inputDir :: FilePath
, CUBE -> [String]
inputDirs :: [FilePath]
, CUBE -> String
rootName :: FPGP.GlobPattern
, CUBE -> String
expectedSuffix :: FileSuffix
, CUBE -> String
separators :: Separators
, CUBE -> [(String, String)]
associatedNames :: [ (String, FileSuffix) ]
, CUBE -> [ParameterPattern]
validParams :: [ParameterPattern]
}
deriving Int -> CUBE -> ShowS
[CUBE] -> ShowS
CUBE -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CUBE] -> ShowS
$cshowList :: [CUBE] -> ShowS
show :: CUBE -> String
$cshow :: CUBE -> String
showsPrec :: Int -> CUBE -> ShowS
$cshowsPrec :: Int -> CUBE -> ShowS
Show
{-# DEPRECATED inputDir "Use inputDirs instead" #-}
type ParameterPattern = (String, Maybe [String])
type Separators = String
mkCUBE :: CUBE
mkCUBE :: CUBE
mkCUBE = CUBE { inputDirs :: [String]
inputDirs = [String
"test/samples"]
, inputDir :: String
inputDir = String
""
, separators :: String
separators = String
".-"
, rootName :: String
rootName = String
"*"
, associatedNames :: [(String, String)]
associatedNames = []
, expectedSuffix :: String
expectedSuffix = String
"exp"
, validParams :: [ParameterPattern]
validParams = []
}
instance Pretty CUBE where
pretty :: forall ann. CUBE -> Doc ann
pretty CUBE
cube =
let assoc :: Maybe (Doc ann)
assoc = forall ann. [(String, String)] -> Maybe (Doc ann)
prettyAssocNames forall a b. (a -> b) -> a -> b
$ CUBE -> [(String, String)]
associatedNames CUBE
cube
parms :: Maybe (Doc ann)
parms = forall ann. [ParameterPattern] -> Maybe (Doc ann)
prettyParamPatterns forall a b. (a -> b) -> a -> b
$ CUBE -> [ParameterPattern]
validParams CUBE
cube
hdrs :: [Doc ann]
hdrs = [ Doc ann
"input dirs: "
forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall a ann. Pretty a => a -> Doc ann
pretty (forall a. Eq a => [a] -> [a]
L.nub forall a b. (a -> b) -> a -> b
$ CUBE -> String
inputDir CUBE
cube forall a. a -> [a] -> [a]
: CUBE -> [String]
inputDirs CUBE
cube)
, Doc ann
"rootName: " forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall a ann. Pretty a => a -> Doc ann
pretty (CUBE -> String
rootName CUBE
cube)
, Doc ann
"expected: " forall ann. Doc ann -> Doc ann -> Doc ann
<+>
forall ann. Doc ann -> Doc ann
brackets (forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ CUBE -> String
separators CUBE
cube) forall a. Semigroup a => a -> a -> a
<>
forall a ann. Pretty a => a -> Doc ann
pretty (CUBE -> String
expectedSuffix CUBE
cube)
]
in Doc ann
"Sugar.CUBE" forall a. Semigroup a => a -> a -> a
<> (forall ann. Int -> Doc ann -> Doc ann
indent Int
1 forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall {ann}. [Doc ann]
hdrs forall a. Semigroup a => a -> a -> a
<> forall a. [Maybe a] -> [a]
catMaybes [forall {ann}. Maybe (Doc ann)
assoc, forall {ann}. Maybe (Doc ann)
parms])
prettyAssocNames :: [(String, String)] -> Maybe (Doc ann)
prettyAssocNames :: forall ann. [(String, String)] -> Maybe (Doc ann)
prettyAssocNames = \case
[] -> forall a. Maybe a
Nothing
[(String, String)]
nms -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Doc ann
"associated:" forall a. Semigroup a => a -> a -> a
<> (forall ann. Int -> Doc ann -> Doc ann
indent Int
1 forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map (forall a ann. Pretty a => a -> Doc ann
pretty forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Show a => a -> String
show) [(String, String)]
nms)
prettyParamPatterns :: [ParameterPattern] -> Maybe (Doc ann)
prettyParamPatterns :: forall ann. [ParameterPattern] -> Maybe (Doc ann)
prettyParamPatterns = \case
[] -> forall a. Maybe a
Nothing
[ParameterPattern]
prms -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Doc ann
"params:" forall a. Semigroup a => a -> a -> a
<>
(let pp :: (a, Maybe [a]) -> Doc ann
pp (a
pn,Maybe [a]
mpv) =
forall a ann. Pretty a => a -> Doc ann
pretty a
pn forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall ann. Doc ann
equals forall ann. Doc ann -> Doc ann -> Doc ann
<+>
case Maybe [a]
mpv of
Maybe [a]
Nothing -> Doc ann
"*"
Just [a]
vl -> forall ann. [Doc ann] -> Doc ann
hsep forall a b. (a -> b) -> a -> b
$
forall a. a -> [a] -> [a]
L.intersperse forall ann. Doc ann
pipe forall a b. (a -> b) -> a -> b
$
forall a b. (a -> b) -> [a] -> [b]
map forall a ann. Pretty a => a -> Doc ann
pretty [a]
vl
in forall ann. Int -> Doc ann -> Doc ann
indent Int
1 forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall {a} {a} {ann}.
(Pretty a, Pretty a) =>
(a, Maybe [a]) -> Doc ann
pp [ParameterPattern]
prms)
data CandidateFile = CandidateFile
{
CandidateFile -> String
candidateDir :: FilePath
, CandidateFile -> [String]
candidateSubdirs :: [ FilePath ]
, CandidateFile -> String
candidateFile :: FilePath
, CandidateFile -> [NamedParamMatch]
candidatePMatch :: [NamedParamMatch]
, CandidateFile -> Natural
candidateMatchIdx :: Natural
}
deriving (CandidateFile -> CandidateFile -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CandidateFile -> CandidateFile -> Bool
$c/= :: CandidateFile -> CandidateFile -> Bool
== :: CandidateFile -> CandidateFile -> Bool
$c== :: CandidateFile -> CandidateFile -> Bool
Eq, Int -> CandidateFile -> ShowS
[CandidateFile] -> ShowS
CandidateFile -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CandidateFile] -> ShowS
$cshowList :: [CandidateFile] -> ShowS
show :: CandidateFile -> String
$cshow :: CandidateFile -> String
showsPrec :: Int -> CandidateFile -> ShowS
$cshowsPrec :: Int -> CandidateFile -> ShowS
Show)
data Sweets = Sweets
{ Sweets -> String
rootBaseName :: String
, Sweets -> String
rootMatchName :: String
, Sweets -> String
rootFile :: FilePath
, Sweets -> [ParameterPattern]
cubeParams :: [ParameterPattern]
, Sweets -> [Expectation]
expected :: [Expectation]
}
deriving (Int -> Sweets -> ShowS
[Sweets] -> ShowS
Sweets -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Sweets] -> ShowS
$cshowList :: [Sweets] -> ShowS
show :: Sweets -> String
$cshow :: Sweets -> String
showsPrec :: Int -> Sweets -> ShowS
$cshowsPrec :: Int -> Sweets -> ShowS
Show, Sweets -> Sweets -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Sweets -> Sweets -> Bool
$c/= :: Sweets -> Sweets -> Bool
== :: Sweets -> Sweets -> Bool
$c== :: Sweets -> Sweets -> Bool
Eq)
instance Pretty Sweets where
pretty :: forall ann. Sweets -> Doc ann
pretty Sweets
inp = Doc ann
"Sweet" forall ann. Doc ann -> Doc ann -> Doc ann
<+>
(forall ann. Doc ann -> Doc ann
align forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a. [Maybe a] -> [a]
catMaybes
[ forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a ann. Pretty a => a -> Doc ann
pretty (Sweets -> String
rootMatchName Sweets
inp)
, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Doc ann
"root:" forall ann. Doc ann -> Doc ann -> Doc ann
<+>
forall ann. Doc ann -> Doc ann
align (forall ann. [Doc ann] -> Doc ann
vsep [ forall a ann. Pretty a => a -> Doc ann
pretty (Sweets -> String
rootBaseName Sweets
inp)
, forall a ann. Pretty a => a -> Doc ann
pretty (Sweets -> String
rootFile Sweets
inp)
])
, forall ann. [ParameterPattern] -> Maybe (Doc ann)
prettyParamPatterns forall a b. (a -> b) -> a -> b
$ Sweets -> [ParameterPattern]
cubeParams Sweets
inp
, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ Sweets -> [Expectation]
expected Sweets
inp
])
type Association = (String, FilePath)
type NamedParamMatch = (String, ParamMatch)
data Expectation = Expectation
{ Expectation -> String
expectedFile :: FilePath
, Expectation -> [NamedParamMatch]
expParamsMatch :: [ NamedParamMatch ]
, Expectation -> [(String, String)]
associated :: [ Association ]
}
deriving Int -> Expectation -> ShowS
[Expectation] -> ShowS
Expectation -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Expectation] -> ShowS
$cshowList :: [Expectation] -> ShowS
show :: Expectation -> String
$cshow :: Expectation -> String
showsPrec :: Int -> Expectation -> ShowS
$cshowsPrec :: Int -> Expectation -> ShowS
Show
instance Eq Expectation where
Expectation
e1 == :: Expectation -> Expectation -> Bool
== Expectation
e2 = let bagCmp :: [a] -> [a] -> Bool
bagCmp [a]
a [a]
b = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ([a]
a forall a. Eq a => a -> a -> Bool
==) forall a b. (a -> b) -> a -> b
$ forall a. [a] -> [[a]]
L.permutations [a]
b
in forall (t :: * -> *). Foldable t => t Bool -> Bool
and [ Expectation -> String
expectedFile Expectation
e1 forall a. Eq a => a -> a -> Bool
== Expectation -> String
expectedFile Expectation
e2
, (forall {a}. Eq a => [a] -> [a] -> Bool
bagCmp forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Expectation -> [NamedParamMatch]
expParamsMatch) Expectation
e1 Expectation
e2
, (forall {a}. Eq a => [a] -> [a] -> Bool
bagCmp forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Expectation -> [(String, String)]
associated) Expectation
e1 Expectation
e2
]
instance Pretty Expectation where
pretty :: forall ann. Expectation -> Doc ann
pretty Expectation
exp =
let p :: [NamedParamMatch]
p = Expectation -> [NamedParamMatch]
expParamsMatch Expectation
exp
pp :: Maybe (Doc ann)
pp = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [NamedParamMatch]
p
then forall a. Maybe a
Nothing
else forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Doc ann
"Matched Params:" forall ann. Doc ann -> Doc ann -> Doc ann
<+> (forall ann. Doc ann -> Doc ann
align forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall {a} {a} {ann}. (Pretty a, Pretty a) => (a, a) -> Doc ann
ppp [NamedParamMatch]
p)
ppp :: (a, a) -> Doc ann
ppp (a
n,a
v) = forall a ann. Pretty a => a -> Doc ann
pretty a
n forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall ann. Doc ann
equals forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall a ann. Pretty a => a -> Doc ann
pretty a
v
a :: [(String, String)]
a = Expectation -> [(String, String)]
associated Expectation
exp
pa :: Maybe (Doc ann)
pa = if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(String, String)]
a
then forall a. Maybe a
Nothing
else forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Doc ann
"Associated:" forall ann. Doc ann -> Doc ann -> Doc ann
<+> (forall ann. Doc ann -> Doc ann
align forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a ann. Pretty a => a -> Doc ann
pretty [(String, String)]
a)
in forall ann. Int -> Doc ann -> Doc ann
hang Int
4 forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a. [Maybe a] -> [a]
catMaybes
[ forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Doc ann
"Expected: " forall ann. Doc ann -> Doc ann -> Doc ann
<+> (forall ann. Doc ann -> Doc ann
align forall a b. (a -> b) -> a -> b
$ forall a ann. Pretty a => a -> Doc ann
pretty (Expectation -> String
expectedFile Expectation
exp))
, forall {ann}. Maybe (Doc ann)
pp
, forall {ann}. Maybe (Doc ann)
pa
]
data ParamMatch =
NotSpecified
| Assumed String
| Explicit String
deriving (Int -> ParamMatch -> ShowS
[ParamMatch] -> ShowS
ParamMatch -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ParamMatch] -> ShowS
$cshowList :: [ParamMatch] -> ShowS
show :: ParamMatch -> String
$cshow :: ParamMatch -> String
showsPrec :: Int -> ParamMatch -> ShowS
$cshowsPrec :: Int -> ParamMatch -> ShowS
Show, ParamMatch -> ParamMatch -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ParamMatch -> ParamMatch -> Bool
$c/= :: ParamMatch -> ParamMatch -> Bool
== :: ParamMatch -> ParamMatch -> Bool
$c== :: ParamMatch -> ParamMatch -> Bool
Eq, Eq ParamMatch
ParamMatch -> ParamMatch -> Bool
ParamMatch -> ParamMatch -> Ordering
ParamMatch -> ParamMatch -> ParamMatch
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
min :: ParamMatch -> ParamMatch -> ParamMatch
$cmin :: ParamMatch -> ParamMatch -> ParamMatch
max :: ParamMatch -> ParamMatch -> ParamMatch
$cmax :: ParamMatch -> ParamMatch -> ParamMatch
>= :: ParamMatch -> ParamMatch -> Bool
$c>= :: ParamMatch -> ParamMatch -> Bool
> :: ParamMatch -> ParamMatch -> Bool
$c> :: ParamMatch -> ParamMatch -> Bool
<= :: ParamMatch -> ParamMatch -> Bool
$c<= :: ParamMatch -> ParamMatch -> Bool
< :: ParamMatch -> ParamMatch -> Bool
$c< :: ParamMatch -> ParamMatch -> Bool
compare :: ParamMatch -> ParamMatch -> Ordering
$ccompare :: ParamMatch -> ParamMatch -> Ordering
Ord)
instance Pretty ParamMatch where
pretty :: forall ann. ParamMatch -> Doc ann
pretty (Explicit String
s) = forall a ann. Pretty a => a -> Doc ann
pretty String
s
pretty (Assumed String
s) = forall ann. Doc ann -> Doc ann
brackets forall a b. (a -> b) -> a -> b
$ forall a ann. Pretty a => a -> Doc ann
pretty String
s
pretty ParamMatch
NotSpecified = Doc ann
"*"
paramMatchVal :: String -> ParamMatch -> Bool
paramMatchVal :: String -> ParamMatch -> Bool
paramMatchVal String
v (Explicit String
s) = String
s forall a. Eq a => a -> a -> Bool
== String
v
paramMatchVal String
v (Assumed String
s) = String
s forall a. Eq a => a -> a -> Bool
== String
v
paramMatchVal String
_ ParamMatch
NotSpecified = Bool
True
isExplicit :: ParamMatch -> Bool
isExplicit :: ParamMatch -> Bool
isExplicit = \case
Explicit String
_ -> Bool
True
ParamMatch
_ -> Bool
False
getExplicit :: ParamMatch -> Maybe String
getExplicit :: ParamMatch -> Maybe String
getExplicit (Explicit String
v) = forall a. a -> Maybe a
Just String
v
getExplicit ParamMatch
_ = forall a. Maybe a
Nothing
getParamVal :: ParamMatch -> Maybe String
getParamVal :: ParamMatch -> Maybe String
getParamVal (Explicit String
v) = forall a. a -> Maybe a
Just String
v
getParamVal (Assumed String
v) = forall a. a -> Maybe a
Just String
v
getParamVal ParamMatch
_ = forall a. Maybe a
Nothing
matchStrength :: [ParamMatch] -> Natural
matchStrength :: [ParamMatch] -> Natural
matchStrength = \case
[] -> Natural
0
(ParamMatch
NotSpecified : [ParamMatch]
ps) -> [ParamMatch] -> Natural
matchStrength [ParamMatch]
ps
((Explicit String
_) : [ParamMatch]
ps) -> Natural
1 forall a. Num a => a -> a -> a
+ [ParamMatch] -> Natural
matchStrength [ParamMatch]
ps
((Assumed String
_) : [ParamMatch]
ps) -> Natural
1 forall a. Num a => a -> a -> a
+ [ParamMatch] -> Natural
matchStrength [ParamMatch]
ps
data SweetExplanation =
SweetExpl { SweetExplanation -> String
rootPath :: FilePath
, SweetExplanation -> String
base :: String
, SweetExplanation -> [String]
expectedNames :: [String]
, SweetExplanation -> Sweets
results :: Sweets
}
instance Pretty SweetExplanation where
pretty :: forall ann. SweetExplanation -> Doc ann
pretty SweetExplanation
expl =
let nms :: [String]
nms = SweetExplanation -> [String]
expectedNames SweetExplanation
expl
in forall ann. Doc ann -> Doc ann
align forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a. [Maybe a] -> [a]
catMaybes [
forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
fillSep forall a b. (a -> b) -> a -> b
$ forall ann. Doc ann -> [Doc ann] -> [Doc ann]
punctuate Doc ann
","
[ Doc ann
"rootPath" forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall ann. Doc ann -> Doc ann
dquotes (forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ SweetExplanation -> String
rootPath SweetExplanation
expl)
, Doc ann
"base" forall ann. Doc ann -> Doc ann -> Doc ann
<+> forall ann. Doc ann -> Doc ann
dquotes (forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ SweetExplanation -> String
base SweetExplanation
expl)
, if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
nms
then Doc ann
"no matches"
else (forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
nms) forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ann
"possible matches"
]
, if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
nms
then forall a. Maybe a
Nothing
else forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall ann. Int -> Doc ann -> Doc ann
indent Int
8 forall a b. (a -> b) -> a -> b
$ forall ann. [Doc ann] -> Doc ann
vsep forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall a ann. Pretty a => a -> Doc ann
pretty [String]
nms
, forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a ann. Pretty a => a -> Doc ann
pretty forall a b. (a -> b) -> a -> b
$ SweetExplanation -> Sweets
results SweetExplanation
expl
]