cimple-0.0.30: test/Language/Cimple/PrettySpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Language.Cimple.PrettySpec where
import Test.Hspec (Spec, describe, it, shouldBe)
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Lazy as TL
import Language.Cimple (Lexeme, Node)
import Language.Cimple.IO (parseText)
import Language.Cimple.Pretty (plain, ppTranslationUnit,
showNode)
import Prettyprinter (SimpleDocStream, layoutCompact)
import Prettyprinter.Render.Terminal (AnsiStyle, renderLazy)
getRight :: Either String a -> a
getRight (Left err) = error err
getRight (Right ok ) = ok
pretty :: String -> String
pretty =
show
. plain
. ppTranslationUnit
. mustParse
compact :: String -> String
compact =
flip displayS ""
. layoutCompact
. plain
. ppTranslationUnit
. mustParse
mustParse :: String -> [Node (Lexeme Text)]
mustParse =
getRight
. parseText
. Text.pack
displayS :: SimpleDocStream AnsiStyle -> ShowS
displayS sdoc =
let rendered = renderLazy sdoc
in (TL.unpack rendered ++)
spec :: Spec
spec = do
-- implementation: Pretty.hs (ppComment).
describe "Regular comment pretty-printing" $ do
it "should pretty-print a doc comment" $
pretty (unlines
[ "/*"
, " * @brief hello world."
, " *"
, " * This is cool stuff."
, " */"
, "const int abc = 3;"
])
`shouldBe` unlines
[ "/*"
, " * @brief hello world."
, " *"
, " * This is cool stuff."
, " */"
, ""
, "int const abc = 3;"
]
describe "showNode" $ do
it "prints code with syntax highlighting" $ do
let pp = case mustParse "int a(void) { return 3; }" of
(x:_) -> showNode x
[] -> error "mustParse returned empty list"
pp <> "\n" `shouldBe` Text.unlines
[ "\ESC[0;32mint\ESC[0m a(\ESC[0;32mvoid\ESC[0m) {"
, " \ESC[0;31mreturn\ESC[0m \ESC[0;31m3\ESC[0m;"
, "}"
]
describe "renderPretty" $ do
it "pretty-prints a simple C function" $ do
let pp = pretty "int a(void) { return 3; }"
pp `shouldBe` unlines
[ "int a(void) {"
, " return 3;"
, "}"
]
it "pretty-prints a typedef struct" $ do
let pp = pretty "typedef struct Foo { int32_t x; } Foo;"
pp `shouldBe` unlines
[ "typedef struct Foo {"
, " int32_t x;"
, "} Foo;"
]
describe "renderCompact" $ do
it "pretty-prints a simple C function" $ do
let pp = compact "int a(void) { return 3; }"
pp `shouldBe` unlines
[ "int a(void) {"
, "return 3;"
, "}"
]
it "pretty-prints a typedef struct" $ do
let pp = compact "typedef struct Foo { int32_t x; } Foo;"
pp `shouldBe` unlines
[ "typedef struct Foo {"
, "int32_t x;"
, "} Foo;"
]
it "pretty-prints ifdef'd struct members in the correct order" $
compact (unlines
[ "typedef struct Foo {"
, " int32_t a;"
, "#ifdef ENABLE_XY"
, " int32_t x;"
, " int32_t y;"
, "#endif /* ENABLE_XY */"
, "} Foo;"
])
`shouldBe` unlines
[ "typedef struct Foo {"
, "int32_t a;"
, "#ifdef ENABLE_XY"
, "int32_t x;"
, ""
, "int32_t y;"
, "#endif /* ENABLE_XY */"
, "} Foo;"
]
it "respects newlines at end of comments" $ do
compact "/* foo bar */" `shouldBe` "/* foo bar */\n"
compact "/* foo bar\n */" `shouldBe` "/* foo bar\n*/\n"
it "respects comment styles" $ do
compact "/* foo bar */" `shouldBe` "/* foo bar */\n"
compact "/*** foo bar */" `shouldBe` "/*** foo bar */\n"
compact "/**** foo bar */" `shouldBe` "/*** foo bar */\n"
-- it "properly formats doxygen comments" $ do
-- compact "/** foo bar */ int a(void);" `shouldBe` "/** foo bar */\n\nint a(void);\n"
it "supports punctuation in comments" $ do
compact "/* foo.bar,baz-blep */"
`shouldBe` "/* foo.bar,baz-blep */\n"
compact "/* foo? */" `shouldBe` "/* foo? */\n"
compact "/* 123 - 456 */" `shouldBe` "/* 123 - 456 */\n"
compact "/* - 3 */" `shouldBe` "/* - 3 */\n"
compact "/* a-b */" `shouldBe` "/* a-b */\n"
it "formats pointer types with east-const" $ do
compact "void foo(const int *a);"
`shouldBe` "void foo(int const* a);\n"
compact "void foo(int const *a);"
`shouldBe` "void foo(int const* a);\n"
it "formats expressions and statements" $ do
compact "void foo() { return 1+2*3/4; }"
`shouldBe` "void foo() {\nreturn 1 + 2 * 3 / 4;\n}\n"
compact "void foo() { a = ~b << !c; }"
`shouldBe` "void foo() {\na = ~b << !c;\n}\n"
compact "void foo() { int a[] = {1,2,3}; }"
`shouldBe` "void foo() {\nint a[] = { 1, 2, 3 };\n}\n"
it "supports variadic functions" $ do
compact "void foo(int a, ...);"
`shouldBe` "void foo(int a, ...);\n"
compact "void foo(int a, const char *msg, ...);"
`shouldBe` "void foo(int a, char const* msg, ...);\n"
it "formats array parameters" $ do
compact "void f(int matrix[ 10][ 10], int j);"
`shouldBe` "void f(int matrix[10][10], int j);\n"
it "supports C preprocessor directives" $ do
compact "#ifndef XYZZY\n#define XYZZY 123\n#endif /* XYZZY */\n"
`shouldBe` "#ifndef XYZZY\n#define XYZZY 123\n#endif /* XYZZY */\n"
compact "#include \"tox.h\"\n"
`shouldBe` "#include \"tox.h\"\n"