{-# OPTIONS_HADDOCK not-home #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TemplateHaskell #-}
module Hedgehog.Internal.TH (
TExpQ
, discover
, discoverPrefix
) where
import qualified Data.List as List
import qualified Data.Map as Map
import qualified Data.Ord as Ord
import Hedgehog.Internal.Discovery
import Hedgehog.Internal.Property
import Language.Haskell.TH (Exp(..), Q, TExp, location, runIO)
import Language.Haskell.TH.Syntax (Loc(..), mkName, unTypeQ, unsafeTExpCoerce)
type TExpQ a =
Q (TExp a)
discover :: TExpQ Group
discover = discoverPrefix "prop_"
discoverPrefix :: String -> TExpQ Group
discoverPrefix prefix = do
file <- getCurrentFile
properties <- Map.toList <$> runIO (readProperties prefix file)
let
startLine =
Ord.comparing $
posLine .
posPostion .
propertySource .
snd
names =
fmap (mkNamedProperty . fst) $
List.sortBy startLine properties
[|| Group $$(moduleName) $$(listTE names) ||]
mkNamedProperty :: PropertyName -> TExpQ (PropertyName, Property)
mkNamedProperty name = do
[|| (name, $$(unsafeProperty name)) ||]
unsafeProperty :: PropertyName -> TExpQ Property
unsafeProperty =
unsafeTExpCoerce . pure . VarE . mkName . unPropertyName
listTE :: [TExpQ a] -> TExpQ [a]
listTE xs = do
unsafeTExpCoerce . pure . ListE =<< traverse unTypeQ xs
moduleName :: TExpQ GroupName
moduleName = do
loc <- GroupName . loc_module <$> location
[|| loc ||]
getCurrentFile :: Q FilePath
getCurrentFile =
loc_filename <$> location