purescript-0.15.3: tests/TestAst.hs
{-# LANGUAGE TypeApplications #-}
module TestAst where
import Protolude hiding (Constraint, Type, (:+))
import Control.Lens ((+~))
import Control.Newtype (ala')
import Generic.Random
import Test.Hspec
import Test.QuickCheck
import Language.PureScript.Label
import Language.PureScript.Names
import Language.PureScript.PSString
import Language.PureScript.Types
spec :: Spec
spec = do
describe "Language.PureScript.Types" $ do
describe "everywhereOnTypes" $ do
everywhereOnTypesSpec everywhereOnTypes
describe "everywhereOnTypesM" $ do
everywhereOnTypesSpec $ ala' Identity everywhereOnTypesM
describe "everywhereOnTypesTopDownM" $ do
everywhereOnTypesSpec $ ala' Identity everywhereOnTypesTopDownM
describe "everythingOnTypes" $ do
everythingOnTypesSpec everythingOnTypes
describe "everythingWithContextOnTypes" $ do
everythingOnTypesSpec $ \f g -> everythingWithContextOnTypes () [] f $ \s -> (s, ) . g
everywhereOnTypesSpec :: ((Type Int -> Type Int) -> Type Int -> Type Int) -> Spec
everywhereOnTypesSpec everywhereOnTypesUnderTest = do
it "should visit each type once" $
forAllShrink (genTypeAnnotatedWith (pure 0) (pure 1)) subterms $ \t ->
all (== 1) `isSatisfiedBy` everywhereOnTypesUnderTest (annForType +~ 1) t
everythingOnTypesSpec :: (([Int] -> [Int] -> [Int]) -> (Type Int -> [Int]) -> Type Int -> [Int]) -> Spec
everythingOnTypesSpec everythingOnTypesUnderTest = do
it "should visit each type once" $
forAllShrink (genTypeAnnotatedWith (pure 1) (pure 0)) subterms $ \t ->
everythingOnTypesUnderTest (++) (pure . getAnnForType) t ===
filter (== 1) (toList t)
infixr 0 `isSatisfiedBy`
isSatisfiedBy :: forall a p. Show a => Testable p => (a -> p) -> a -> Property
isSatisfiedBy = liftA2 counterexample show
genTypeAnnotatedWith :: forall a. Gen a -> Gen a -> Gen (Type a)
genTypeAnnotatedWith genTypeAnn genConstraintAnn = genType where
generatorEnvironment
= genConstraint
:+ maybeOf genConstraintData
:+ Label <$> genPSString
:+ genPSString
:+ genQualified (OpName @'TypeOpName)
:+ genQualified (ProperName @'ClassName)
:+ genQualified (ProperName @'TypeName)
:+ genSkolemScope
:+ maybeOf genSkolemScope
:+ genText
:+ listOf' (listOf' genText)
:+ maybeOf genText
:+ genType
:+ listOf' genType
:+ maybeOf genType
:+ genWildcardData
genConstraint :: Gen (Constraint a)
genConstraint = genericArbitraryUG (genConstraintAnn :+ generatorEnvironment)
genConstraintData :: Gen ConstraintData
genConstraintData = genericArbitraryUG generatorEnvironment
genQualified :: forall b. (Text -> b) -> Gen (Qualified b)
genQualified ctor = Qualified ByNullSourcePos . ctor <$> genText
genSkolemScope :: Gen SkolemScope
genSkolemScope = SkolemScope <$> arbitrary
genType :: Gen (Type a)
genType = genericArbitraryRecG (genTypeAnn :+ generatorEnvironment) uniform `withBaseCase` (TypeVar <$> genTypeAnn <*> genText)
genWildcardData :: Gen WildcardData
genWildcardData = genericArbitraryUG genText
maybeOf :: forall b. Gen b -> Gen (Maybe b)
maybeOf = genericArbitraryUG
genText :: Gen Text
genText = pure "x" -- Feel free to make this random if it matters at some point.
genPSString :: Gen PSString
genPSString = pure "x" -- Ditto.