ghc-mod/Info.hs

112 lines
3.7 KiB
Haskell

module Info where
import Control.Applicative hiding (empty)
import Control.Monad
import Data.Maybe
import GHC
import Outputable
import PprTyThing
import Types
import NameSet
import HscTypes
import Data.List
import Control.Exception
import StringBuffer
import System.Time
type Expression = String
type ModuleString = String
----------------------------------------------------------------
typeExpr :: Options -> ModuleString -> Expression -> FilePath -> IO String
typeExpr _ modstr expr file = (++ "\n") <$> typeOf file modstr expr
typeOf :: FilePath -> ModuleString -> Expression -> IO String
typeOf fileName modstr expr =
inModuleContext fileName modstr (pretty <$> exprType expr)
where
pretty = showSDocForUser neverQualify . pprTypeForUser False
----------------------------------------------------------------
infoExpr :: Options -> ModuleString -> Expression -> FilePath -> IO String
infoExpr _ modstr expr file = (++ "\n") <$> info file modstr expr
info :: FilePath -> ModuleString -> FilePath -> IO String
info fileName modstr expr = inModuleContext fileName modstr (infoThing expr)
where
-- ghc/InteractiveUI.hs
infoThing str = do
names <- parseName str
mb_stuffs <- mapM getInfo names
let filtered = filterOutChildren (\(t,_f,_i) -> t) (catMaybes mb_stuffs)
unqual <- getPrintUnqual
return $ showSDocForUser unqual $ vcat (intersperse (text "") $ map (pprInfo False) filtered)
filterOutChildren :: (a -> TyThing) -> [a] -> [a]
filterOutChildren get_thing xs
= [x | x <- xs, not (getName (get_thing x) `elemNameSet` implicits)]
where
implicits = mkNameSet [getName t | x <- xs, t <- implicitTyThings (get_thing x)]
pprInfo :: PrintExplicitForalls -> (TyThing, Fixity, [GHC.Instance]) -> SDoc
pprInfo pefas (thing, fixity, insts)
= pprTyThingInContextLoc pefas thing
$$ show_fixity fixity
$$ vcat (map pprInstance insts)
where
show_fixity fix
| fix == defaultFixity = empty
| otherwise = ppr fix <+> ppr (getName thing)
----------------------------------------------------------------
inModuleContext :: FilePath -> ModuleString -> Ghc String -> IO String
inModuleContext fileName modstr action = withGHC valid
where
valid = do
initSession ["-w"]
setTargetFile fileName
loadWithLogger (\_ -> return ()) LoadAllTargets
ok <- setContextFromTarget
if ok
then action
else invalid
invalid = do
initSession ["-w"]
dummyModule
loadWithLogger defaultWarnErrLogger LoadAllTargets
ok <- setContextFromTarget
if ok
then action
else return errorMessage
dummyModule = do
modgraph <- depanal [mkModuleName modstr] True
let imports = concatMap (map (showSDoc . ppr . unLoc)) $
map ms_imps modgraph ++ map ms_srcimps modgraph
moddef = "module " ++ sanitize modstr ++ " where"
header = moddef : imports
importsBuf <- liftIO . stringToStringBuffer . unlines $ header
clkTime <- liftIO getClockTime
setTargets [Target (TargetModule $ mkModuleName modstr) True (Just (importsBuf, clkTime))]
sanitize = fromMaybe "SomeModule" . listToMaybe . words
errorMessage = "Couldn't determine type"
setContextFromTarget :: Ghc Bool
setContextFromTarget = do
ms <- depanal [] False
top <- map ms_mod <$> filterM isTop ms
setContext top []
return (top /= [])
where
isTop ms = lookupMod `gcatch` returnFalse
where
lookupMod = lookupModule (ms_mod_name ms) Nothing >> return True
returnFalse = constE $ return False
----------------------------------------------------------------
constE :: a -> (SomeException -> a)
constE func = \_ -> func