haskell-tools-debug-1.0.0.0: Language/Haskell/Tools/Debug.hs
{-# LANGUAGE DeriveGeneric, LambdaCase, StandaloneDeriving #-}
module Language.Haskell.Tools.Debug where
import Control.Monad (Monad(..), (=<<), forM_)
import Control.Monad.IO.Class (MonadIO(..))
import Control.Reference ((^.))
import Data.List.Split (splitOn)
import Data.Maybe (Maybe(..), fromJust)
import GHC.Generics (Generic(..))
import System.FilePath (pathSeparator, (</>), (<.>))
import DynFlags (xopt)
import GHC hiding (loadModule)
import GHC.Paths ( libdir )
import Language.Haskell.TH.LanguageExtensions (Extension(..))
import StringBuffer (hGetStringBuffer)
import Language.Haskell.Tools.AST (NodeInfo(..))
import Language.Haskell.Tools.BackendGHC
import Language.Haskell.Tools.Debug.DebugGhcAST ()
import Language.Haskell.Tools.Debug.RangeDebug (srcInfoDebug)
import Language.Haskell.Tools.Debug.RangeDebugInstances ()
import Language.Haskell.Tools.PrettyPrint (prettyPrint)
import Language.Haskell.Tools.PrettyPrint.Prepare
import Language.Haskell.Tools.Refactor
import Language.Haskell.Tools.Refactor.Builtin (builtinRefactorings)
-- | Should be only used for testing
demoRefactor :: String -> String -> [String] -> String -> IO ()
demoRefactor command workingDir args moduleName =
runGhc (Just libdir) $ do
initGhcFlags
_ <- useFlags args
useDirs [workingDir]
ms <- loadModule workingDir moduleName
p <- parseModule ms
t <- typecheckModule p
let annots = pm_annotations $ tm_parsed_module t
hasCPP = Cpp `xopt` ms_hspp_opts ms
liftIO $ putStrLn "=========== tokens:"
liftIO $ putStrLn $ show (fst annots)
liftIO $ putStrLn "=========== comments:"
liftIO $ putStrLn $ show (snd annots)
liftIO $ putStrLn "=========== parsed source:"
liftIO $ putStrLn $ show (pm_parsed_source p)
liftIO $ putStrLn "=========== renamed source:"
liftIO $ putStrLn $ show (fromJust $ tm_renamed_source t)
liftIO $ putStrLn "=========== typechecked source:"
liftIO $ putStrLn $ show (typecheckedSource t)
liftIO $ putStrLn "=========== parsed:"
--transformed <- runTrf (fst annots) (getPragmaComments $ snd annots) $ trfModule (pm_parsed_source p)
parseTrf <- runTrf (fst annots) (getPragmaComments $ snd annots) $ trfModule ms (pm_parsed_source p)
liftIO $ putStrLn $ srcInfoDebug parseTrf
liftIO $ putStrLn "=========== typed:"
transformed <- addTypeInfos (typecheckedSource t) =<< (runTrf (fst annots) (getPragmaComments $ snd annots) $ trfModuleRename ms parseTrf (fromJust $ tm_renamed_source t) (pm_parsed_source p))
liftIO $ putStrLn $ srcInfoDebug transformed
liftIO $ putStrLn "=========== ranges fixed:"
sourceOrigin <- if hasCPP then liftIO $ hGetStringBuffer (workingDir </> map (\case '.' -> pathSeparator; c -> c) moduleName <.> "hs")
else return (fromJust $ ms_hspp_buf $ pm_mod_summary p)
let commented = fixRanges $ placeComments (fst annots) (getNormalComments $ snd annots) $ fixMainRange sourceOrigin transformed
liftIO $ putStrLn $ srcInfoDebug commented
liftIO $ putStrLn "=========== cut up:"
let cutUp = cutUpRanges commented
liftIO $ putStrLn $ srcInfoDebug cutUp
liftIO $ putStrLn $ show $ getLocIndices cutUp
liftIO $ putStrLn $ show $ mapLocIndices sourceOrigin (getLocIndices cutUp)
liftIO $ putStrLn "=========== sourced:"
let sourced = (if hasCPP then extractStayingElems else id) $ rangeToSource sourceOrigin cutUp
liftIO $ putStrLn $ srcInfoDebug sourced
liftIO $ putStrLn "=========== pretty printed:"
let prettyPrinted = prettyPrint sourced
liftIO $ putStrLn prettyPrinted
transformed <- performCommand builtinRefactorings (splitOn " " command)
(Right ((SourceFileKey (moduleSourceFile moduleName) moduleName), sourced))
[]
case transformed of
Right changes -> do
forM_ changes $ \case
ContentChanged (mod, correctlyTransformed) -> do
liftIO $ putStrLn $ "=========== transformed AST (" ++ (mod ^. sfkModuleName) ++ "):"
liftIO $ putStrLn $ srcInfoDebug correctlyTransformed
liftIO $ putStrLn $ "=========== transformed & prettyprinted (" ++ (mod ^. sfkModuleName) ++ "):"
let prettyPrinted = prettyPrint correctlyTransformed
liftIO $ putStrLn prettyPrinted
liftIO $ putStrLn "==========="
ModuleRemoved mod -> do
liftIO $ putStrLn $ "=========== module removed: " ++ mod
ModuleCreated mod cont _ -> do
liftIO $ putStrLn $ "=========== created AST (" ++ mod ++ "):"
liftIO $ putStrLn $ srcInfoDebug cont
liftIO $ putStrLn $ "=========== created & prettyprinted (" ++ mod ++ "):"
let prettyPrinted = prettyPrint cont
liftIO $ putStrLn prettyPrinted
Left transformProblem -> do
liftIO $ putStrLn "==========="
liftIO $ putStrLn transformProblem
liftIO $ putStrLn "==========="
deriving instance Generic SrcSpan
deriving instance Generic (NodeInfo sema src)