{-# LANGUAGE CPP #-}
-- | Use "runhaskell Setup.hs test" or "cabal test" to run these tests.
module Main where
import Language.Haskell.GHC.ExactPrint
-- import Language.Haskell.GHC.ExactPrint.Types
import Language.Haskell.GHC.ExactPrint.Utils
import GHC.Paths ( libdir )
import qualified DynFlags as GHC
import qualified FastString as GHC
import qualified GHC as GHC
import qualified MonadUtils as GHC
import qualified Outputable as GHC
import qualified GHC.SYB.Utils as SYB
import Control.Monad
import System.Directory
import System.FilePath
import System.IO
import Test.HUnit
-- import qualified Data.Map as Map
-- ---------------------------------------------------------------------
main :: IO Counts
main = runTestTT tests
-- tests = TestCase (do r <- manipulateAstTest "examples/LetStmt.hs" "Layout.LetStmt"
-- assertBool "test" r )
tests = TestList
[
mkTestMod "examples/LetStmt.hs" "Layout.LetStmt"
, mkTestMod "examples/LetExpr.hs" "LetExpr"
, mkTestMod "examples/ExprPragmas.hs" "ExprPragmas"
, mkTestMod "examples/ListComprehensions.hs" "Main"
, mkTestMod "examples/MonadComprehensions.hs" "Main"
, mkTestMod "examples/FunDeps.hs" "Main"
, mkTestMod "examples/ImplicitParams.hs" "Main"
, mkTestMod "examples/RecursiveDo.hs" "Main"
, mkTestMod "examples/TypeFamilies.hs" "Main"
, mkTestMod "examples/MultiParamTypeClasses.hs" "Main"
, mkTestMod "examples/DataFamilies.hs" "DataFamilies"
, mkTestMod "examples/Deriving.hs" "Main"
, mkTestMod "examples/Default.hs" "Main"
, mkTestMod "examples/ForeignDecl.hs" "ForeignDecl"
, mkTestMod "examples/Warning.hs" "Warning"
, mkTestMod "examples/Annotations.hs" "Annotations"
, mkTestMod "examples/DocDecls.hs" "DocDecls"
, mkTestModTH "examples/QuasiQuote.hs" "QuasiQuote"
, mkTestMod "examples/Roles.hs" "Roles"
, mkTestMod "examples/Splice.hs" "Splice"
, mkTestMod "examples/ImportsSemi.hs" "ImportsSemi"
, mkTestMod "examples/Stmts.hs" "Stmts"
, mkTestMod "examples/Mixed.hs" "Main"
, mkTestMod "examples/Arrow.hs" "Arrow"
, mkTestMod "examples/PatSynBind.hs" "Main"
, mkTestMod "examples/HsDo.hs" "HsDo"
, mkTestMod "examples/ForAll.hs" "ForAll"
, mkTestMod "examples/PArr.hs" "PArr"
, mkTestMod "examples/ViewPatterns.hs" "Main"
, mkTestMod "examples/BangPatterns.hs" "Main"
, mkTestMod "examples/Associated.hs" "Main"
, mkTestMod "examples/Move1.hs" "Move1"
, mkTestMod "examples/Rules.hs" "Rules"
, mkTestMod "examples/TypeOperators.hs" "Main"
, mkTestMod "examples/NullaryTypeClasses.hs" "Main"
, mkTestMod "examples/FunctionalDeps.hs" "Main"
, mkTestMod "examples/DerivingOC.hs" "Main"
, mkTestMod "examples/GenericDeriving.hs" "Main"
, mkTestMod "examples/OverloadedStrings.hs" "Main"
, mkTestMod "examples/RankNTypes.hs" "Main"
, mkTestMod "examples/Existential.hs" "Main"
, mkTestMod "examples/ScopedTypeVariables.hs" "Main"
, mkTestMod "examples/Arrows.hs" "Main"
, mkTestMod "examples/TH.hs" "Main"
, mkTestMod "examples/StaticPointers.hs" "Main"
, mkTestMod "examples/DataDecl.hs" "Main"
, mkTestMod "examples/Guards.hs" "Main"
, mkTestMod "examples/RebindableSyntax.hs" "Main"
, mkTestMod "examples/RdrNames.hs" "RdrNames"
, mkTestMod "examples/Vect.hs" "Vect"
, mkTestMod "examples/Tuple.hs" "Main"
, mkTestMod "examples/ExtraConstraints1.hs" "ExtraConstraints1"
, mkTestMod "examples/AddAndOr3.hs" "AddAndOr3"
, mkTestMod "examples/Ann01.hs" "Ann01"
, mkTestMod "examples/StrictLet.hs" "Main"
, mkTestMod "examples/Cg008.hs" "Cg008"
, mkTestMod "examples/T2388.hs" "T2388"
, mkTestMod "examples/T3132.hs" "T3132"
, mkTestMod "examples/Stream.hs" "Stream"
, mkTestMod "examples/Trit.hs" "Trit"
, mkTestMod "examples/DataDecl.hs" "Main"
, mkTestMod "examples/Zipper.hs" "Zipper"
, mkTestMod "examples/Sigs.hs" "Sigs"
, mkTestMod "examples/Utils2.hs" "Utils2"
, mkTestMod "examples/EmptyMostlyInst.hs" "EmptyMostlyInst"
, mkTestMod "examples/EmptyMostlyNoSemis.hs" "EmptyMostlyNoSemis"
, mkTestMod "examples/Dead1.hs" "Dead1"
, mkTestMod "examples/EmptyMostly.hs" "EmptyMostly"
, mkTestMod "examples/FromUtils.hs" "Main"
, mkTestMod "examples/DocDecls.hs" "DocDecls"
, mkTestMod "examples/RecordUpdate.hs" "Main"
-- , mkTestMod "examples/Unicode.hs" "Main"
, mkTestMod "examples/B.hs" "Main"
, mkTestMod "examples/LayoutWhere.hs" "Main"
, mkTestMod "examples/LayoutLet.hs" "Main"
, mkTestMod "examples/Deprecation.hs" "Deprecation"
, mkTestMod "examples/Infix.hs" "Main"
, mkTestMod "examples/BCase.hs" "Main"
, mkTestMod "examples/AltsSemis.hs" "Main"
, mkTestMod "examples/LetExprSemi.hs" "LetExprSemi"
]
mkTestMain :: FilePath -> Test
mkTestMain fileName = TestCase (do r <- manipulateAstTest fileName "Main"
assertBool fileName r )
mkTestMod :: FilePath -> String -> Test
mkTestMod fileName modName
= TestCase (do r <- manipulateAstTest fileName modName
assertBool fileName r )
mkTestModTH :: FilePath -> String -> Test
mkTestModTH fileName modName
= TestCase (do r <- manipulateAstTestTH fileName modName
assertBool fileName r )
-- ---------------------------------------------------------------------
t :: IO Bool
t = do
manipulateAstTest "examples/LetStmt.hs" "Layout.LetStmt"
manipulateAstTest "examples/LetExpr.hs" "LetExpr"
manipulateAstTest "examples/ExprPragmas.hs" "ExprPragmas"
manipulateAstTest "examples/ListComprehensions.hs" "Main"
manipulateAstTest "examples/MonadComprehensions.hs" "Main"
manipulateAstTest "examples/FunDeps.hs" "Main"
manipulateAstTest "examples/ImplicitParams.hs" "Main"
manipulateAstTest "examples/RecursiveDo.hs" "Main"
manipulateAstTest "examples/TypeFamilies.hs" "Main"
manipulateAstTest "examples/MultiParamTypeClasses.hs" "Main"
manipulateAstTest "examples/DataFamilies.hs" "DataFamilies"
manipulateAstTest "examples/Deriving.hs" "Main"
manipulateAstTest "examples/Default.hs" "Main"
manipulateAstTest "examples/ForeignDecl.hs" "ForeignDecl"
manipulateAstTest "examples/Warning.hs" "Warning"
manipulateAstTest "examples/Annotations.hs" "Annotations"
manipulateAstTest "examples/DocDecls.hs" "DocDecls"
manipulateAstTestTH "examples/QuasiQuote.hs" "QuasiQuote"
manipulateAstTest "examples/Roles.hs" "Roles"
manipulateAstTest "examples/Splice.hs" "Splice"
manipulateAstTest "examples/ImportsSemi.hs" "ImportsSemi"
manipulateAstTest "examples/Stmts.hs" "Stmts"
manipulateAstTest "examples/Mixed.hs" "Main"
manipulateAstTest "examples/Arrow.hs" "Arrow"
manipulateAstTest "examples/PatSynBind.hs" "Main"
manipulateAstTest "examples/HsDo.hs" "HsDo"
manipulateAstTest "examples/ForAll.hs" "ForAll"
manipulateAstTest "examples/PArr.hs" "PArr"
manipulateAstTest "examples/ViewPatterns.hs" "Main"
manipulateAstTest "examples/BangPatterns.hs" "Main"
manipulateAstTest "examples/Associated.hs" "Main"
manipulateAstTest "examples/Move1.hs" "Move1"
manipulateAstTest "examples/Rules.hs" "Rules"
manipulateAstTest "examples/TypeOperators.hs" "Main"
manipulateAstTest "examples/NullaryTypeClasses.hs" "Main"
manipulateAstTest "examples/FunctionalDeps.hs" "Main"
manipulateAstTest "examples/DerivingOC.hs" "Main"
manipulateAstTest "examples/GenericDeriving.hs" "Main"
manipulateAstTest "examples/OverloadedStrings.hs" "Main"
manipulateAstTest "examples/RankNTypes.hs" "Main"
manipulateAstTest "examples/Existential.hs" "Main"
manipulateAstTest "examples/ScopedTypeVariables.hs" "Main"
manipulateAstTest "examples/Arrows.hs" "Main"
manipulateAstTest "examples/TH.hs" "Main"
manipulateAstTest "examples/StaticPointers.hs" "Main"
manipulateAstTest "examples/DataDecl.hs" "Main"
manipulateAstTest "examples/Guards.hs" "Main"
manipulateAstTest "examples/RebindableSyntax.hs" "Main"
manipulateAstTest "examples/RdrNames.hs" "RdrNames"
manipulateAstTest "examples/Vect.hs" "Vect"
manipulateAstTest "examples/Tuple.hs" "Main"
manipulateAstTest "examples/ExtraConstraints1.hs" "ExtraConstraints1"
manipulateAstTest "examples/AddAndOr3.hs" "AddAndOr3"
manipulateAstTest "examples/Ann01.hs" "Ann01"
manipulateAstTest "examples/StrictLet.hs" "Main"
manipulateAstTest "examples/Cg008.hs" "Cg008"
manipulateAstTest "examples/T2388.hs" "T2388"
manipulateAstTest "examples/T3132.hs" "T3132"
manipulateAstTest "examples/Stream.hs" "Stream"
manipulateAstTest "examples/Trit.hs" "Trit"
manipulateAstTest "examples/DataDecl.hs" "Main"
manipulateAstTest "examples/Zipper.hs" "Zipper"
manipulateAstTest "examples/Sigs.hs" "Sigs"
manipulateAstTest "examples/Utils2.hs" "Utils2"
manipulateAstTest "examples/EmptyMostlyInst.hs" "EmptyMostlyInst"
manipulateAstTest "examples/EmptyMostlyNoSemis.hs" "EmptyMostlyNoSemis"
manipulateAstTest "examples/Dead1.hs" "Dead1"
manipulateAstTest "examples/EmptyMostly.hs" "EmptyMostly"
manipulateAstTest "examples/FromUtils.hs" "Main"
manipulateAstTest "examples/DocDecls.hs" "DocDecls"
manipulateAstTest "examples/RecordUpdate.hs" "Main"
-- manipulateAstTest "examples/Unicode.hs" "Main"
manipulateAstTest "examples/B.hs" "Main"
manipulateAstTest "examples/LayoutWhere.hs" "Main"
manipulateAstTest "examples/LayoutLet.hs" "Main"
manipulateAstTest "examples/Deprecation.hs" "Deprecation"
manipulateAstTest "examples/Infix.hs" "Main"
manipulateAstTest "examples/BCase.hs" "Main"
manipulateAstTest "examples/AltsSemis.hs" "Main"
manipulateAstTest "examples/LetExprSemi.hs" "LetExprSemi"
{-
manipulateAstTest "examples/Cpp.hs" "Main"
manipulateAstTest "examples/Lhs.lhs" "Main"
manipulateAstTest "examples/ParensAroundContext.hs" "ParensAroundContext"
manipulateAstTest "examples/EmptyMostly2.hs" "EmptyMostly2"
manipulateAstTest "examples/Foo.hs" "Main"
-}
-- | Where all the tests are to be found
examplesDir :: FilePath
examplesDir = "tests" </> "examples"
examplesDir2 :: FilePath
examplesDir2 = "examples"
manipulateAstTest :: FilePath -> String -> IO Bool
manipulateAstTest file modname = manipulateAstTest' False file modname
manipulateAstTestTH :: FilePath -> String -> IO Bool
manipulateAstTestTH file modname = manipulateAstTest' True file modname
manipulateAstTest' :: Bool -> FilePath -> String -> IO Bool
manipulateAstTest' useTH file modname = do
let out = file <.> "out"
golden = file <.> "golden"
contents <- readUTF8File file
(ghcAnns,t) <- parsedFileGhc file modname useTH
let
parsed@(GHC.L l hsmod) = GHC.pm_parsed_source $ GHC.tm_parsed_module t
parsedAST = SYB.showData SYB.Parser 0 parsed
-- parsedAST = showGhc parsed
-- `debug` ("getAnn:=" ++ (show (getAnnotationValue (snd ann) (GHC.getLoc parsed) :: Maybe AnnHsModule)))
-- try to pretty-print; summarize the test result
ann = annotateAST parsed ghcAnns
`debug` ("ghcAnns:" ++ showGhc ghcAnns)
Just (GHC.L le exps) = GHC.hsmodExports hsmod
secondExp@(GHC.L l2 _) = ghead "foo" $ tail exps
ss = GHC.mkSrcSpan (GHC.mkSrcLoc (GHC.mkFastString "examples/PatBind.hs") 16 9)
(GHC.mkSrcLoc (GHC.mkFastString "examples/PatBind.hs") 16 27)
printed = exactPrintAnnotation parsed [] ann -- `debug` ("ann=" ++ (show $ map (\(s,a) -> (ss2span s, a)) $ Map.toList ann))
result =
if printed == contents
then "Match\n"
else printed ++ "\n==============\n"
++ "lengths:" ++ show (length printed,length contents) ++ "\n"
++ parsedAST
-- putStrLn $ "Test:parsed=" ++ parsedAST
writeFile out $ result
-- putStrLn $ "Test:ann organised:" ++ showGhc (organiseAnns ann)
-- putStrLn $ "Test:showdata:" ++ showAnnData (organiseAnns ann) 0 parsed
return ("Match\n" == result)
-- }}}
-- ---------------------------------------------------------------------
-- |Result of parsing a Haskell source file. It is simply the
-- TypeCheckedModule produced by GHC.
type ParseResult = GHC.TypecheckedModule
parsedFileGhc :: String -> String -> Bool -> IO (GHC.ApiAnns,ParseResult)
parsedFileGhc fileName modname useTH = do
putStrLn $ "parsedFileGhc:" ++ show fileName
#if __GLASGOW_HASKELL__ > 704
GHC.defaultErrorHandler GHC.defaultFatalMessager GHC.defaultFlushOut $ do
#else
GHC.defaultErrorHandler GHC.defaultLogAction $ do
#endif
GHC.runGhc (Just libdir) $ do
dflags <- GHC.getSessionDynFlags
let dflags' = foldl GHC.xopt_set dflags
[GHC.Opt_Cpp, GHC.Opt_ImplicitPrelude, GHC.Opt_MagicHash]
dflags'' = dflags' { GHC.importPaths = ["./tests/examples/","../tests/examples/",
"./src/","../src/"] }
tgt = if useTH then GHC.HscInterpreted
else GHC.HscNothing -- allows FFI
dflags''' = dflags'' { GHC.hscTarget = tgt,
GHC.ghcLink = GHC.LinkInMemory
, GHC.packageFlags = [GHC.ExposePackage (GHC.PackageArg "ghc") (GHC.ModRenaming False [])]
}
dflags4 = if False -- useHaddock
then GHC.gopt_set (GHC.gopt_set dflags''' GHC.Opt_Haddock)
GHC.Opt_KeepRawTokenStream
else GHC.gopt_set dflags'''
GHC.Opt_KeepRawTokenStream
-- else GHC.gopt_set (GHC.gopt_unset dflags''' GHC.Opt_Haddock)
-- GHC.Opt_KeepRawTokenStream
(dflags5,args,warns) <- GHC.parseDynamicFlagsCmdLine dflags4 [GHC.noLoc "-package ghc"]
GHC.liftIO $ putStrLn $ "dflags set:(args,warns)" ++ show (map GHC.unLoc args,map GHC.unLoc warns)
void $ GHC.setSessionDynFlags dflags5
-- GHC.liftIO $ putStrLn $ "dflags set"
target <- GHC.guessTarget fileName Nothing
GHC.setTargets [target]
GHC.liftIO $ putStrLn $ "target set:" ++ showGhc (GHC.targetId target)
void $ GHC.load GHC.LoadAllTargets -- Loads and compiles, much as calling make
-- GHC.liftIO $ putStrLn $ "targets loaded"
g <- GHC.getModuleGraph
let showStuff ms = show (GHC.moduleNameString $ GHC.moduleName $ GHC.ms_mod ms,GHC.ms_location ms)
-- GHC.liftIO $ putStrLn $ "module graph:" ++ (intercalate "," (map showStuff g))
modSum <- GHC.getModSummary $ GHC.mkModuleName modname
-- GHC.liftIO $ putStrLn $ "got modSum"
-- let modSum = head g
p <- GHC.parseModule modSum
-- GHC.liftIO $ putStrLn $ "got parsedModule"
t <- GHC.typecheckModule p
GHC.liftIO $ putStrLn $ "typechecked"
-- toks <- GHC.getRichTokenStream (GHC.ms_mod modSum)
-- GHC.liftIO $ putStrLn $ "toks"
let anns = GHC.pm_annotations p
GHC.liftIO $ putStrLn $ "anns"
return (anns,t)
readUTF8File :: FilePath -> IO String
readUTF8File fp = openFile fp ReadMode >>= \h -> do
hSetEncoding h utf8
hGetContents h
-- ---------------------------------------------------------------------
pwd :: IO FilePath
pwd = getCurrentDirectory
cd :: FilePath -> IO ()
cd = setCurrentDirectory
-- ---------------------------------------------------------------------
mkSs :: (Int,Int) -> (Int,Int) -> GHC.SrcSpan
mkSs (sr,sc) (er,ec)
= GHC.mkSrcSpan (GHC.mkSrcLoc (GHC.mkFastString "examples/PatBind.hs") sr sc)
(GHC.mkSrcLoc (GHC.mkFastString "examples/PatBind.hs") er ec)