summaryrefslogtreecommitdiff
path: root/utils/check-exact/Test.hs
diff options
context:
space:
mode:
Diffstat (limited to 'utils/check-exact/Test.hs')
-rw-r--r--utils/check-exact/Test.hs840
1 files changed, 840 insertions, 0 deletions
diff --git a/utils/check-exact/Test.hs b/utils/check-exact/Test.hs
new file mode 100644
index 0000000000..57c09cc737
--- /dev/null
+++ b/utils/check-exact/Test.hs
@@ -0,0 +1,840 @@
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
+{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
+{-# OPTIONS_GHC -Wno-orphans #-}
+
+import Data.List
+import Data.Data
+import GHC.Types.Name.Occurrence
+import GHC.Types.Name.Reader
+import GHC hiding (moduleName)
+import GHC.Driver.Ppr
+import GHC.Driver.Session
+import GHC.Hs.Dump
+import GHC.Data.Bag
+import System.Environment( getArgs )
+import System.Exit
+import System.FilePath
+
+import Types
+import Utils
+import ExactPrint
+import Transform
+import Parsers
+
+import GHC.Parser.Lexer
+import GHC.Data.FastString
+import GHC.Types.SrcLoc
+
+-- ---------------------------------------------------------------------
+
+_tt :: IO ()
+-- _tt = testOneFile changers "/home/alanz/mysrc/git.haskell.org/ghc/_build/stage1/lib"
+_tt = testOneFile changers "/home/alanz/mysrc/git.haskell.org/worktree/exactprint/_build/stage1/lib"
+-- _tt = testOneFile changers "/home/alanz/mysrc/git.haskell.org/worktree/epw/_build/stage1/lib"
+ "cases/RenameCase1.hs" changeRenameCase1
+ -- "cases/LayoutLet2.hs" changeLayoutLet2
+ -- "cases/LayoutLet3.hs" changeLayoutLet3
+ -- "cases/LayoutLet4.hs" changeLayoutLet3
+ -- "cases/Rename1.hs" changeRename1
+ -- "cases/Rename2.hs" changeRename2
+ -- "cases/LayoutIn1.hs" changeLayoutIn1
+ -- "cases/LayoutIn3.hs" changeLayoutIn3
+ -- "cases/LayoutIn3a.hs" changeLayoutIn3
+ -- "cases/LayoutIn3b.hs" changeLayoutIn3
+ -- "cases/LayoutIn4.hs" changeLayoutIn4
+ -- "cases/LocToName.hs" changeLocToName
+ -- "cases/LetIn1.hs" changeLetIn1
+ -- "cases/WhereIn4.hs" changeWhereIn4
+ -- "cases/AddDecl1.hs" changeAddDecl1
+ -- "cases/AddDecl2.hs" changeAddDecl2
+ -- "cases/AddDecl3.hs" changeAddDecl3
+ -- "cases/LocalDecls.hs" changeLocalDecls
+ -- "cases/LocalDecls2.hs" changeLocalDecls2
+ -- "cases/WhereIn3a.hs" changeWhereIn3a
+ -- "cases/WhereIn3b.hs" changeWhereIn3b
+ -- "cases/AddLocalDecl1.hs" addLocaLDecl1
+ -- "cases/AddLocalDecl2.hs" addLocaLDecl2
+ -- "cases/AddLocalDecl3.hs" addLocaLDecl3
+ -- "cases/AddLocalDecl4.hs" addLocaLDecl4
+ -- "cases/AddLocalDecl5.hs" addLocaLDecl5
+ -- "cases/AddLocalDecl6.hs" addLocaLDecl6
+ -- "cases/RmDecl1.hs" rmDecl1
+ -- "cases/RmDecl2.hs" rmDecl2
+ -- "cases/RmDecl3.hs" rmDecl3
+ -- "cases/RmDecl4.hs" rmDecl4
+ -- "cases/RmDecl5.hs" rmDecl5
+ -- "cases/RmDecl6.hs" rmDecl6
+ -- "cases/RmDecl7.hs" rmDecl7
+ -- "cases/RmTypeSig1.hs" rmTypeSig1
+ -- "cases/RmTypeSig2.hs" rmTypeSig2
+ -- "cases/AddHiding1.hs" addHiding1
+ -- "cases/AddHiding2.hs" addHiding2
+
+-- cloneT does not need a test, function can be retired
+
+
+-- exact = ppr
+
+changers :: [(String, Changer)]
+changers =
+ [("noChange", noChange)
+ ,("changeRenameCase1", changeRenameCase1)
+ ,("changeLayoutLet2", changeLayoutLet2)
+ ,("changeLayoutLet3", changeLayoutLet3)
+ ,("changeLayoutIn1", changeLayoutIn1)
+ ,("changeLayoutIn3", changeLayoutIn3)
+ ,("changeLayoutIn4", changeLayoutIn4)
+ ,("changeLocToName", changeLocToName)
+ ,("changeRename1", changeRename1)
+ ,("changeRename2", changeRename2)
+ ,("changeWhereIn4", changeWhereIn4)
+ ,("changeLetIn1", changeLetIn1)
+ ,("changeAddDecl1", changeAddDecl1)
+ ,("changeAddDecl2", changeAddDecl2)
+ ,("changeAddDecl3", changeAddDecl3)
+ ,("changeLocalDecls", changeLocalDecls)
+ ,("changeLocalDecls2", changeLocalDecls2)
+ ,("changeWhereIn3a", changeWhereIn3a)
+ ,("changeWhereIn3b", changeWhereIn3b)
+ ,("addLocaLDecl1", addLocaLDecl1)
+ ,("addLocaLDecl2", addLocaLDecl2)
+ ,("addLocaLDecl3", addLocaLDecl3)
+ ,("addLocaLDecl4", addLocaLDecl4)
+ ,("addLocaLDecl5", addLocaLDecl5)
+ ,("addLocaLDecl6", addLocaLDecl6)
+ ,("rmDecl1", rmDecl1)
+ ,("rmDecl2", rmDecl2)
+ ,("rmDecl3", rmDecl3)
+ ,("rmDecl4", rmDecl4)
+ ,("rmDecl5", rmDecl5)
+ ,("rmDecl6", rmDecl6)
+ ,("rmDecl7", rmDecl7)
+ ,("rmTypeSig1", rmTypeSig1)
+ ,("rmTypeSig2", rmTypeSig2)
+ ,("addHiding1", addHiding1)
+ ,("addHiding2", addHiding2)
+ ,("addHiding2", addHiding2)
+ ]
+
+-- ---------------------------------------------------------------------
+
+usage :: String
+usage = unlines
+ [ "usage: check-ppr (libdir) (file)"
+ , ""
+ , "where libdir is the GHC library directory (e.g. the output of"
+ , "ghc --print-libdir) and file is the file to parse."
+ ]
+
+main :: IO()
+main = do
+ args <- getArgs
+ case args of
+ [libdir,fileName] -> testOneFile changers libdir fileName noChange
+ _ -> putStrLn usage
+
+deriving instance Data Token
+deriving instance Data PsSpan
+deriving instance Data BufSpan
+deriving instance Data BufPos
+
+testOneFile :: [(String, Changer)] -> FilePath -> String -> Changer -> IO ()
+testOneFile _ libdir fileName changer = do
+ (p,_toks) <- parseOneFile libdir fileName
+ -- putStrLn $ "\n\ngot p" ++ showAst (take 4 $ reverse toks)
+ let
+ origAst = ppAst (pm_parsed_source p)
+ anns' = pm_annotations p
+ -- pped = pragmas ++ "\n" ++ (exactPrint $ pm_parsed_source p)
+ pped = exactPrint (pm_parsed_source p) anns'
+ -- pragmas = getPragmas anns'
+
+ newFile = dropExtension fileName <.> "ppr" <.> takeExtension fileName
+ newFileChanged = dropExtension fileName <.> "changed" <.> takeExtension fileName
+ newFileExpected = dropExtension fileName <.> "expected" <.> takeExtension fileName
+ astFile = fileName <.> "ast"
+ newAstFile = fileName <.> "ast.new"
+ changedAstFile = fileName <.> "ast.changed"
+
+ -- pped' <- exactprintWithChange changeRenameCase1 (pm_parsed_source p) anns'
+ (pped', ast') <- exactprintWithChange libdir changer (pm_parsed_source p) anns'
+ -- putStrLn $ "\n\nabout to writeFile"
+ writeFile changedAstFile (ppAst ast')
+ writeFile astFile origAst
+ -- putStrLn $ "\n\nabout to pp"
+ writeFile newFile pped
+ writeFile newFileChanged pped'
+
+ -- putStrLn $ "anns':" ++ showPprUnsafe (apiAnnRogueComments anns')
+
+ (p',_) <- parseOneFile libdir newFile
+
+ let newAstStr :: String
+ newAstStr = ppAst (pm_parsed_source p')
+ writeFile newAstFile newAstStr
+ expectedSource <- readFile newFileExpected
+ changedSource <- readFile newFileChanged
+
+ -- putStrLn $ "\n\nanns':" ++ showPprUnsafe (apiAnnRogueComments anns')
+
+ let
+ origAstOk = origAst == newAstStr
+ changedSourceOk = expectedSource == changedSource
+ if origAstOk && changedSourceOk
+ then do
+ -- putStrLn "ASTs matched"
+ exitSuccess
+ else if not origAstOk
+ then do
+ putStrLn "AST Match Failed"
+ -- putStrLn "\n===================================\nOrig\n\n"
+ -- putStrLn origAst
+ putStrLn "\n===================================\nNew\n\n"
+ putStrLn newAstStr
+ exitFailure
+ else do
+ putStrLn "Changed AST Source Mismatch"
+ putStrLn "\n===================================\nExpected\n\n"
+ putStrLn expectedSource
+ putStrLn "\n===================================\nChanged\n\n"
+ putStrLn changedSource
+ putStrLn "\n===================================\n"
+ putStrLn $ show changedSourceOk
+ exitFailure
+
+ppAst :: Data a => a -> String
+ppAst ast = showSDocUnsafe $ showAstData BlankSrcSpanFile NoBlankApiAnnotations ast
+
+parseOneFile :: FilePath -> FilePath -> IO (ParsedModule, [Located Token])
+parseOneFile libdir fileName = do
+ let modByFile m =
+ case ml_hs_file $ ms_location m of
+ Nothing -> False
+ Just fn -> fn == fileName
+ runGhc (Just libdir) $ do
+ dflags <- getSessionDynFlags
+ let dflags2 = dflags `gopt_set` Opt_KeepRawTokenStream
+ _ <- setSessionDynFlags dflags2
+ addTarget Target { targetId = TargetFile fileName Nothing
+ , targetAllowObjCode = True
+ , targetContents = Nothing }
+ _ <- load LoadAllTargets
+ graph <- getModuleGraph
+ let
+ modSum = case filter modByFile (mgModSummaries graph) of
+ [x] -> x
+ xs -> error $ "Can't find module, got:"
+ ++ show (map (ml_hs_file . ms_location) xs)
+ pm <- GHC.parseModule modSum
+ toks <- getTokenStream (ms_mod modSum)
+ return (pm, toks)
+
+ -- getTokenStream :: GhcMonad m => Module -> m [Located Token]
+
+-- getPragmas :: ApiAnns -> String
+-- getPragmas anns' = pragmaStr
+-- where
+-- tokComment (L _ (AnnBlockComment s)) = s
+-- tokComment (L _ (AnnLineComment s)) = s
+-- tokComment _ = ""
+
+-- comments' = map tokComment $ sortRealLocated $ apiAnnRogueComments anns'
+-- pragmas = filter (\c -> isPrefixOf "{-#" c ) comments'
+-- pragmaStr = intercalate "\n" pragmas
+
+-- pp :: (Outputable a) => a -> String
+-- pp a = showPpr unsafeGlobalDynFlags a
+
+-- ---------------------------------------------------------------------
+
+exactprintWithChange :: FilePath -> Changer -> ParsedSource -> ApiAnns -> IO (String, ParsedSource)
+exactprintWithChange libdir f p anns = do
+ debugM $ "exactprintWithChange:anns=" ++ showGhc (apiAnnRogueComments anns)
+ (anns',p') <- f libdir anns p
+ return (exactPrint p' anns', p')
+
+
+-- First param is libdir
+type Changer = FilePath -> (ApiAnns -> ParsedSource -> IO (ApiAnns,ParsedSource))
+
+noChange :: Changer
+noChange _libdir ans parsed = return (ans,parsed)
+
+changeRenameCase1 :: Changer
+changeRenameCase1 _libdir ans parsed = return (ans,rename "bazLonger" [((3,15),(3,18))] parsed)
+
+changeLayoutLet2 :: Changer
+changeLayoutLet2 _libdir ans parsed = return (ans,rename "xxxlonger" [((7,5),(7,8)),((8,24),(8,27))] parsed)
+
+changeLayoutLet3 :: Changer
+changeLayoutLet3 _libdir ans parsed = return (ans,rename "xxxlonger" [((7,5),(7,8)),((9,14),(9,17))] parsed)
+
+changeLayoutIn1 :: Changer
+changeLayoutIn1 _libdir ans parsed = return (ans,rename "square" [((7,17),(7,19)),((7,24),(7,26))] parsed)
+
+changeLayoutIn3 :: Changer
+changeLayoutIn3 _libdir ans parsed = return (ans,rename "anotherX" [((7,13),(7,14)),((7,37),(7,38)),((8,37),(8,38))] parsed)
+
+changeLayoutIn4 :: Changer
+changeLayoutIn4 _libdir ans parsed = return (ans,rename "io" [((7,8),(7,13)),((7,28),(7,33))] parsed)
+
+changeLocToName :: Changer
+changeLocToName _libdir ans parsed = return (ans,rename "LocToName.newPoint" [((20,1),(20,11)),((20,28),(20,38)),((24,1),(24,11))] parsed)
+
+
+changeRename1 :: Changer
+changeRename1 _libdir ans parsed = return (ans,rename "bar2" [((3,1),(3,4))] parsed)
+
+changeRename2 :: Changer
+changeRename2 _libdir ans parsed = return (ans,rename "joe" [((2,1),(2,5))] parsed)
+
+rename :: (Data a) => String -> [(Pos, Pos)] -> a -> a
+rename newNameStr spans' a
+ = everywhere (mkT replaceRdr) a
+ where
+ newName = mkRdrUnqual (mkVarOcc newNameStr)
+
+ cond :: SrcSpan -> Bool
+ cond ln = ss2range ln `elem` spans'
+
+ replaceRdr :: LocatedN RdrName -> LocatedN RdrName
+ replaceRdr (L ln _)
+ | cond (locA ln) = L ln newName
+ replaceRdr x = x
+
+-- ---------------------------------------------------------------------
+
+changeWhereIn4 :: Changer
+changeWhereIn4 _libdir ans parsed
+ = return (ans,everywhere (mkT replace) parsed)
+ where
+ replace :: LocatedN RdrName -> LocatedN RdrName
+ replace (L ln _n)
+ | ss2range (locA ln) == ((12,16),(12,17)) = L ln (mkRdrUnqual (mkVarOcc "p_2"))
+ replace x = x
+
+-- ---------------------------------------------------------------------
+
+changeLetIn1 :: Changer
+changeLetIn1 _libdir ans parsed
+ = return (ans,everywhere (mkT replace) parsed)
+ where
+ replace :: HsExpr GhcPs -> HsExpr GhcPs
+ replace (HsLet (ApiAnn anc (AnnsLet l _i) cs) localDecls expr)
+ =
+ let (HsValBinds x (ValBinds xv bagDecls sigs)) = localDecls
+ [l2,_l1] = map wrapDecl $ bagToList bagDecls
+ bagDecls' = listToBag $ concatMap decl2Bind [l2]
+ (L (SrcSpanAnn _ le) e) = expr
+ a = (SrcSpanAnn (ApiAnn (Anchor (realSrcSpan le) (MovedAnchor (DP 0 1))) mempty noCom) le)
+ expr' = L a e
+ in (HsLet (ApiAnn anc (AnnsLet l (AD (DP 1 0))) cs) (HsValBinds x (ValBinds xv bagDecls' sigs)) expr')
+
+ replace x = x
+-- ---------------------------------------------------------------------
+
+-- | Add a declaration to AddDecl
+changeAddDecl1 :: Changer
+changeAddDecl1 libdir ans top = do
+ Right (_, decl) <- withDynFlags libdir (\df -> parseDecl df "<interactive>" "nn = n2")
+ let decl' = setEntryDP' decl (DP 2 0)
+
+ let (p',(_,_),_) = runTransform mempty doAddDecl
+ doAddDecl = everywhereM (mkM replaceTopLevelDecls) top
+ replaceTopLevelDecls :: ParsedSource -> Transform ParsedSource
+ replaceTopLevelDecls m = insertAtStart m decl'
+ return (ans,p')
+
+-- ---------------------------------------------------------------------
+changeAddDecl2 :: Changer
+changeAddDecl2 libdir ans top = do
+ Right (_, decl) <- withDynFlags libdir (\df -> parseDecl df "<interactive>" "nn = n2")
+ let decl' = setEntryDP' decl (DP 2 0)
+ let top' = anchorEof top
+
+ let (p',(_,_),_) = runTransform mempty doAddDecl
+ doAddDecl = everywhereM (mkM replaceTopLevelDecls) top'
+ replaceTopLevelDecls :: ParsedSource -> Transform ParsedSource
+ replaceTopLevelDecls m = insertAtEnd m decl'
+ return (ans,p')
+
+-- ---------------------------------------------------------------------
+changeAddDecl3 :: Changer
+changeAddDecl3 libdir ans top = do
+ Right (_, decl) <- withDynFlags libdir (\df -> parseDecl df "<interactive>" "nn = n2")
+ let decl' = setEntryDP' decl (DP 2 0)
+
+ let (p',(_,_),_) = runTransform mempty doAddDecl
+ doAddDecl = everywhereM (mkM replaceTopLevelDecls) top
+ f d (l1:l2:ls) = l1:d:l2':ls
+ where
+ l2' = setEntryDP' l2 (DP 2 0)
+ replaceTopLevelDecls :: ParsedSource -> Transform ParsedSource
+ replaceTopLevelDecls m = insertAt f m decl'
+ return (ans,p')
+
+-- ---------------------------------------------------------------------
+
+-- | Add a local declaration with signature to LocalDecl
+changeLocalDecls :: Changer
+changeLocalDecls libdir ans (L l p) = do
+ Right (_, s@(L ls (SigD _ sig))) <- withDynFlags libdir (\df -> parseDecl df "sig" "nn :: Int")
+ Right (_, d@(L ld (ValD _ decl))) <- withDynFlags libdir (\df -> parseDecl df "decl" "nn = 2")
+ let decl' = setEntryDP' (L ld decl) (DP 1 0)
+ let sig' = setEntryDP' (L ls sig) (DP 0 0)
+ let (p',(_,_),_w) = runTransform mempty doAddLocal
+ doAddLocal = everywhereM (mkM replaceLocalBinds) p
+ replaceLocalBinds :: LMatch GhcPs (LHsExpr GhcPs)
+ -> Transform (LMatch GhcPs (LHsExpr GhcPs))
+ replaceLocalBinds (L lm (Match an mln pats (GRHSs _ rhs (HsValBinds van (ValBinds _ binds sigs))))) = do
+ let oldDecls = sortLocatedA $ map wrapDecl (bagToList binds) ++ map wrapSig sigs
+ let decls = s:d:oldDecls
+ let oldDecls' = captureLineSpacing oldDecls
+ let oldBinds = concatMap decl2Bind oldDecls'
+ (os:oldSigs) = concatMap decl2Sig oldDecls'
+ os' = setEntryDP' os (DP 2 0)
+ let sortKey = captureOrder decls
+ let (ApiAnn anc (AnnList (Just (Anchor anc2 _)) a b c dd) cs) = van
+ let van' = (ApiAnn anc (AnnList (Just (Anchor anc2 (MovedAnchor (DP 1 4)))) a b c dd) cs)
+ let binds' = (HsValBinds van'
+ (ValBinds sortKey (listToBag $ decl':oldBinds)
+ (sig':os':oldSigs)))
+ return (L lm (Match an mln pats (GRHSs noExtField rhs binds')))
+ replaceLocalBinds x = return x
+ return (ans,L l p')
+
+-- ---------------------------------------------------------------------
+
+-- | Add a local declaration with signature to LocalDecl, where there was no
+-- prior local decl. So it adds a "where" annotation.
+changeLocalDecls2 :: Changer
+changeLocalDecls2 libdir ans (L l p) = do
+ Right (_, d@(L ld (ValD _ decl))) <- withDynFlags libdir (\df -> parseDecl df "decl" "nn = 2")
+ Right (_, s@(L ls (SigD _ sig))) <- withDynFlags libdir (\df -> parseDecl df "sig" "nn :: Int")
+ let decl' = setEntryDP' (L ld decl) (DP 1 0)
+ let sig' = setEntryDP' (L ls sig) (DP 0 2)
+ let (p',(_,_),_w) = runTransform mempty doAddLocal
+ doAddLocal = everywhereM (mkM replaceLocalBinds) p
+ replaceLocalBinds :: LMatch GhcPs (LHsExpr GhcPs)
+ -> Transform (LMatch GhcPs (LHsExpr GhcPs))
+ replaceLocalBinds (L lm (Match ma mln pats (GRHSs _ rhs EmptyLocalBinds{}))) = do
+ newSpan <- uniqueSrcSpanT
+ let anc = (Anchor (rs newSpan) (MovedAnchor (DP 1 2)))
+ let anc2 = (Anchor (rs newSpan) (MovedAnchor (DP 1 4)))
+ let an = ApiAnn anc
+ (AnnList (Just anc2) Nothing Nothing
+ [(undeltaSpan (rs newSpan) AnnWhere (DP 0 0))] [])
+ noCom
+ let decls = [s,d]
+ let sortKey = captureOrder decls
+ let binds = (HsValBinds an (ValBinds sortKey (listToBag $ [decl'])
+ [sig']))
+ return (L lm (Match ma mln pats (GRHSs noExtField rhs binds)))
+ replaceLocalBinds x = return x
+ return (ans,L l p')
+
+-- ---------------------------------------------------------------------
+
+-- | Check that balanceCommentsList is idempotent
+changeWhereIn3a :: Changer
+changeWhereIn3a _libdir ans (L l p) = do
+ let decls0 = hsmodDecls p
+ (decls,(_,_),w) = runTransform mempty (balanceCommentsList decls0)
+ (_de0:_:de1:_d2:_) = decls
+ debugM $ unlines w
+ debugM $ "changeWhereIn3a:de1:" ++ showAst de1
+ let p2 = p { hsmodDecls = decls}
+ return (ans,L l p2)
+
+-- ---------------------------------------------------------------------
+
+changeWhereIn3b :: Changer
+changeWhereIn3b _libdir ans (L l p) = do
+ let decls0 = hsmodDecls p
+ (decls,(_,_),w) = runTransform mempty (balanceCommentsList decls0)
+ (de0:_:de1:d2:_) = decls
+ de0' = setEntryDP' de0 (DP 2 0)
+ de1' = setEntryDP' de1 (DP 2 0)
+ d2' = setEntryDP' d2 (DP 2 0)
+ decls' = d2':de1':de0':(tail decls)
+ debugM $ unlines w
+ debugM $ "changeWhereIn3b:de1':" ++ showAst de1'
+ let p2 = p { hsmodDecls = decls'}
+ return (ans,L l p2)
+
+-- ---------------------------------------------------------------------
+
+addLocaLDecl1 :: Changer
+addLocaLDecl1 libdir ans lp = do
+ Right (_, (L ld (ValD _ decl))) <- withDynFlags libdir (\df -> parseDecl df "decl" "nn = 2")
+ let decl' = setEntryDP' (L ld decl) (DP 1 4)
+ doAddLocal = do
+ (de1:d2:d3:_) <- hsDecls lp
+ (de1'',d2') <- balanceComments de1 d2
+ (de1',_) <- modifyValD (getLocA de1'') de1'' $ \_m d -> do
+ return ((wrapDecl decl' : d),Nothing)
+ replaceDecls lp [de1', d2', d3]
+
+ (lp',(_,_),w) <- runTransformT mempty doAddLocal
+ debugM $ "addLocaLDecl1:" ++ intercalate "\n" w
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+addLocaLDecl2 :: Changer
+addLocaLDecl2 libdir ans lp = do
+ Right (_, newDecl) <- withDynFlags libdir (\df -> parseDecl df "decl" "nn = 2")
+ let
+ doAddLocal = do
+ (de1:d2:_) <- hsDecls lp
+ (de1'',d2') <- balanceComments de1 d2
+
+ (parent',_) <- modifyValD (getLocA de1) de1'' $ \_m (d:ds) -> do
+ newDecl' <- transferEntryDP' d newDecl
+ let d' = setEntryDP' d (DP 1 0)
+ return ((newDecl':d':ds),Nothing)
+
+ replaceDecls lp [parent',d2']
+
+ (lp',(_,_),_w) <- runTransformT mempty doAddLocal
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+addLocaLDecl3 :: Changer
+addLocaLDecl3 libdir ans lp = do
+ Right (_, newDecl) <- withDynFlags libdir (\df -> parseDecl df "decl" "nn = 2")
+ -- Right (_, newDecl@(L ld (ValD _ decl))) <- withDynFlags libdir (\df -> parseDecl df "decl" "jj = 2")
+ let
+ doAddLocal = do
+ (de1:d2:_) <- hsDecls lp
+ (de1'',d2') <- balanceComments de1 d2
+
+ (parent',_) <- modifyValD (getLocA de1) de1'' $ \_m (d:ds) -> do
+ let newDecl' = setEntryDP' newDecl (DP 1 0)
+ return (((d:ds) ++ [newDecl']),Nothing)
+
+ replaceDecls (anchorEof lp) [parent',d2']
+
+ (lp',(_,_),_w) <- runTransformT mempty doAddLocal
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+addLocaLDecl4 :: Changer
+addLocaLDecl4 libdir ans lp = do
+ Right (_, newDecl) <- withDynFlags libdir (\df -> parseDecl df "decl" "nn = 2")
+ Right (_, newSig) <- withDynFlags libdir (\df -> parseDecl df "sig" "nn :: Int")
+ -- putStrLn $ "addLocaLDecl4:lp=" ++ showGhc lp
+ let
+ doAddLocal = do
+ (parent:ds) <- hsDecls lp
+
+ let newDecl' = setEntryDP' newDecl (DP 1 0)
+ let newSig' = setEntryDP' newSig (DP 1 4)
+
+ (parent',_) <- modifyValD (getLocA parent) parent $ \_m decls -> do
+ return ((decls++[newSig',newDecl']),Nothing)
+
+ replaceDecls (anchorEof lp) (parent':ds)
+
+ (lp',(_,_),_w) <- runTransformT mempty doAddLocal
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+
+-- ---------------------------------------------------------------------
+
+addLocaLDecl5 :: Changer
+addLocaLDecl5 _libdir ans lp = do
+ let
+ doAddLocal = do
+ decls <- hsDecls lp
+ [s1,de1,d2,d3] <- balanceCommentsList decls
+
+ let d3' = setEntryDP' d3 (DP 2 0)
+
+ (de1',_) <- modifyValD (getLocA de1) de1 $ \_m _decls -> do
+ let d2' = setEntryDP' d2 (DP 1 0)
+ return ([d2'],Nothing)
+ replaceDecls lp [s1,de1',d3']
+
+ (lp',(_,_),_w) <- runTransformT mempty doAddLocal
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+addLocaLDecl6 :: Changer
+addLocaLDecl6 libdir ans lp = do
+ Right (_, newDecl) <- withDynFlags libdir (\df -> parseDecl df "decl" "x = 3")
+ let
+ newDecl' = setEntryDP' newDecl (DP 1 4)
+ doAddLocal = do
+ decls0 <- hsDecls lp
+ [de1'',d2] <- balanceCommentsList decls0
+
+ let de1 = captureMatchLineSpacing de1''
+ let L _ (ValD _ (FunBind _ _ (MG _ (L _ ms) _) _)) = de1
+ let [ma1,_ma2] = ms
+
+ (de1',_) <- modifyValD (getLocA ma1) de1 $ \_m decls -> do
+ return ((newDecl' : decls),Nothing)
+ replaceDecls lp [de1', d2]
+
+ (lp',(_,_),_w) <- runTransformT mempty doAddLocal
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmDecl1 :: Changer
+rmDecl1 _libdir ans lp = do
+ let doRmDecl = do
+ tlDecs0 <- hsDecls lp
+ tlDecs <- balanceCommentsList $ captureLineSpacing tlDecs0
+ let (de1:_s1:_d2:ds) = tlDecs
+
+ replaceDecls lp (de1:ds)
+
+ (lp',(_,_),_w) <- runTransformT mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmDecl2 :: Changer
+rmDecl2 _libdir ans lp = do
+ let
+ doRmDecl = do
+ let
+ go :: GHC.LHsExpr GhcPs -> Transform (GHC.LHsExpr GhcPs)
+ go e@(GHC.L _ (GHC.HsLet{})) = do
+ decs0 <- hsDecls e
+ decs <- balanceCommentsList $ captureLineSpacing decs0
+ e' <- replaceDecls e (init decs)
+ return e'
+ go x = return x
+
+ everywhereM (mkM go) lp
+
+ let (lp',(_,_),_w) = runTransform mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmDecl3 :: Changer
+rmDecl3 _libdir ans lp = do
+ let
+ doRmDecl = do
+ [de1,d2] <- hsDecls lp
+
+ (de1',Just sd1) <- modifyValD (getLocA de1) de1 $ \_m [sd1] -> do
+ let sd1' = setEntryDP' sd1 (DP 2 0)
+ return ([],Just sd1')
+
+ replaceDecls lp [de1',sd1,d2]
+
+ (lp',(_,_),_w) <- runTransformT mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmDecl4 :: Changer
+rmDecl4 _libdir ans lp = do
+ let
+ doRmDecl = do
+ [de1] <- hsDecls lp
+
+ (de1',Just sd1) <- modifyValD (getLocA de1) de1 $ \_m [sd1,sd2] -> do
+ sd2' <- transferEntryDP' sd1 sd2
+
+ let sd1' = setEntryDP' sd1 (DP 2 0)
+ return ([sd2'],Just sd1')
+
+ replaceDecls (anchorEof lp) [de1',sd1]
+
+ (lp',(_,_),_w) <- runTransformT mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmDecl5 :: Changer
+rmDecl5 _libdir ans lp = do
+ let
+ doRmDecl = do
+ let
+ go :: HsExpr GhcPs -> Transform (HsExpr GhcPs)
+ go (HsLet a lb expr) = do
+ decs <- hsDeclsValBinds lb
+ let dec = last decs
+ _ <- transferEntryDPT (head decs) dec
+ lb' <- replaceDeclsValbinds WithoutWhere lb [dec]
+ return (HsLet a lb' expr)
+ go x = return x
+
+ everywhereM (mkM go) lp
+
+ let (lp',(_,_),_w) = runTransform mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmDecl6 :: Changer
+rmDecl6 _libdir ans lp = do
+ let
+ doRmDecl = do
+ [de1] <- hsDecls lp
+
+ (de1',_) <- modifyValD (getLocA de1) de1 $ \_m subDecs -> do
+ let (ss1:_sd1:sd2:sds) = subDecs
+ sd2' <- transferEntryDP' ss1 sd2
+
+ return (sd2':sds,Nothing)
+
+ replaceDecls lp [de1']
+
+ (lp',(_,_),_w) <- runTransformT mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmDecl7 :: Changer
+rmDecl7 _libdir ans lp = do
+ let
+ doRmDecl = do
+ tlDecs <- hsDecls lp
+ [s1,de1,d2,d3] <- balanceCommentsList tlDecs
+
+ d3' <- transferEntryDP' d2 d3
+
+ replaceDecls lp [s1,de1,d3']
+
+ (lp',(_,_),_w) <- runTransformT mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmTypeSig1 :: Changer
+rmTypeSig1 _libdir ans lp = do
+ let doRmDecl = do
+ tlDecs <- hsDecls lp
+ let (s0:de1:d2) = tlDecs
+ s1 = captureTypeSigSpacing s0
+ (L l (SigD x1 (TypeSig x2 [n1,n2] typ))) = s1
+ n2' <- transferEntryDP n1 n2
+ let s1' = (L l (SigD x1 (TypeSig x2 [n2'] typ)))
+ replaceDecls lp (s1':de1:d2)
+
+ let (lp',(_,_),_w) = runTransform mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+rmTypeSig2 :: Changer
+rmTypeSig2 _libdir ans lp = do
+ let doRmDecl = do
+ tlDecs <- hsDecls lp
+ let [de1] = tlDecs
+
+ (de1',_) <- modifyValD (getLocA de1) de1 $ \_m [s,d] -> do
+ d' <- transferEntryDPT s d
+ return ([d'],Nothing)
+ replaceDecls lp [de1']
+
+ let (lp',(_,_),_w) = runTransform mempty doRmDecl
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+addHiding1 :: Changer
+addHiding1 _libdir ans (L l p) = do
+ let doTransform = do
+ l0 <- uniqueSrcSpanT
+ l1 <- uniqueSrcSpanT
+ l2 <- uniqueSrcSpanT
+ let
+ [L li imp1,imp2] = hsmodImports p
+ n1 = L (noAnnSrcSpanDP0 l1) (mkVarUnqual (mkFastString "n1"))
+ n2 = L (noAnnSrcSpanDP0 l2) (mkVarUnqual (mkFastString "n2"))
+ v1 = L (addComma $ noAnnSrcSpanDP0 l1) (IEVar noExtField (L (noAnnSrcSpanDP0 l1) (IEName n1)))
+ v2 = L ( noAnnSrcSpanDP0 l2) (IEVar noExtField (L (noAnnSrcSpanDP0 l2) (IEName n2)))
+ impHiding = L (SrcSpanAnn (ApiAnn (Anchor (realSrcSpan l0) m0)
+ (AnnList Nothing
+ (Just (AddApiAnn AnnOpenP d1))
+ (Just (AddApiAnn AnnCloseP d0))
+ [(AddApiAnn AnnHiding d1)]
+ [])
+ noCom) l0) [v1,v2]
+ imp1' = imp1 { ideclHiding = Just (True,impHiding)}
+ p' = p { hsmodImports = [L li imp1',imp2]}
+ return (L l p')
+
+ let (lp',(_ans',_),_w) = runTransform mempty doTransform
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+-- ---------------------------------------------------------------------
+
+addHiding2 :: Changer
+addHiding2 _libdir ans (L l p) = do
+ let doTransform = do
+ l1 <- uniqueSrcSpanT
+ l2 <- uniqueSrcSpanT
+ let
+ [L li imp1] = hsmodImports p
+ Just (_,L lh ns) = ideclHiding imp1
+ lh' = (SrcSpanAnn (ApiAnn (Anchor (realSrcSpan (locA lh)) m0)
+ (AnnList Nothing
+ (Just (AddApiAnn AnnOpenP d1))
+ (Just (AddApiAnn AnnCloseP d0))
+ [(AddApiAnn AnnHiding d1)]
+ [])
+ noCom) (locA lh))
+ n1 = L (noAnnSrcSpanDP0 l1) (mkVarUnqual (mkFastString "n1"))
+ n2 = L (noAnnSrcSpanDP0 l2) (mkVarUnqual (mkFastString "n2"))
+ v1 = L (addComma $ noAnnSrcSpanDP0 l1) (IEVar noExtField (L (noAnnSrcSpanDP0 l1) (IEName n1)))
+ v2 = L ( noAnnSrcSpanDP0 l2) (IEVar noExtField (L (noAnnSrcSpanDP0 l2) (IEName n2)))
+ L ln n = last ns
+ n' = L (addComma ln) n
+ imp1' = imp1 { ideclHiding = Just (True,L lh' (init ns ++ [n',v1,v2]))}
+ p' = p { hsmodImports = [L li imp1']}
+ return (L l p')
+
+ let (lp',(_ans',_),_w) = runTransform mempty doTransform
+ debugM $ "log:[\n" ++ intercalate "\n" _w ++ "]log end\n"
+ return (ans,lp')
+
+
+-- ---------------------------------------------------------------------
+-- From SYB
+
+-- | Apply transformation on each level of a tree.
+--
+-- Just like 'everything', this is stolen from SYB package.
+everywhere :: (forall a. Data a => a -> a) -> (forall a. Data a => a -> a)
+everywhere f = f . gmapT (everywhere f)
+
+-- | Create generic transformation.
+--
+-- Another function stolen from SYB package.
+mkT :: (Typeable a, Typeable b) => (b -> b) -> (a -> a)
+mkT f = case cast f of
+ Just f' -> f'
+ Nothing -> id
+
+-- ---------------------------------------------------------------------