packages feed

cimple-0.0.26: test/Language/Cimple/CommentParserSpec.hs

{-# LANGUAGE OverloadedStrings #-}
module Language.Cimple.CommentParserSpec where

import           Data.Text          (Text)
import qualified Data.Text          as Text
import           Test.Hspec         (Spec, describe, it, shouldSatisfy)

import           Language.Cimple    (Lexeme, Node)
import           Language.Cimple.IO (parseText)


isRight1 :: Either a [b] -> Bool
isRight1 (Right [_]) = True
isRight1 _           = False


parseLines :: [Text] -> Either String [Node (Lexeme Text)]
parseLines = parseText . Text.unlines


spec :: Spec
spec = do
    describe "Doxygen comment parsing" $ do
        it "should parse a doc comment" $
            parseLines
                [ "/**"
                , " * @brief hello world."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a doc comment with a number at the end" $
            parseLines
                [ "/**"
                , " * @brief hello world."
                , " *"
                , " * There's more to say about today."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a @param" $
            parseLines
                [ "/**"
                , " * @param p1 hello world."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a @param with [in] attribute" $
            parseLines
                [ "/**"
                , " * @param[in] p1 hello world."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a @return" $
            parseLines
                [ "/**"
                , " * @return hello world."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a @retval" $
            parseLines
                [ "/**"
                , " * @retval 0 Success."
                , " * @retval 1 Failure."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a bullet list" $
            parseLines
                [ "/**"
                , " * - item 1"
                , " * - item 2"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a nested bullet list" $
            parseLines
                [ "/**"
                , " * - item 1"
                , " *   - nested item 1"
                , " * - item 2"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a numbered list" $
            parseLines
                [ "/**"
                , " * 1. item 1"
                , " * 2. item 2"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a numbered list with continuation" $
            parseLines
                [ "/**"
                , " * 1. item 1"
                , " *    continued."
                , " * 2. item 2"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a code block" $
            parseLines
                [ "/**"
                , " * @code"
                , " * int x = 5;"
                , " * @endcode"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @deprecated" $
            parseLines
                [ "/**"
                , " * @deprecated Use new_function instead."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @see" $
            parseLines
                [ "/**"
                , " * @see other_function for more details."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @attention" $
            parseLines
                [ "/**"
                , " * @attention This is important."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @note" $
            parseLines
                [ "/**"
                , " * @note This is a note."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @private" $
            parseLines
                [ "/**"
                , " * @private"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @extends" $
            parseLines
                [ "/**"
                , " * @extends BaseClass"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @implements" $
            parseLines
                [ "/**"
                , " * @implements Interface"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @security_rank" $
            parseLines
                [ "/**"
                , " * @security_rank(sink, data, 1)"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse a complex comment" $
            parseLines
                [ "/**"
                , " * @brief A brief description."
                , " *"
                , " * A more detailed description."
                , " * - list item 1"
                , " * - list item 2"
                , " * @param p1 Description for p1."
                , " * @return Description for return."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse words with operators" $
            parseLines
                [ "/**"
                , " * check if x == 5"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @ref" $
            parseLines
                [ "/**"
                , " * see @ref my_ref"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @p" $
            parseLines
                [ "/**"
                , " * @p my_p"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @file" $
            parseLines
                [ "/**"
                , " * @file"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @section" $
            parseLines
                [ "/**"
                , " * @section sec_id sec_title"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse @subsection" $
            parseLines
                [ "/**"
                , " * @subsection subsec_id subsec_title"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse words with colon" $
            parseLines
                [ "/**"
                , " * Note:"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse words with parens" $
            parseLines
                [ "/**"
                , " * (Note)"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse words with parens including long sentences going to the next line" $
            parseLines
                [ "/**"
                , " * This is a comment (and there is more"
                , " * to say about this)."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse words with operators" $
            parseLines
                [ "/**"
                , " * a + b = c"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse words with assignment" $
            parseLines
                [ "/**"
                , " * x = 5"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should parse sentences with various punctuation" $
            parseLines
                [ "/**"
                , " * Is this a question?"
                , " * This is exciting!"
                , " * This is a clause;"
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should allow numbers in the text" $
            parseLines
                [ "/**"
                , " * I have 3 things on my mind."
                , " */"
                , "const int abc = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should allow numbers at the start of the text" $
            parseLines
                [ "/**"
                , " * I have 3 things on my mind. You have"
                , " * 20 things on your mind. We are not the same."
                , " */"
                , "const int my_mind = 3;"
                ]
            `shouldSatisfy` isRight1

        it "should allow numbers at the end of the sentence at the start of a line" $
            parseLines
                [ "/**"
                , " * I have 3 things on my mind. The number of things on your mind is"
                , " * 20."
                , " */"
                , "const int my_mind = 3;"
                ]
            `shouldSatisfy` isRight1