{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
module Test.Hspec.Megaparsec
(
shouldParse,
parseSatisfies,
shouldSucceedOn,
shouldFailOn,
shouldFailWith,
shouldFailWithM,
failsLeaving,
succeedsLeaving,
initialState,
initialPosState,
module Text.Megaparsec.Error.Builder,
)
where
import Control.Monad (unless)
import Data.List.NonEmpty qualified as NE
import Test.Hspec.Expectations
import Text.Megaparsec
import Text.Megaparsec.Error.Builder
shouldParse ::
( HasCallStack,
ShowErrorComponent e,
Stream s,
VisualStream s,
TraversableStream s,
Show a,
Eq a
) =>
Either (ParseErrorBundle s e) a ->
a ->
Expectation
Either (ParseErrorBundle s e) a
r shouldParse :: forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a, Eq a) =>
Either (ParseErrorBundle s e) a -> a -> Expectation
`shouldParse` a
v = case Either (ParseErrorBundle s e) a
r of
Left ParseErrorBundle s e
e ->
HasCallStack => String -> Expectation
expectationFailure forall a b. (a -> b) -> a -> b
$
String
"expected: "
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
v
forall a. [a] -> [a] -> [a]
++ String
"\nbut parsing failed with error:\n"
forall a. [a] -> [a] -> [a]
++ forall e s.
(ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s) =>
ParseErrorBundle s e -> String
showBundle ParseErrorBundle s e
e
Right a
x -> a
x forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`shouldBe` a
v
parseSatisfies ::
( HasCallStack,
ShowErrorComponent e,
Stream s,
VisualStream s,
TraversableStream s,
Show a,
Eq a
) =>
Either (ParseErrorBundle s e) a ->
(a -> Bool) ->
Expectation
Either (ParseErrorBundle s e) a
r parseSatisfies :: forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a, Eq a) =>
Either (ParseErrorBundle s e) a -> (a -> Bool) -> Expectation
`parseSatisfies` a -> Bool
p = case Either (ParseErrorBundle s e) a
r of
Left ParseErrorBundle s e
e ->
HasCallStack => String -> Expectation
expectationFailure forall a b. (a -> b) -> a -> b
$
String
"expected a parsed value to check against the predicate"
forall a. [a] -> [a] -> [a]
++ String
"\nbut parsing failed with error:\n"
forall a. [a] -> [a] -> [a]
++ forall e s.
(ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s) =>
ParseErrorBundle s e -> String
showBundle ParseErrorBundle s e
e
Right a
x ->
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (a -> Bool
p a
x) forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => String -> Expectation
expectationFailure forall a b. (a -> b) -> a -> b
$
String
"the value did not satisfy the predicate: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
x
shouldFailOn ::
(HasCallStack, Show a) =>
(s -> Either (ParseErrorBundle s e) a) ->
s ->
Expectation
s -> Either (ParseErrorBundle s e) a
p shouldFailOn :: forall a s e.
(HasCallStack, Show a) =>
(s -> Either (ParseErrorBundle s e) a) -> s -> Expectation
`shouldFailOn` s
s = forall a s e.
(HasCallStack, Show a) =>
Either (ParseErrorBundle s e) a -> Expectation
shouldFail (s -> Either (ParseErrorBundle s e) a
p s
s)
shouldSucceedOn ::
( HasCallStack,
ShowErrorComponent e,
Stream s,
VisualStream s,
TraversableStream s,
Show a
) =>
(s -> Either (ParseErrorBundle s e) a) ->
s ->
Expectation
s -> Either (ParseErrorBundle s e) a
p shouldSucceedOn :: forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a) =>
(s -> Either (ParseErrorBundle s e) a) -> s -> Expectation
`shouldSucceedOn` s
s = forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a) =>
Either (ParseErrorBundle s e) a -> Expectation
shouldSucceed (s -> Either (ParseErrorBundle s e) a
p s
s)
shouldFailWith ::
( HasCallStack,
ShowErrorComponent e,
Stream s,
VisualStream s,
TraversableStream s,
Show a,
Eq e
) =>
Either (ParseErrorBundle s e) a ->
ParseError s e ->
Expectation
Either (ParseErrorBundle s e) a
r shouldFailWith :: forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a, Eq e) =>
Either (ParseErrorBundle s e) a -> ParseError s e -> Expectation
`shouldFailWith` ParseError s e
perr1 = Either (ParseErrorBundle s e) a
r forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a, Eq e) =>
Either (ParseErrorBundle s e) a -> [ParseError s e] -> Expectation
`shouldFailWithM` [ParseError s e
perr1]
shouldFailWithM ::
( HasCallStack,
ShowErrorComponent e,
Stream s,
VisualStream s,
TraversableStream s,
Show a,
Eq e
) =>
Either (ParseErrorBundle s e) a ->
[ParseError s e] ->
Expectation
Either (ParseErrorBundle s e) a
r shouldFailWithM :: forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a, Eq e) =>
Either (ParseErrorBundle s e) a -> [ParseError s e] -> Expectation
`shouldFailWithM` [ParseError s e]
perrs1' = case Either (ParseErrorBundle s e) a
r of
Left ParseErrorBundle s e
e0 ->
let e1 :: ParseErrorBundle s e
e1 = ParseErrorBundle s e
e0 {bundleErrors :: NonEmpty (ParseError s e)
bundleErrors = NonEmpty (ParseError s e)
perrs1}
perrs0 :: NonEmpty (ParseError s e)
perrs0 = forall s e. ParseErrorBundle s e -> NonEmpty (ParseError s e)
bundleErrors ParseErrorBundle s e
e0
perrs1 :: NonEmpty (ParseError s e)
perrs1 = forall a. [a] -> NonEmpty a
NE.fromList [ParseError s e]
perrs1'
in forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (NonEmpty (ParseError s e)
perrs0 forall a. Eq a => a -> a -> Bool
== NonEmpty (ParseError s e)
perrs1) forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => String -> Expectation
expectationFailure forall a b. (a -> b) -> a -> b
$
String
"the parser is expected to fail with:\n"
forall a. [a] -> [a] -> [a]
++ forall e s.
(ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s) =>
ParseErrorBundle s e -> String
showBundle ParseErrorBundle s e
e1
forall a. [a] -> [a] -> [a]
++ String
"but it failed with:\n"
forall a. [a] -> [a] -> [a]
++ forall e s.
(ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s) =>
ParseErrorBundle s e -> String
showBundle ParseErrorBundle s e
e0
Right a
v ->
HasCallStack => String -> Expectation
expectationFailure forall a b. (a -> b) -> a -> b
$
String
"the parser is expected to fail, but it parsed: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
v
failsLeaving ::
( HasCallStack,
Show a,
Eq s,
Show s
) =>
(State s e, Either (ParseErrorBundle s e) a) ->
s ->
Expectation
(State s e
st, Either (ParseErrorBundle s e) a
r) failsLeaving :: forall a s e.
(HasCallStack, Show a, Eq s, Show s) =>
(State s e, Either (ParseErrorBundle s e) a) -> s -> Expectation
`failsLeaving` s
s = do
forall a s e.
(HasCallStack, Show a) =>
Either (ParseErrorBundle s e) a -> Expectation
shouldFail Either (ParseErrorBundle s e) a
r
forall s. (HasCallStack, Eq s, Show s) => s -> s -> Expectation
checkUnconsumed s
s (forall s e. State s e -> s
stateInput State s e
st)
succeedsLeaving ::
( HasCallStack,
Show a,
Eq s,
Show s,
ShowErrorComponent e,
Stream s,
VisualStream s,
TraversableStream s
) =>
(State s e, Either (ParseErrorBundle s e) a) ->
s ->
Expectation
(State s e
st, Either (ParseErrorBundle s e) a
r) succeedsLeaving :: forall a s e.
(HasCallStack, Show a, Eq s, Show s, ShowErrorComponent e,
Stream s, VisualStream s, TraversableStream s) =>
(State s e, Either (ParseErrorBundle s e) a) -> s -> Expectation
`succeedsLeaving` s
s = do
forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a) =>
Either (ParseErrorBundle s e) a -> Expectation
shouldSucceed Either (ParseErrorBundle s e) a
r
forall s. (HasCallStack, Eq s, Show s) => s -> s -> Expectation
checkUnconsumed s
s (forall s e. State s e -> s
stateInput State s e
st)
initialState :: s -> State s e
initialState :: forall s e. s -> State s e
initialState s
s =
State
{ stateInput :: s
stateInput = s
s,
stateOffset :: Int
stateOffset = Int
0,
statePosState :: PosState s
statePosState = forall s. s -> PosState s
initialPosState s
s,
stateParseErrors :: [ParseError s e]
stateParseErrors = []
}
initialPosState :: s -> PosState s
initialPosState :: forall s. s -> PosState s
initialPosState s
s =
PosState
{ pstateInput :: s
pstateInput = s
s,
pstateOffset :: Int
pstateOffset = Int
0,
pstateSourcePos :: SourcePos
pstateSourcePos = String -> SourcePos
initialPos String
"",
pstateTabWidth :: Pos
pstateTabWidth = Pos
defaultTabWidth,
pstateLinePrefix :: String
pstateLinePrefix = String
""
}
shouldFail ::
(HasCallStack, Show a) =>
Either (ParseErrorBundle s e) a ->
Expectation
shouldFail :: forall a s e.
(HasCallStack, Show a) =>
Either (ParseErrorBundle s e) a -> Expectation
shouldFail Either (ParseErrorBundle s e) a
r = case Either (ParseErrorBundle s e) a
r of
Left ParseErrorBundle s e
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
Right a
v ->
HasCallStack => String -> Expectation
expectationFailure forall a b. (a -> b) -> a -> b
$
String
"the parser is expected to fail, but it parsed: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
v
shouldSucceed ::
( HasCallStack,
ShowErrorComponent e,
Stream s,
VisualStream s,
TraversableStream s,
Show a
) =>
Either (ParseErrorBundle s e) a ->
Expectation
shouldSucceed :: forall e s a.
(HasCallStack, ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s, Show a) =>
Either (ParseErrorBundle s e) a -> Expectation
shouldSucceed Either (ParseErrorBundle s e) a
r = case Either (ParseErrorBundle s e) a
r of
Left ParseErrorBundle s e
e ->
HasCallStack => String -> Expectation
expectationFailure forall a b. (a -> b) -> a -> b
$
String
"the parser is expected to succeed, but it failed with:\n"
forall a. [a] -> [a] -> [a]
++ forall e s.
(ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s) =>
ParseErrorBundle s e -> String
showBundle ParseErrorBundle s e
e
Right a
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
checkUnconsumed ::
( HasCallStack,
Eq s,
Show s
) =>
s ->
s ->
Expectation
checkUnconsumed :: forall s. (HasCallStack, Eq s, Show s) => s -> s -> Expectation
checkUnconsumed s
e s
a =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (s
e forall a. Eq a => a -> a -> Bool
== s
a) forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => String -> Expectation
expectationFailure forall a b. (a -> b) -> a -> b
$
String
"the parser is expected to leave unconsumed input: "
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show s
e
forall a. [a] -> [a] -> [a]
++ String
"\nbut it left this: "
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show s
a
showBundle ::
( ShowErrorComponent e,
Stream s,
VisualStream s,
TraversableStream s
) =>
ParseErrorBundle s e ->
String
showBundle :: forall e s.
(ShowErrorComponent e, Stream s, VisualStream s,
TraversableStream s) =>
ParseErrorBundle s e -> String
showBundle = [String] -> String
unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> String
indent forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s e.
(VisualStream s, TraversableStream s, ShowErrorComponent e) =>
ParseErrorBundle s e -> String
errorBundlePretty
where
indent :: String -> String
indent String
x =
if forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
x
then String
x
else String
" " forall a. [a] -> [a] -> [a]
++ String
x