ghc-exactprint-1.9.0.0: tests/Test/NoAnnotations.hs
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
module Test.NoAnnotations where
import Data.Algorithm.Diff
import Data.Algorithm.DiffOutput
import Data.List
import Language.Haskell.GHC.ExactPrint
import Language.Haskell.GHC.ExactPrint.Parsers
import Language.Haskell.GHC.ExactPrint.Types
import Language.Haskell.GHC.ExactPrint.Utils
import qualified Control.Monad.IO.Class as GHC
import qualified GHC as GHC hiding (parseModule)
import qualified GHC.Hs.Dump as GHC
import qualified GHC.Utils.Outputable as GHC
import System.Directory
import System.FilePath
import Test.Common
import Test.HUnit
{-# ANN module "HLint: ignore Eta reduce" #-}
-- ---------------------------------------------------------------------
noAnnotationTests :: Test
noAnnotationTests = TestLabel "no annotation tests" $ TestList
[
TestLabel "no annotations"
(TestList noAnnTests)
]
noAnnTests :: [Test]
noAnnTests = [
]
-- ---------------------------------------------------------------------
mkPrettyRoundtrip :: LibDir -> FilePath -> FilePath -> Test
mkPrettyRoundtrip libdir dir fp = mkParsingTest (prettyRoundtripTest libdir) dir fp
prettyRoundtripTest :: LibDir -> FilePath -> IO Report
prettyRoundtripTest libdir origFile = do
-- res <- parseModuleApiAnnsWithCpp defaultCppOptions origFile
res <- parseModuleEpAnnsWithCpp libdir defaultCppOptions origFile
case res of
Left m -> return . Left $ ParseFailure (showErrorMessages m)
Right (injectedComments, _dflags, parsed) -> do
res2 <- GHC.liftIO (runPrettyRoundTrip libdir origFile parsed injectedComments)
case res2 of
Left m -> return . Left $ ParseFailure (showErrorMessages m)
Right parsed' -> do
let
originalStructure = astStructure parsed
roundtripStructure = astStructure parsed'
(status,debugTxt') = if roundtripStructure == originalStructure
then (Success, "ok")
else (RoundTripFailure,diffText originalStructure roundtripStructure
++ sep ++ originalStructure ++ sep ++ roundtripStructure)
cppStatus = Nothing
debugTxt = intercalate sep [ debugTxt'
, originalStructure
, roundtripStructure
, showAst parsed
]
sep = "\n=====================================\n"
return $ Right Report {debugTxt,status,cppStatus}
-- ---------------------------------------------------------------------
runPrettyRoundTrip :: LibDir -> FilePath -> GHC.ParsedSource
-> [GHC.LEpaComment]
-> IO (ParseResult GHC.ParsedSource)
runPrettyRoundTrip libdir origFile !parsedOrig _cs = do
let priorComments = GHC.priorComments $ GHC.epAnnComments $ GHC.hsmodAnn
$ GHC.hsmodExt $ GHC.unLoc parsedOrig
let comments = concatMap tokComment priorComments
let pragmas = filter (\(Comment c _ _ _) -> isPrefixOf "{-#" c ) comments
let pragmaStr = intercalate "\n" $ map commentContents pragmas
let !printed = pragmaStr ++ "\n" ++ exactPrint parsedOrig
parseString libdir origFile printed parsedOrig
parseString :: LibDir -> FilePath -> String -> GHC.ParsedSource
-> IO (ParseResult GHC.ParsedSource)
parseString libdir origFile src origParsed = do
tmpDir <- getTemporaryDirectory
let workDir = tmpDir </> "ghc-exactprint" </> "noannotations"
-- putStrLn $ "workDir=" ++ workDir
createDirectoryIfMissing True workDir
let fileName = workDir </> takeFileName origFile
writeFile (workDir </> takeFileName origFile <.> ".anns")
(showAst origParsed)
writeFile fileName src
parseModule libdir fileName
-- ---------------------------------------------------------------------
diffText :: String -> String -> String
diffText f1 f2 = diff
where
d = getGroupedDiff (lines f1) (lines f2)
diff = ppDiff d
-- ---------------------------------------------------------------------
-- |Convert an AST with comments into a string representing the structure only
-- (i.e. ignoring locations), to be used for comparisons between the original
-- AST and the one after pretty-print roundtripping.
astStructure :: GHC.ParsedSource -> String
astStructure parsed = r
where
r = GHC.showSDocUnsafe
$ GHC.showAstData GHC.BlankSrcSpanFile GHC.NoBlankEpAnnotations parsed