diff --git a/compiler/src/Reporting/Error/Syntax.hs b/compiler/src/Reporting/Error/Syntax.hs index 894b006b..6cab29ce 100644 --- a/compiler/src/Reporting/Error/Syntax.hs +++ b/compiler/src/Reporting/Error/Syntax.hs @@ -70,6 +70,7 @@ data Error | NoPortModulesInPackage A.Region | NoEffectsOutsideKernel A.Region | ParseError Module + deriving (Show) -- MODULE @@ -104,6 +105,7 @@ data Module Infix Row Col | -- Declarations Decl Row Col + deriving (Show) data Exposing = ExposingSpace Space Row Col @@ -117,6 +119,7 @@ data Exposing | -- ExposingIndentEnd Row Col | ExposingIndentValue Row Col + deriving (Show) -- DECLARATIONS @@ -129,6 +132,7 @@ data Decl | DeclDef Name.Name DeclDef Row Col | -- DeclFreshLineAfterDocComment Row Col + deriving (Show) data DeclDef = DeclDefSpace Space Row Col @@ -142,6 +146,7 @@ data DeclDef DeclDefIndentType Row Col | DeclDefIndentEquals Row Col | DeclDefIndentBody Row Col + deriving (Show) data Port = PortSpace Space Row Col @@ -151,6 +156,7 @@ data Port | PortIndentName Row Col | PortIndentColon Row Col | PortIndentType Row Col + deriving (Show) -- TYPE DECLARATIONS @@ -161,6 +167,7 @@ data DeclType | DT_Union CustomType Row Col | -- DT_IndentName Row Col + deriving (Show) data TypeAlias = AliasSpace Space Row Col @@ -170,6 +177,7 @@ data TypeAlias | -- AliasIndentEquals Row Col | AliasIndentBody Row Col + deriving (Show) data CustomType = CT_Space Space Row Col @@ -183,6 +191,7 @@ data CustomType | CT_IndentBar Row Col | CT_IndentAfterBar Row Col | CT_IndentAfterEquals Row Col + deriving (Show) -- EXPRESSIONS diff --git a/gren.cabal b/gren.cabal index e5e4b19c..30555217 100644 --- a/gren.cabal +++ b/gren.cabal @@ -249,8 +249,9 @@ Test-Suite gren-tests Helpers.Parse -- tests - Parse.SpaceSpec + Integration.FormatSpec Parse.RecordUpdateSpec + Parse.SpaceSpec Parse.UnderscorePatternSpec Build-Depends: diff --git a/terminal/src/Format.hs b/terminal/src/Format.hs index 47b9fd6d..4cc0c9c9 100644 --- a/terminal/src/Format.hs +++ b/terminal/src/Format.hs @@ -3,6 +3,7 @@ module Format ( Flags (..), run, + formatByteString, ) where diff --git a/tests/Integration/FormatSpec.hs b/tests/Integration/FormatSpec.hs new file mode 100644 index 00000000..12136d1d --- /dev/null +++ b/tests/Integration/FormatSpec.hs @@ -0,0 +1,62 @@ +{-# LANGUAGE OverloadedStrings #-} + +-- | Integration tests for formatting that cover both the parsing and formatting +-- (tests go from text to text). +module Integration.FormatSpec where + +import Data.ByteString.Builder qualified as Builder +import Data.Text (Text) +import Data.Text qualified as Text +import Data.Text.Encoding qualified as TE +import Data.Text.Lazy qualified as LazyText +import Data.Text.Lazy.Encoding qualified as LTE +import Format qualified +import Test.Hspec + +spec :: Spec +spec = do + describe "top-level definition" $ do + it "formats" $ + ["f = {}"] + `shouldFormatModuleBodyAs` [ "f =", + " {}" + ] + describe "expressions" $ do + describe "record" $ do + it "formats with fields" $ + ["{a=1, b = 2}"] + `shouldFormatExpressionAs` [ "{ a = 1", + ", b = 2", + "}" + ] + +shouldFormatModuleBodyAs :: [Text] -> [LazyText.Text] -> IO () +shouldFormatModuleBodyAs inputLines expectedOutputLines = + let input = TE.encodeUtf8 $ Text.unlines inputLines + expectedOutput = LazyText.unlines expectedOutputLines + actualOutput = LTE.decodeUtf8 . Builder.toLazyByteString <$> Format.formatByteString input + in case LazyText.stripPrefix "module Main exposing (..)\n\n\n\n" <$> actualOutput of + Nothing -> + expectationFailure "shouldFormatModuleBodyAs: failed to format" + Just Nothing -> + expectationFailure "shouldFormatModuleBodyAs: internal error: could not strip module header" + Just (Just actualModuleBody) -> + actualModuleBody `shouldBe` expectedOutput + +shouldFormatExpressionAs :: [Text] -> [LazyText.Text] -> IO () +shouldFormatExpressionAs inputLines expectedOutputLines = + let input = TE.encodeUtf8 $ "expr = " <> Text.unlines inputLines + expectedOutput = LazyText.unlines expectedOutputLines + actualOutput = LTE.decodeUtf8 . Builder.toLazyByteString <$> Format.formatByteString input + cleanOutput i = + LazyText.stripPrefix "module Main exposing (..)\n\n\n\nexpr =\n" i + >>= (return . LazyText.lines) + >>= traverse (LazyText.stripPrefix " ") + >>= (return . LazyText.unlines) + in case fmap cleanOutput actualOutput of + Nothing -> + expectationFailure "shouldFormatExpressionAs: failed to format" + Just Nothing -> + expectationFailure "shouldFormatExpressionAs: internal error: could clean output" + Just (Just actualExpression) -> + actualExpression `shouldBe` expectedOutput