ormolu-0.5.3.0: tests/Ormolu/Fixity/ParserSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Ormolu.Fixity.ParserSpec (spec) where
import qualified Data.Map.Strict as Map
import Data.Text (Text)
import qualified Data.Text as T
import Ormolu.Fixity
import Ormolu.Fixity.Parser
import Test.Hspec
import Test.Hspec.Megaparsec
spec :: Spec
spec = do
describe "parseFixtiyDeclaration" $ do
it "parses a simple infixr declaration" $
parseFixityDeclaration "infixr 5 $"
`shouldParse` [("$", FixityInfo (Just InfixR) 5 5)]
it "parses a simple infixl declaration" $
parseFixityDeclaration "infixl 5 $"
`shouldParse` [("$", FixityInfo (Just InfixL) 5 5)]
it "parses a simple infix declaration" $
parseFixityDeclaration "infix 5 $"
`shouldParse` [("$", FixityInfo (Just InfixN) 5 5)]
it "parses a declaration for a ticked identifier" $
parseFixityDeclaration "infixl 5 `foo`"
`shouldParse` [("foo", FixityInfo (Just InfixL) 5 5)]
it "parses a declaration for a ticked identifier (constructor case)" $
parseFixityDeclaration "infixl 5 `Foo`"
`shouldParse` [("Foo", FixityInfo (Just InfixL) 5 5)]
it "parses a multi-operator declaration" $
parseFixityDeclaration "infixl 5 $, ., `Foo`, `bar`"
`shouldParse` [ ("$", FixityInfo (Just InfixL) 5 5),
(".", FixityInfo (Just InfixL) 5 5),
("Foo", FixityInfo (Just InfixL) 5 5),
("bar", FixityInfo (Just InfixL) 5 5)
]
it "parses a declaration with a unicode operator" $
parseFixityDeclaration "infixr 5 ×"
`shouldParse` [("×", FixityInfo (Just InfixR) 5 5)]
it "fails with correct parse error (keyword wrong)" $
parseFixityDeclaration "foobar 5 $"
`shouldFailWith` err
0
( mconcat
[ utoks "foobar",
etoks "infix",
etoks "infixl",
etoks "infixr"
]
)
it "fails with correct parse error (missing operator)" $
parseFixityDeclaration "infixr 5 "
`shouldFailWith` err
9
( mconcat
[ ueof,
etok '`',
elabel "operator character"
]
)
it "fails with correct parse error (trailing comma)" $
parseFixityDeclaration "infixr 5 ., "
`shouldFailWith` err
12
( mconcat
[ ueof,
etok '`',
elabel "operator character"
]
)
describe "parseFixityMap" $ do
it "parses the empty input without choking" $
parseFixityMap "" ""
`shouldParse` Map.empty
it "parses a collection of declarations" $
-- The example is taken from base.
parseFixityMap
""
( T.unlines
[ "infixr 9 .",
"infixr 5 ++",
"infixl 4 <$",
"infixl 1 >>, >>=",
"infixr 1 =<<",
"infixr 0 $, $!",
"infixl 4 <*>, <*, *>, <**>"
]
)
`shouldParse` Map.fromList
[ ("$", FixityInfo (Just InfixR) 0 0),
("$!", FixityInfo (Just InfixR) 0 0),
("*>", FixityInfo (Just InfixL) 4 4),
("++", FixityInfo (Just InfixR) 5 5),
(".", FixityInfo (Just InfixR) 9 9),
("<$", FixityInfo (Just InfixL) 4 4),
("<*", FixityInfo (Just InfixL) 4 4),
("<**>", FixityInfo (Just InfixL) 4 4),
("<*>", FixityInfo (Just InfixL) 4 4),
("=<<", FixityInfo (Just InfixR) 1 1),
(">>", FixityInfo (Just InfixL) 1 1),
(">>=", FixityInfo (Just InfixL) 1 1)
]
it "combines conflicting declarations correctly" $
parseFixityMap
""
( T.unlines
[ "infixr 9 ., ^",
"infixr 7 ., $",
"infixr 9 ^ ",
"infixl 7 $"
]
)
`shouldParse` Map.fromList
[ ("$", FixityInfo Nothing 7 7),
(".", FixityInfo (Just InfixR) 7 9),
("^", FixityInfo (Just InfixR) 9 9)
]
it "handles CRLF line endings correctly" $
parseFixityMap ""
`shouldSucceedOn` ( unlinesCrlf
[ "infixr 9 .",
"infixr 5 ++"
]
)
it "fails with correct parse error (keyword wrong second line)" $
parseFixityMap "" "infixr 5 .\nfoobar 5 $"
`shouldFailWith` err
11
( mconcat
[ utok 'f',
etoks "infix",
etoks "infixl",
etoks "infixr",
eeof
]
)
unlinesCrlf :: [Text] -> Text
unlinesCrlf = T.concat . fmap (<> "\r\n")