content: {-# LANGUAGE CPP #-}
  module UtilsSpec (main, spec) where
  
  import           Test.Hspec
  
  import           TestUtils
  
  import qualified GHC        as GHC
  import qualified HscTypes   as GHC
  
  import Control.Exception
  import Control.Monad.State
  import Data.List
  
  import qualified GhcMod.Types as GM (mpModule)
  
  import Language.Haskell.GHC.ExactPrint.Utils
  import Language.Haskell.Refact.Refactoring.Renaming
  import Language.Haskell.Refact.Utils.GhcVersionSpecific
  import Language.Haskell.Refact.Utils.LocUtils
  import Language.Haskell.Refact.Utils.Monad
  import Language.Haskell.Refact.Utils.MonadFunctions
  import Language.Haskell.Refact.Utils.TypeUtils
  import Language.Haskell.Refact.Utils.Types
  import Language.Haskell.Refact.Utils.Utils
  import Language.Haskell.Refact.Utils.Variables
  
  import Language.Haskell.Refact.Refactoring.RoundTrip
  
  import System.Directory
  
  -- ---------------------------------------------------------------------
  
  main :: IO ()
  main = do
    hspec spec
  
  spec :: Spec
  spec = do
  
    describe "locToExp on ParsedSource" $ do
      it "p:finds the largest leftmost expression contained in a given region #1" $ do
        t <- ct $ parsedFileGhc "./TypeUtils/B.hs"
        let parsed = GHC.pm_parsed_source $ tmParsedModule t
  
        let (Just expr) = locToExp (7,7) (7,43) parsed :: Maybe (GHC.Located (GHC.HsExpr GHC.RdrName))
        getLocatedStart expr `shouldBe` (7,9)
        getLocatedEnd   expr `shouldBe` (7,42)
  
      it "p:finds the largest leftmost expression contained in a given region #2" $ do
        -- ((_, _, mod), toks) <- parsedFileBGhc
        t <- ct $ parsedFileGhc "./TypeUtils/B.hs"
        let modu = GHC.pm_parsed_source $ tmParsedModule t
  
        let (Just expr) = locToExp (7,7) (7,41) modu :: Maybe (GHC.Located (GHC.HsExpr GHC.RdrName))
        getLocatedStart expr `shouldBe` (7,12)
        getLocatedEnd   expr `shouldBe` (7,19)
  
      it "finds the largest leftmost expression in RenamedSource" $ do
        t <- ct $ parsedFileGhc "./TypeUtils/B.hs"
        let renamed = tmRenamedSource t
  
        let (Just expr) = locToExp (7,7) (7,41) renamed :: Maybe (GHC.Located (GHC.HsExpr GHC.Name))
        getLocatedStart expr `shouldBe` (7,12)
        getLocatedEnd   expr `shouldBe` (7,19)
  
    describe "locToExp on RenamedSource" $ do
      it "r:finds the largest leftmost expression contained in a given region #1" $ do
        -- ((_, Just renamed, _), toks) <- parsedFileBGhc
        t <- ct $ parsedFileGhc "./TypeUtils/B.hs"
        let renamed = tmRenamedSource t
  
        let (Just expr) = locToExp (7,7) (7,43) renamed :: Maybe (GHC.Located (GHC.HsExpr GHC.Name))
        getLocatedStart expr `shouldBe` (7,9)
        getLocatedEnd   expr `shouldBe` (7,42)
  
    -- -------------------------------------------------------------------
  
    describe "loading a file" $ do
      it "loads a file having the LANGUAGE CPP pragma" $ do
        t <- ct $ parsedFileGhc "./BCpp.hs"
  
        let parsed = GHC.pm_parsed_source $ tmParsedModule t
        (showGhc parsed) `shouldBe` "module BCpp where\nbob :: Int -> Int -> Int\nbob x y = x + y"
  
       -- ---------------------------------
      it "loads a file having a top comment and LANGUAGE CPP pragma" $ do
        t <- ct $ parsedFileGhc "./BCppTC.hs"
  
        let parsed = GHC.pm_parsed_source $ tmParsedModule t
        (showGhc parsed) `shouldBe` "module BCppTC where\nbob :: Int -> Int -> Int\nbob x y = x + y"
  
       -- ---------------------------------
  
      it "refactors a file having the LANGUAGE CPP pragma" $ do
        r <- ct $ roundTrip defaultTestSettings testOptions "BCpp.hs"
        -- r <- ct $ roundTrip logTestSettings testOptions "BCpp.hs"
        r' <- ct $ mapM makeRelativeToCurrentDirectory r
        r' `shouldBe` ["BCpp.hs"]
        diff <- compareFiles "./test/testdata/BCpp.refactored.hs"
                             "./test/testdata/BCpp.hs"
        diff `shouldBe` []
  
      -- ---------------------------------
  
      it "loads a series of files based on cabal1" $ do
  
        currentDir <- getCurrentDirectory
        setCurrentDirectory "./test/testdata/cabal/cabal1"
  
        let settings = defaultSettings { rsetEnabledTargets = (True,True,False,False)
                                       -- , rsetVerboseLevel = Debug
                                       }
  
        r <- rename settings testOptions "./src/Foo/Bar.hs" "baz1" (3, 1)
        -- r <- rename logTestSettings cradle "./src/Foo/Bar.hs" "baz1" (3, 1)
        r' <- mapM makeRelativeToCurrentDirectory r
        setCurrentDirectory currentDir
  
        (show r') `shouldBe` "[\"src/Foo/Bar.hs\","
                            ++"\"src/main.hs\"]"
  
  
    -- -----------------------------------
  
      it "loads a series of files based on cabal2, which has 2 exe" $ do
  
        currentDir <- getCurrentDirectory
        setCurrentDirectory "./test/testdata/cabal/cabal2"
  
        let settings = defaultSettings { rsetEnabledTargets = (True,True,True,True)
                                       -- , rsetVerboseLevel = Debug
                                       }
  
        let handler = [Handler handler1]
            handler1 :: GHC.SourceError -> IO [String]
            handler1 e = do
               setCurrentDirectory currentDir
               return [show e]
  
        r <- catches (rename settings testOptions "./src/Foo/Bar.hs" "baz1" (3, 1)) handler
        r' <- mapM makeRelativeToCurrentDirectory r
        setCurrentDirectory currentDir
  
  
        (show r') `shouldBe` "[\"src/Foo/Bar.hs\","++
                              "\"src/main1.hs\","++
                              "\"src/main2.hs\"]"
  
    -- -----------------------------------
  
      it "loads a file without a cabal project" $ do
  
        tmp <- getTemporaryDirectory
        let testDir = tmp ++ "/hare-test-no-cabal"
            testFileName = testDir ++ "/Foo.hs"
            testFileContents = unlines
              [ "main = putStrLn \"helo\""
              , "x = 1"
              ]
        createDirectoryIfMissing True testDir
        writeFile testFileName testFileContents
  
        let
          comp = do
           parseSourceFileGhc testFileName
           tm <- getRefactTargetModule
           g <- clientModsAndFiles tm
           return g
        (mg,_s) <- cdAndDo testDir $ runRefactGhc comp initialState testOptions
        -- (mg,_s) <- cdAndDo testDir $ runRefactGhc comp initialLogOnState testOptions
        showGhc (map GM.mpModule mg) `shouldBe` "[]"
  
    -- -----------------------------------
  
      it "loads a series of files based on cabal3, which has a lib and an exe" $ do
  
        currentDir <- getCurrentDirectory
        setCurrentDirectory "./test/testdata/cabal/cabal3"
  
        let settings = defaultSettings { rsetEnabledTargets = (True,True,True,True)
                                       -- , rsetVerboseLevel = Debug
                                       }
  
        let handler = [Handler handler1]
            handler1 :: GHC.SourceError -> IO [String]
            handler1 e = do
               setCurrentDirectory currentDir
               return [show e]
  
        r <- catches (rename settings testOptions "./src/main1.hs" "baz1" (7, 1)) handler
        r' <- mapM makeRelativeToCurrentDirectory r
        setCurrentDirectory currentDir
  
  
        (show r') `shouldBe` "[\"src/main1.hs\"]"
  
    -- -----------------------------------
  
      it "loads a series of files based on cabal4, with different dependencies" $ do
  
        currentDir <- getCurrentDirectory
        setCurrentDirectory "./test/testdata/cabal/cabal4"
  
        let settings = defaultSettings { rsetEnabledTargets = (True,True,True,True)
                                       -- , rsetVerboseLevel = Debug
                                       }
  
        let handler = [Handler handler1]
            handler1 :: GHC.SourceError -> IO [String]
            handler1 e = do
               setCurrentDirectory currentDir
               return [show e]
  
        r <- catches (rename settings testOptions "./src/Foo/Bar.hs" "baz1" (3, 1)) handler
        -- r <- catches (rename settings testOptions "./src/main4.hs" "baz1" (3, 1)) handler
        r' <- mapM makeRelativeToCurrentDirectory r
        setCurrentDirectory currentDir
  
  
        (show r') `shouldBe` "[\"src/Foo/Bar.hs\",\"src/main4.hs\"]"
  
    -- -----------------------------------
  {- TODO: this test fails on travis, due to missing hspec-discover
      it "renames in HaRe Utils 1" $ do
  
        currentDir <- getCurrentDirectory
        -- currentDir `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
        setCurrentDirectory "./"
        -- d <- getCurrentDirectory
        -- d `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
        cradle <- findCradle
        -- (show cradle) `shouldBe` ""
        -- (cradleCurrentDir cradle) `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
  
        let settings = defaultSettings { rsetEnabledTargets = (True,True,True,True)
                                       -- , rsetVerboseLevel = Debug
                                       }
  
        let handler = [Handler handler1]
            handler1 :: GHC.SourceError -> IO [String]
            handler1 e = do
               setCurrentDirectory currentDir
               return [show e]
  
        r <- catches (rename settings cradle "./src/Language/Haskell/Refact/Utils.hs" "clientModsAndFiles1" (473, 6)) handler
        setCurrentDirectory currentDir
  
        r' <- mapM makeRelativeToCurrentDirectory r
  
        (show r') `shouldBe`
            "[\"./src/Language/Haskell/Refact/Utils.hs\","++
             "\"./src/Language/Haskell/Refact/Renaming.hs\","++
             "\"./src/Language/Haskell/Refact/MoveDef.hs\","++
             "\"./src/Language/Haskell/Refact/DupDef.hs\","++
             "\"./src/Language/Haskell/Refact/Renaming.hs\","++
             "\"./src/Language/Haskell/Refact/MoveDef.hs\","++
             "\"./src/Language/Haskell/Refact/DupDef.hs\","++
             "\"test/UtilsSpec.hs\","++
             "\"./src/Language/Haskell/Refact/Renaming.hs\","++
             "\"./src/Language/Haskell/Refact/MoveDef.hs\","++
             "\"./src/Language/Haskell/Refact/DupDef.hs\"]"
  -}
  
    -- -----------------------------------
  {-
      it "renames in HaRe Utils 2" $ do
  
        currentDir <- getCurrentDirectory
        -- currentDir `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
        setCurrentDirectory "./"
        -- d <- getCurrentDirectory
        -- d `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
        cradle <- findCradle
        -- (show cradle) `shouldBe` ""
        -- (cradleCurrentDir cradle) `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
  
        let settings = defaultSettings { rsetEnabledTargets = (True,True,True,True)
                                       , rsetVerboseLevel = Debug
                                       }
  
        let handler = [Handler handler1]
            handler1 :: GHC.SourceError -> IO [String]
            handler1 e = do
               setCurrentDirectory currentDir
               return [show e]
  
        r <- catches (rename settings cradle "./test/UtilsSpec.hs" "parsed" (41, 10)) handler
        setCurrentDirectory currentDir
  
        r' <- mapM makeRelativeToCurrentDirectory r
  
        (show r') `shouldBe`
            "[\"./src/Language/Haskell/Refact/Utils.hs\","++
             "\"./src/Language/Haskell/Refact/Renaming.hs\","++
             "\"./src/Language/Haskell/Refact/MoveDef.hs\","++
             "\"./src/Language/Haskell/Refact/DupDef.hs\","++
             "\"./src/Language/Haskell/Refact/Renaming.hs\","++
             "\"./src/Language/Haskell/Refact/MoveDef.hs\","++
             "\"./src/Language/Haskell/Refact/DupDef.hs\","++
             "\"test/UtilsSpec.hs\","++
             "\"./src/Language/Haskell/Refact/Renaming.hs\","++
             "\"./src/Language/Haskell/Refact/MoveDef.hs\","++
             "\"./src/Language/Haskell/Refact/DupDef.hs\"]"
  -}
    -- -----------------------------------
  {-
    -- This test does not work properly on Travis, missing hspec-discover
      it "renames in HaRe Utils 3" $ do
  
        currentDir <- getCurrentDirectory
        -- currentDir `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
        setCurrentDirectory "./"
        -- d <- getCurrentDirectory
        -- d `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
        cradle <- findCradle
        -- (show cradle) `shouldBe` ""
        -- (cradleCurrentDir cradle) `shouldBe` "/home/alanz/mysrc/github/alanz/HaRe"
  
        let settings = defaultSettings { rsetEnabledTargets = (True,True,True,True)
                                       -- , rsetVerboseLevel = Debug
                                       }
  
        let handler = [Handler handler1]
            handler1 :: GHC.SourceError -> IO [String]
            handler1 e = do
               setCurrentDirectory currentDir
               return [show e]
  
        r <- catches (rename settings cradle "./test/UtilsSpec.hs" "parsed" (41, 11)) handler
        setCurrentDirectory currentDir
  
        r' <- mapM makeRelativeToCurrentDirectory r
  
        (show r') `shouldBe`
            "[\"test/UtilsSpec.hs\"]"
  -}
    -- -------------------------------------------------------------------
  
    describe "sameOccurrence" $ do
      it "checks that a given syntax element is the same occurrence as another" $ do
        pending -- "write this test"
  
    -- -------------------------------------------------------------------
  
    describe "isVarId" $ do
      it "returns True if a string is a lexically valid variable name" $ do
        isVarId "foo" `shouldBe` True
  
      it "returns False if a string is not lexically valid variable name" $ do
        isVarId "Foo" `shouldBe` False
  
  
    -- -------------------------------------------------------------------
  
    describe "getModuleName" $ do
      it "returns a string for the module name if there is one" $ do
        t <- ct $ parsedFileGhc "./TypeUtils/B.hs"
        let modu = GHC.pm_parsed_source $ tmParsedModule t
  
        let (Just (_modname,modNameStr)) = getModuleName modu
        modNameStr `shouldBe` "TypeUtils.B"
  
      it "returns Nothing for the module name otherwise" $ do
        t <- ct $ parsedFileGhc "./NoMod.hs"
        let modu = GHC.pm_parsed_source $ tmParsedModule t
        getModuleName modu `shouldBe` Nothing
  
    -- -------------------------------------------------------------------
  
    describe "modIsExported" $ do
      it "needs a test or two" $ do
        pending  -- "write this test"
  
    -- -------------------------------------------------------------------
  
    describe "clientModsAndFiles" $ do
      it "can only be called in a live RefactGhc session" $ do
        pending  -- "write this test"
  
      ------------------------------------
  
      it "gets modules which directly or indirectly import a module #1" $ do
        -- TODO: harvest this commonality
        let
          comp = do
           parseSourceFileGhc "./S1.hs"
           tm <- getRefactTargetModule
           g <- clientModsAndFiles tm
           return g
        (mg,_s) <- ct $ runRefactGhc comp initialState testOptions
        -- (mg,_s) <- ct $ runRefactGhc comp initialLogOnState testOptions
        (sort $ map (showGhc . GM.mpModule) mg) `shouldBe` ["M2", "M3", "Main"]
  
      ------------------------------------
  
      it "gets modules which directly or indirectly import a module #2" $ do
        let
          comp = do
           parseSourceFileGhc "./M3.hs"
           tm <- getRefactTargetModule
           g <- clientModsAndFiles tm
           return g
        (mg,_s) <- ct $ runRefactGhc comp initialState testOptions
        showGhc (map GM.mpModule mg) `shouldBe` "[Main]"
  
      ------------------------------------
  
      it "gets modules which import a module in different cabal targets" $ do
        currentDir <- getCurrentDirectory
        setCurrentDirectory "./test/testdata/cabal/cabal2"
  
        let
          comp = do
           parseSourceFileGhc "./src/Foo/Bar.hs" -- Load the file first
           tm <- getRefactTargetModule
           g <- clientModsAndFiles tm
           return g
        (mg,_s) <- runRefactGhc comp initialState testOptions
        showGhc (map GM.mpModule mg) `shouldBe` "[Main, Main]"
  
        setCurrentDirectory currentDir
  
      ------------------------------------
  
      it "gets modules when loading without a cabal file" $ do
  
        tmp <- getTemporaryDirectory
        let testDir = tmp ++ "/hare-test-no-cabal-clientmodsandfiles"
            testFileBName   = testDir ++ "/B.hs"
            testFileFooName = testDir ++ "/Foo.hs"
            testFileBContents = unlines
              [ "module B where"
              , "y = 2"
              ]
            testFileFooContents = unlines
              [ "import B"
              , "main = putStrLn \"hello\""
              , "x = y + 1"
              ]
        createDirectoryIfMissing True testDir
        writeFile testFileBName testFileBContents
        writeFile testFileFooName testFileFooContents
  
        let
          comp = do
           parseSourceFileGhc "./Foo.hs" -- Load the file first
           parseSourceFileGhc "./B.hs" -- Load the file first
           tm <- getRefactTargetModule
           g <- clientModsAndFiles tm
           return g
        (mg,_s) <- cdAndDo testDir $ runRefactGhc comp initialState testOptions
        showGhc (map GM.mpModule mg) `shouldBe` "[]"
  
  
      ------------------------------------
  
      it "gets modules for HaRe" $ do
        {-
        let
          comp = do
           parseSourceFileGhc "src/Language/Haskell/Refact/Utils/TypeUtils.hs" -- Load the file first
           tm <- getRefactTargetModule
           g <- clientModsAndFiles tm
           return g
        (mg,_s) <- runRefactGhc comp initialState testOptions
        -- (mg,_s) <- runRefactGhc comp initialLogOnState testOptions
        show (sort $ map GM.mpModule mg) `shouldBe` "[ModuleName \"Language.Haskell.Refact.API\",ModuleName \"Language.Haskell.Refact.HaRe\",ModuleName \"Language.Haskell.Refact.Refactoring.Case\",ModuleName \"Language.Haskell.Refact.Refactoring.DupDef\",ModuleName \"Language.Haskell.Refact.Refactoring.MoveDef\",ModuleName \"Language.Haskell.Refact.Refactoring.Renaming\",ModuleName \"Language.Haskell.Refact.Refactoring.RoundTrip\",ModuleName \"Language.Haskell.Refact.Refactoring.SwapArgs\",ModuleName \"Language.Haskell.Refact.Refactoring.Simple\",ModuleName \"MoveDefSpec\",ModuleName \"Main\",ModuleName \"Main\",ModuleName \"CaseSpec\",ModuleName \"DupDefSpec\",ModuleName \"GhcUtilsSpec\",ModuleName \"RenamingSpec\",ModuleName \"RoundTripSpec\",ModuleName \"SimpleSpec\",ModuleName \"SwapArgsSpec\",ModuleName \"TypeUtilsSpec\",ModuleName \"UtilsSpec\"]"
      -}
      pendingWith "make an equivalent test using testdata/cabal"
  
    -- -------------------------------------------------------------------
  
    describe "serverModsAndFiles" $ do
      it "can only be called in a live RefactGhc session" $ do
        pending  -- "write this test"
  
      it "gets modules which are directly or indirectly imported by a module #1" $ do
        let
          comp = do
           parseSourceFileGhc "./M.hs" -- Load the file first
           g <- serverModsAndFiles $ GHC.mkModuleName "S1"
           return g
        (mg,_s) <- ct $ runRefactGhc comp initialState testOptions
        -- (mg,_s) <- ct $ runRefactGhc comp initialLogOnState testOptions
        showGhc (map GHC.ms_mod mg) `shouldBe` "[]"
  
      it "gets modules which are directly or indirectly imported by a module #2" $ do
        let
          comp = do
           parseSourceFileGhc "./M3.hs" -- Load the file first
           g <- serverModsAndFiles $ GHC.mkModuleName "M3"
           return g
        (mg,_s) <- ct $ runRefactGhc comp initialState testOptions
        showGhc (map GHC.ms_mod mg) `shouldBe` "[M2, S1]"
  
  
    -- -------------------------------------------------------------------
  {-
    describe "getCurrentModuleGraph" $ do
      it "gets the module graph for the currently loaded modules" $ do
        let
          comp = do
           (_p,_toks) <- parseFileBGhc -- Load the file first
           g <- getCurrentModuleGraph
           return g
        (mg,_s) <- runRefactGhcState comp
        map (\m -> GHC.moduleNameString $ GHC.ms_mod_name m) mg `shouldBe` (["TypeUtils.B","TypeUtils.C"])
        map (\m -> show $ GHC.ml_hs_file $ GHC.ms_location m) mg `shouldBe` (["Just \"./test/testdata/TypeUtils/B.hs\""
                                                                             ,"Just \"./test/testdata/TypeUtils/C.hs\""])
  
  
      it "gets the updated graph, after a refactor" $ do
        pending -- "write this test"
  -}
    -- -------------------------------------------------------------------
  {-
    describe "sortCurrentModuleGraph" $ do
      it "needs a test or two" $ do
        let
          comp = do
           (_p,_toks) <- parseFileBGhc -- Load the file first
           g <- sortCurrentModuleGraph
           return g
        (mg,_s) <- runRefactGhcState comp
        (showGhc $ map (\m -> GHC.ms_mod m) (GHC.flattenSCCs mg)) `shouldBe` "[main:TypeUtils.C, main:TypeUtils.B]"
  -}
    -- -------------------------------------------------------------------
  
    describe "parseSourceFileGhc" $ do
      it "retrieves a module from an existing module graph #1" $ do
        let
          comp = do
            parseSourceFileGhc "./S1.hs"
            pr <- getTypecheckedModule
            tm <- getRefactTargetModule
            g <- clientModsAndFiles tm
  
            return (pr,g)
  
        ( (t, mg), _s) <- ct $ runRefactGhc comp initialState testOptions
        let parsed = GHC.pm_parsed_source $ tmParsedModule t
  
        (show $ getModuleName parsed) `shouldBe` "Just (ModuleName \"S1\",\"S1\")"
        (sort $ map (showGhc . GM.mpModule) mg) `shouldBe` ["M2", "M3", "Main"]
  
      -- ---------------------------------
  
      it "loads the module and dependents if no existing module graph" $ do
        let
          comp = do
            parseSourceFileGhc "./S1.hs"
            pr <- getTypecheckedModule
            tm <- getRefactTargetModule
            g <- clientModsAndFiles tm
  
            return (pr,g)
        ((t, mg ), _s) <- ct $ runRefactGhc comp initialState testOptions
        let parsed = GHC.pm_parsed_source $ tmParsedModule t
  
        (show $ getModuleName parsed) `shouldBe` "Just (ModuleName \"S1\",\"S1\")"
        (sort $ map (showGhc . GM.mpModule) mg) `shouldBe` ["M2", "M3", "Main"]
  
      -- ---------------------------------
  
      it "retrieves a module from an existing module graph #2" $ do
        let
          comp = do
            parseSourceFileGhc "./DupDef/Dd1.hs"
            pr <- getTypecheckedModule
            tm <- getRefactTargetModule
            g <- clientModsAndFiles tm
  
            return (pr,g)
        ((t, mg), _s) <- ct $ runRefactGhc comp  initialState testOptions
        let parsed = GHC.pm_parsed_source $ tmParsedModule t
        (show $ getModuleName parsed) `shouldBe` "Just (ModuleName \"DupDef.Dd1\",\"DupDef.Dd1\")"
        showGhc (map GM.mpModule mg) `shouldBe` "[DupDef.Dd2, DupDef.Dd3]"
  
  
    -- -------------------------------------------------------------------
  
    describe "runRefactGhc" $ do
      it "contains a State monad" $ do
        let
         comp = do
          s <- get
          parseSourceFileGhc "./TypeUtils/B.hs"
  
          g <- GHC.getModuleGraph
          gs <- mapM GHC.showModule g
  
          put (s {rsUniqState = 100})
          return (show gs)
  
        (_,s) <- ct $ runRefactGhc comp (initialState { rsModule = Nothing }) testOptions
        (rsUniqState s) `shouldBe` 100
  
      -- ---------------------------------
  
      it "contains the GhcT monad" $ do
        let
         comp = do
          s <- get
          parseSourceFileGhc "./TypeUtils/B.hs"
  
          g <- GHC.getModuleGraph
          gs <- mapM GHC.showModule g
  
          put (s {rsUniqState = 100})
          return (gs)
  
        (r,_) <- ct $ runRefactGhc comp initialState testOptions
        (sort r) `shouldBe` ["TypeUtils.B      ( TypeUtils/B.hs, nothing )",
                             "TypeUtils.C      ( TypeUtils/C.hs, nothing )"]
  
    -- -------------------------------------------------------------------
  
    describe "RefactFlags" $ do
      it "puts the RefactDone flag through its paces" $ do
        let
          comp = do
            parseSourceFileGhc "./FreeAndDeclared/DeclareTypes.hs"
            v1 <- getRefactDone
            clearRefactDone
            v2 <- getRefactDone
            setRefactDone
            v3 <- getRefactDone
  
            return (v1,v2,v3)
        ((v1',v2',v3'), _s) <- ct $ runRefactGhc comp initialState testOptions
  
        (show (v1',v2',v3')) `shouldBe` "(False,False,True)"
  
    -- -------------------------------------------------------------------
  
    describe "directoryManagement" $ do
      it "loads a file from a sub directory" $ do
        t <- ct $ parsedFileGhc "./FreeAndDeclared/DeclareS.hs"
        fileName <- canonicalizePath "./test/testdata/FreeAndDeclared/DeclareS.hs"
        let parsed = GHC.pm_parsed_source $ tmParsedModule t
        let
          comp = do
            parseSourceFileGhc fileName
            r <- hsFreeAndDeclaredPNs parsed
            return r
        ((res),_s) <- cdAndDo "./test/testdata/FreeAndDeclared" $
                       runRefactGhc comp initialState testOptions
  
        -- Free Vars
        (showGhcQual $ map (\n -> (n, getGhcLoc $ GHC.nameSrcSpan n)) (fst res)) `shouldBe` "[]"
  
        -- Declared Vars
        (showGhcQual $ map (\n -> (n, getGhcLoc $ GHC.nameSrcSpan n)) (snd res)) `shouldBe` "[(FreeAndDeclared.DeclareS.c, (6, 1))]"
  
    -- -------------------------------------------------------------------
  
    describe "stripCallStack" $ do
      it "strips a call stack from the end of an error string" $ do
        let s = "\nThe identifier is not a local function/pattern name!\nCallStack (from HasCallStack):\n  error, called at ../src/Language/Haskell/Refact/Refactoring/MoveDef.hs:155:12 in main:Language.Haskell.Refact.Refactoring.MoveDef"
        (stripCallStack s) `shouldBe` "\nThe identifier is not a local function/pattern name!"
  
      it "noops if no call stack from the end of an error string" $ do
        let s = "\nThe identifier is not a local function/pattern name!"
        (stripCallStack s) `shouldBe` "\nThe identifier is not a local function/pattern name!"
  
      it "noops if no call stack from the end of an error string, trailing nl" $ do
        let s = "\nThe identifier is not a local function/pattern name!\n"
        (stripCallStack s) `shouldBe` "\nThe identifier is not a local function/pattern name!\n"
  
  -- ---------------------------------------------------------------------
  