camfort-1.2.0: tests/Camfort/Analysis/CommentAnnotatorSpec.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Camfort.Analysis.CommentAnnotatorSpec (spec) where
import Camfort.Analysis.CommentAnnotator
import Camfort.Specification.Parser (mkParser, parseError, SpecParser)
import Control.Monad.Identity (runIdentity)
import Control.Monad.Writer.Strict
import Data.Data
import Language.Fortran.AST
import Language.Fortran.Version
import Language.Fortran.Util.Position
import Test.Hspec
p :: SrcSpan
p = SrcSpan (Position 0 1 1 "" Nothing) (Position 0 1 1 "" Nothing)
annotateWith :: (String -> String) -> ProgramFile A -> ProgramFile A
annotateWith s = runIdentity . annotateComments trivialParser ignore
where trivialParser = mkParser (Right . s) []
ignore = const . const . pure $ ()
spec :: SpecWith ()
spec =
describe "Comment annotator" $ do
it "annotates with no comment blocks" $
annotateWith (const "") pf `shouldBe` pf
it "links & annotates single comment block" $
annotateWith (const "hello") pf2 `shouldBe` pf2e
it "link multiple comments to single statement" $
annotateWith ("!!!"++) pf3 `shouldBe` pf3e
it "link comments to separate targets" $
annotateWith ("!!!"++) pf4 `shouldBe` pf4e
it "allows handling of parse errors" $ do
let parser :: SpecParser String String
parser = mkParser (const $ Left "This is a warning.") []
shouldBe (runWriter (annotateComments parser (\srcSpan err -> tell [(srcSpan, err)]) pf5))
(pf5e, [ (initSrcSpan, parseError "This is a warning.")
, (initSrcSpan, parseError "This is a warning.")])
data A = A
{ annLink :: Maybe (Block A)
, annAST :: Maybe String }
deriving (Data, Eq, Show)
instance ASTEmbeddable A String where
annotateWithAST a str = a { annAST = Just str }
instance Linkable A where
link a block = a { annLink = Just block }
linkPU = undefined
-- Some helper functions
varGen :: Name -> Expression A
varGen x = ExpValue ea p (ValVariable x)
intGen :: Integer -> Expression A
intGen i = ExpValue ea p (ValInteger (show i) Nothing)
wrapBlocks :: [Block A] -> ProgramFile A
wrapBlocks bs' = ProgramFile (MetaInfo { miVersion = Fortran90, miFilename = "<unknown>" }) [ pu ]
where
pu = PUModule ea p "my_module" bs' Nothing
-- Test cases
mkComment :: String -> Comment a
mkComment = Comment . ("= "++)
ea :: A
ea = A Nothing Nothing
pf :: ProgramFile A
pf = wrapBlocks bs
bs :: [Block A]
bs = [ BlStatement ea p Nothing (StPause ea p Nothing) ]
pf2 :: ProgramFile A
pf2 = wrapBlocks bs2
bs2 :: [Block A]
bs2 =
[ BlComment ea p (mkComment "something")
, BlStatement ea p Nothing (StPause ea p Nothing) ]
pf2e :: ProgramFile A
pf2e = wrapBlocks bs2e
bs2e :: [Block A]
bs2e =
[ BlComment (A (Just (bs2e !! 1)) (Just "hello")) p (mkComment "something")
, BlStatement ea p Nothing (StPause ea p Nothing) ]
pf3 :: ProgramFile A
pf3 = wrapBlocks bs3
bs3 :: [Block A]
bs3 =
[ BlComment ea p (mkComment "mistral")
, BlComment ea p (mkComment "orhan")
, BlComment ea p (mkComment "jean-pierre")
, BlComment ea p (mkComment "contrastin")
, BlStatement ea p Nothing (StPause ea p Nothing) ]
pf3e :: ProgramFile A
pf3e = wrapBlocks bs3e
bs3e :: [Block A]
bs3e =
[ BlComment (A (Just (last bs3e)) (Just "!!!mistral")) p (mkComment "mistral")
, BlComment (A (Just (last bs3e)) (Just "!!!orhan")) p (mkComment "orhan")
, BlComment (A (Just (last bs3e)) (Just "!!!jean-pierre")) p (mkComment "jean-pierre")
, BlComment (A (Just (last bs3e)) (Just "!!!contrastin")) p (mkComment "contrastin")
, BlStatement ea p Nothing (StPause ea p Nothing) ]
pf4 :: ProgramFile A
pf4 = wrapBlocks bs4
bs4 :: [Block A]
bs4 =
[ BlComment ea p (mkComment "mistral")
, BlComment ea p (mkComment "contrastin")
, BlStatement ea p Nothing (StPause ea p Nothing)
, BlComment ea p (mkComment "dominic")
, BlComment ea p (mkComment "orchard")
, BlStatement ea p Nothing (StExpressionAssign ea p (varGen "x") (intGen 42)) ]
pf4e :: ProgramFile A
pf4e = wrapBlocks bs4e
bs4e :: [Block A]
bs4e =
[ BlComment (A (Just (bs4e !! 2)) (Just "!!!mistral")) p (mkComment "mistral")
, BlComment (A (Just (bs4e !! 2)) (Just "!!!contrastin")) p (mkComment "contrastin")
, BlStatement ea p Nothing (StPause ea p Nothing)
, BlComment (A (Just (last bs4e)) (Just "!!!dominic")) p (mkComment "dominic")
, BlComment (A (Just (last bs4e)) (Just "!!!orchard")) p (mkComment "orchard")
, BlStatement ea p Nothing (StExpressionAssign ea p (varGen "x") (intGen 42)) ]
pf5 :: ProgramFile A
pf5 = wrapBlocks bs5
bs5 :: [Block A]
bs5 =
[ BlComment ea p (mkComment "comment 1")
, BlComment ea p (mkComment "comment 2")
, BlStatement ea p Nothing (StPause ea p Nothing) ]
pf5e :: ProgramFile A
pf5e = wrapBlocks bs5e
bs5e :: [Block A]
bs5e =
[ BlComment (A (Just (last bs5e)) Nothing) p (mkComment "comment 1")
, BlComment (A (Just (last bs5e)) Nothing) p (mkComment "comment 2")
, BlStatement ea p Nothing (StPause ea p Nothing) ]