PageRenderTime 28ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Scion/Inspect/IFaceLoader.hs

http://github.com/JPMoresmau/scion
Haskell | 524 lines | 403 code | 39 blank | 82 comment | 23 complexity | ea50684d11cebf2b64e286ab0651c567 MD5 | raw file
  1. {-# LANGUAGE ScopedTypeVariables #-}
  2. -- |
  3. -- Module : Scion.Inspect.ModuleLoader
  4. -- Copyright : (c) B. Scott Michel, 2011
  5. -- License : BSD-style
  6. --
  7. -- Maintainer : bscottm@ieee.org
  8. -- Stability : experimental
  9. -- Portability : portable
  10. --
  11. -- Collect symbol names from modules to support IDE completion.
  12. --
  13. -- Note: The inspiration for this source code comes from the Leksah IDE's server
  14. module Scion.Inspect.IFaceLoader
  15. ( updateMCacheFromTypecheck
  16. , unknownPackageId
  17. , unknownModule
  18. , updateHomeModuleTyCons
  19. ) where
  20. import Scion.Types
  21. import Scion.Utils
  22. import Scion.Inspect
  23. import qualified Data.Map as Map
  24. import qualified Data.Set as Set
  25. import qualified Data.Foldable as Fold
  26. import qualified Data.List as List
  27. -- GHC's imports
  28. import GHC
  29. import GHC.Exception()
  30. import BasicTypes
  31. import HscTypes
  32. import Module
  33. import Outputable
  34. import Finder
  35. import qualified Maybes
  36. import LoadIface
  37. import TcRnTypes
  38. import TcRnMonad
  39. import OccName
  40. import IfaceSyn
  41. import RdrName
  42. #if __GLASGOW_HASKELL__ < 700
  43. import LazyUniqFM
  44. #else
  45. import UniqFM ( lookupUFM )
  46. #endif
  47. -- System imports
  48. import System.Directory
  49. import System.Time
  50. -- | Synonym for a set of OccNames
  51. type OccNameSet = Set.Set OccName
  52. -- | A Module set that tracks modules already read and avoid infinite interface read cycles
  53. type ModulesRead = Set.Set Module
  54. -- | Modules that are hidden or had IO errors.
  55. type ModErrorSet = Set.Set ModuleName
  56. -- | State we drag along while we're reading interfaces
  57. data ModStateT =
  58. ModStateT {
  59. modsRead :: ModulesRead
  60. , exportSyms :: OccNameSet
  61. , modSyms :: ModSymData
  62. , hiddenMods :: ModErrorSet
  63. , otherMods :: ModErrorSet
  64. }
  65. -- | Dependent module information type
  66. type DepModuleInfo = (Module, [Module])
  67. -- | Get the list of modules associated with the type-checked source, updating the module cache
  68. -- as needed.
  69. updateMCacheFromTypecheck :: ParsedModule -- ^ The parsed module
  70. -> ScionM ModuleCache -- ^ The updated module cache
  71. updateMCacheFromTypecheck pm = generateDepModuleInfo pm >>= updateModuleCache
  72. -- | Update the module cache
  73. updateModuleCache :: ([ImportDecl RdrName], DepModuleInfo)
  74. -> ScionM ModuleCache
  75. updateModuleCache (impDecls, (topMod, depMods)) =
  76. getSessionSelector moduleCache
  77. >>= updateModules depMods
  78. >>= updateImpDecls topMod impDecls
  79. -- | Update a home module's associated import declaration list. Note: This only applies to home, i.e., not external pacakge,
  80. -- modules. Returns the updated module cache, where information about this module resides.
  81. updateImpDecls :: Module -- ^ The home module
  82. -> [ImportDecl RdrName] -- ^ The import declarations list
  83. -> ModuleCache -- ^ The associated module cache
  84. -> ScionM ModuleCache -- ^ The updated module cache
  85. updateImpDecls topMod impDecls mCache = return $ Map.insert topMod (struct { importDecls = impDecls }) mCache
  86. where
  87. struct = case Map.lookup topMod mCache of
  88. (Just mdata) -> mdata
  89. Nothing -> emptyModCacheData
  90. -- | Extract the modules referenced by the parsed module, returning
  91. -- the primary module's data and a list of the dependent modules
  92. generateDepModuleInfo :: ParsedModule -- ^ The parsed module
  93. -> ScionM ([ImportDecl RdrName], DepModuleInfo) -- ^ Returned import declarations and dependent modules
  94. -- ^ Primary module, dependent modules list
  95. generateDepModuleInfo pm = getInnerModules >>= depImportsModules
  96. where
  97. -- What we return
  98. depImportsModules mods = return (impDecls, (thisMod, mods))
  99. -- Associated machinery with generating what we return
  100. thisModSum = pm_mod_summary pm
  101. thisMod = ms_mod thisModSum
  102. impDecls = map unLoc $ ms_imps thisModSum
  103. initialModNames = map (unLoc . ideclName) impDecls
  104. -- Ensure that Prelude is part of the list of modules scanned
  105. innerModNames = if preludeModName `List.notElem` initialModNames
  106. then preludeModName:initialModNames
  107. else initialModNames
  108. -- Change Prelude's package ID to make it easier to lookup later, if lookupModule
  109. -- found Prelude in a package more specific than "base".
  110. fixModulePkg m
  111. | moduleName m == preludeModName
  112. = mkModule basePackageId (moduleName m)
  113. | otherwise
  114. = m
  115. fixModulePkgs mods = return $ map fixModulePkg mods
  116. getInnerModules = mapM modLookup innerModNames >>= fixModulePkgs
  117. -- Catch the GHC source error exception when a module doesn't appear to be loaded
  118. modLookup mName = gcatch (lookupModule mName Nothing)
  119. (\(_ :: SourceError) -> return (unknownModule mName))
  120. -- | Handy reference to Prelude's module name
  121. preludeModName :: ModuleName
  122. preludeModName = mkModuleName "Prelude"
  123. -- | Examine the incoming module list, read interface files if needed, return the updated module cache
  124. updateModules :: [Module] -- ^ The dependent module list
  125. -> ModuleCache -- ^ The original/incoming module cache
  126. -> ScionM ModuleCache -- ^ The updated module cache
  127. updateModules [] mCache = return mCache
  128. updateModules (m:mods) mCache
  129. | unknownPackageId == (modulePackageId m)
  130. = modDebugMsg m "Ignoring "
  131. >> updateModules mods mCache
  132. | mainPackageId == (modulePackageId m)
  133. = modDebugMsg m "Adding (main/home) "
  134. >> cacheHomePackageModule m mCache
  135. >>= updateModules mods
  136. | Nothing <- Map.lookup m mCache
  137. = modDebugMsg m "Adding "
  138. >> cacheIFaceModule m mCache
  139. >>= updateModules mods
  140. | otherwise
  141. = case Map.lookup m mCache of
  142. (Just mData) ->do
  143. ifM (moduleChanged m (lastModTime mData))
  144. (modDebugMsg m "Updating "
  145. >> cacheIFaceModule m mCache
  146. >>= updateModules mods)
  147. (modDebugMsg m "NoMod " >> updateModules mods mCache)
  148. Nothing ->
  149. modDebugMsg m "NoMod??! " >> updateModules mods mCache
  150. -- | Package identifier for unknown/unloaded modules
  151. unknownPackageId :: PackageId
  152. unknownPackageId = stringToPackageId "*unknown*"
  153. -- Predicate for detecting if the module's time/date stamp has changed
  154. moduleChanged :: Module -- ^ The module to test
  155. -> ClockTime -- ^ Existing last-modified time of the module
  156. -> ScionM Bool -- ^ The result
  157. moduleChanged m modTime = getSession >>= compareMTimes
  158. where
  159. compareMTimes hsc = liftIO (findExactModule hsc m >>= checkMTimes)
  160. -- May return True or False
  161. checkMTimes (Found loc _) =
  162. getModificationTime (ml_hi_file loc)
  163. >>= (\hiMTime -> return (diffClockTimes modTime hiMTime /= noTimeDiff))
  164. -- Ensure that we leave the interface file alone if it cannot be found.
  165. checkMTimes _ = return False
  166. -- | Trace actions related to whether we load/ignore/update a Haskell interface
  167. modDebugMsg :: Module
  168. -> String
  169. -> ScionM ()
  170. modDebugMsg m msg = message Verbose (showSDoc $ text msg <+> ppr m)
  171. -- | Find and load the Haskell interface file, extracting its exports and correlating them
  172. -- with the declarations. Note that the interface's export list only tells us the names of
  173. -- things that are exported; we subsequently have to look at the mi_decls list to extract
  174. -- specifics (Is something a type name or class? Does a constructor have arguments?)
  175. cacheIFaceModule :: Module
  176. -> ModuleCache
  177. -> ScionM ModuleCache
  178. cacheIFaceModule m cache = getInterfaceFile m >>= readIFace
  179. where
  180. readIFace :: Maybe (ModIface, FilePath) -> ScionM ModuleCache
  181. readIFace (Just (iface, fpath)) =
  182. let eSet = exportSet iface
  183. initialMState = ModStateT {
  184. modsRead = Set.singleton m
  185. , exportSyms = eSet
  186. , modSyms = Map.empty
  187. , hiddenMods = Set.empty
  188. , otherMods = Set.empty
  189. }
  190. updateModSyms mstate = do
  191. let fixedMState = fixPrelude m mstate
  192. updMSyms = modSyms fixedMState
  193. mcd <- liftIO (mkModCacheData fpath updMSyms)
  194. debugModSymData (exportSyms fixedMState) updMSyms
  195. >> reportProblems m fixedMState
  196. >> (return $ Map.insert m mcd cache)
  197. in collectInterface initialMState iface
  198. >>= updateModSyms
  199. readIFace Nothing = modDebugMsg m "Could not load " >> return cache
  200. -- | Extract the set of occurrance names exported through the module interface. This is a
  201. -- straightforward list-to-set transformation
  202. exportSet :: ModIface -> OccNameSet
  203. exportSet iface = List.foldl' insertExp Set.empty [i | (_, i) <- mi_exports iface]
  204. where
  205. insertExp eSet names = List.foldl' insertExp' eSet names
  206. insertExp' eSet (Avail name) = Set.insert name eSet
  207. insertExp' eSet (AvailTC name mbrs) = Set.union (Set.insert name eSet) (Set.fromList mbrs)
  208. reportProblems :: Module -> ModStateT -> ScionM ()
  209. reportProblems m mstate =
  210. if haveProblems
  211. then (liftIO $ logWarn $ (moduleNameString (moduleName m)) ++ " module cache:")
  212. {- >> listProblems "-- Hidden modules: " (modNameList (hiddenMods mstate)) -}
  213. >> listProblems "-- Unreadable modules: " (modNameList (otherMods mstate))
  214. >> listProblems "-- Symbols not cached: " (occNameList (exportSyms mstate))
  215. else return ()
  216. where
  217. -- The haveProblems predicate is here to make commenting/uncommenting stuff easier.
  218. haveProblems = not ({- (Set.null (hiddenMods mstate)) &&-} (Set.null (otherMods mstate)) && (Set.null (exportSyms mstate)))
  219. listProblems title (mn:mns) = liftIO $ logWarn $ title ++ (List.foldl' (\acc s -> acc ++ ", " ++ s) mn mns)
  220. listProblems _ [] = return ()
  221. modNameList modnames = [ moduleNameString mn | mn <- Set.toList modnames ]
  222. occNameList occNames = [ occNameString o | o <- Set.toList occNames ]
  223. -- | Cache names from a home package module, i.e., something that's not an external package and
  224. -- is likely to be part of the "main" package
  225. cacheHomePackageModule :: Module
  226. -> ModuleCache
  227. -> ScionM ModuleCache
  228. cacheHomePackageModule m cache = withSession readHomePackageModule
  229. where
  230. readHomePackageModule hsc =
  231. case lookupUFM (hsc_HPT hsc) (moduleName m) of
  232. (Just hmi) -> do
  233. let iface = hm_iface hmi
  234. eSet = exportSet iface
  235. initialMState = ModStateT {
  236. modsRead = Set.singleton m
  237. , exportSyms = eSet
  238. , modSyms = case Map.lookup m cache of
  239. (Just msyms) -> modSymData msyms
  240. Nothing -> Map.empty
  241. , hiddenMods = Set.empty
  242. , otherMods = Set.empty
  243. }
  244. collectInterface initialMState iface
  245. >>= (\mstate ->do
  246. let updMSyms = modSyms mstate
  247. mcd <- liftIO (mkModCacheData "." updMSyms) -- getModificationTime "" throws an error on unixes
  248. (debugModSymData (exportSyms mstate) updMSyms)
  249. >> (reportProblems m mstate)
  250. >> (return $ Map.insert m mcd cache))
  251. Nothing -> return cache
  252. -- | Collect declarations from a Haskell interface's mi_usages module usage list.
  253. collectUsageDecls :: ModStateT -> Usage -> ScionM ModStateT
  254. collectUsageDecls mstate (UsagePackageModule usedMod _) =
  255. let eSet = exportSyms mstate
  256. mods = modsRead mstate
  257. updMState iface origMState = origMState { modsRead = Set.insert (mi_module iface) mods }
  258. readIfaceFile (Just (iface, _)) = collectInterface (updMState iface mstate) iface
  259. readIfaceFile Nothing = return mstate
  260. in if not (Set.null eSet) && (Set.notMember usedMod mods)
  261. then getInterfaceFile usedMod >>= readIfaceFile
  262. else return mstate
  263. collectUsageDecls mstate (UsageHomeModule usedMod _ _ _) =
  264. let mods = modsRead mstate
  265. addHiddenMod theMod =
  266. return mstate {
  267. hiddenMods = Set.insert theMod (hiddenMods mstate)
  268. }
  269. processModule m =
  270. if Set.notMember m mods
  271. then getInterfaceFile m >>= readModule m
  272. else return mstate
  273. -- Read an actual interface
  274. readModule m (Just (iface, _)) = collectInterface (updMState m) iface
  275. -- Need to try harder: This could be a home module
  276. readModule m Nothing =
  277. withSession (\hsc ->
  278. case lookupUFM (hsc_HPT hsc) (moduleName m) of
  279. Just homeModInfo -> collectInterface (updMState m) (hm_iface homeModInfo)
  280. Nothing -> return (updMState m)
  281. )
  282. updMState m = mstate { modsRead = Set.insert m mods }
  283. in if not (Set.null (exportSyms mstate))
  284. then gcatch
  285. (lookupModule usedMod Nothing >>= processModule)
  286. -- We can get a SourceError if GHC can't find the module
  287. (\(_ :: SourceError) -> addHiddenMod usedMod)
  288. else return mstate
  289. -- | The basic Haskell interface collector driver.
  290. collectInterface :: ModStateT -> ModIface -> ScionM ModStateT
  291. collectInterface mstate iface =
  292. let declsList = [ d | (_, d) <- mi_decls iface ]
  293. updMState = List.foldl' processDecl mstate declsList
  294. usages = mi_usages iface
  295. in Fold.foldlM collectUsageDecls updMState usages
  296. debugModSymData :: OccNameSet -> ModSymData -> ScionM ()
  297. debugModSymData eSet msyms = message Verbose $ matchLengths ++ "\n" ++ modSymDump
  298. where
  299. missing = Set.difference (Set.fromList (map occNameString (Set.toList eSet)))
  300. (Set.fromList (map (showSDoc . ppr) (Map.keys msyms)))
  301. exportedSize = Set.size eSet
  302. msymSize = Map.size msyms
  303. matchLengths
  304. | Set.null missing
  305. = "-- Everything extracted --"
  306. | otherwise
  307. = (show exportedSize)
  308. ++ " not found, "
  309. ++ (show msymSize)
  310. ++ " collected\ndifference is "
  311. ++ (show missing)
  312. ++ "\n"
  313. modSymDump = (List.foldl' (showModSymData) "" (Map.toList msyms))
  314. showModSymData s (name, decls) = s ++ ((showSDoc . ppr) name) ++ " -> [ " ++ (Fold.foldl showModDecls "" decls) ++ "]\n"
  315. showModDecls s d = s ++ (show d) ++ " "
  316. -- | Process each declaration as we receive it from a module's declaration's list.
  317. processDecl :: ModStateT -> IfaceDecl -> ModStateT
  318. -- Regular function or top level identifier.
  319. processDecl mState (IfaceId { ifName = name }) = addExportDecl mState name MIdDecl
  320. -- A 'data' declaration: insert it first, followed by its data type constructors
  321. processDecl mState sym@(IfaceData { ifName = name }) =
  322. let updMState = addExportDecl mState name (MTypeDecl sym)
  323. in addDataCons updMState (ifCons sym)
  324. -- A 'newtype' (synonym) declaration
  325. processDecl mState sym@(IfaceSyn { ifName = name }) = addExportDecl mState name (MTypeDecl sym)
  326. -- A 'class' declaration: insert the class name first, followed by its functions
  327. processDecl mState sym@(IfaceClass { ifName = name }) =
  328. let updMState = addExportDecl mState name (MClassDecl sym)
  329. in Fold.foldl' filterSig updMState (ifSigs sym)
  330. -- Ingore anything else...
  331. processDecl occMSymTuple (IfaceForeign _ _) = occMSymTuple
  332. -- | Capture declarations in which we're interested
  333. addExportDecl :: ModStateT -> OccName -> ModDecl -> ModStateT
  334. addExportDecl mstate name sym =
  335. let nameStr = mkRdrUnqual name
  336. eSet = exportSyms mstate
  337. msymMap = modSyms mstate
  338. symSeq = case Map.lookup nameStr msymMap of
  339. (Just msyms) -> Set.insert sym msyms
  340. Nothing -> Set.singleton sym
  341. in if Set.member name eSet
  342. then mstate {
  343. exportSyms = Set.delete name eSet
  344. , modSyms = Map.insert nameStr symSeq msymMap
  345. }
  346. else mstate
  347. addDataCons :: ModStateT -> IfaceConDecls -> ModStateT
  348. addDataCons mState IfAbstractTyCon = mState
  349. addDataCons mState IfOpenDataTyCon = mState
  350. addDataCons mState (IfDataTyCon conDecls) = Fold.foldl' filterCon mState conDecls
  351. addDataCons mState (IfNewTyCon newTyDecl) = filterCon mState newTyDecl
  352. filterCon :: ModStateT -> IfaceConDecl -> ModStateT
  353. filterCon mstate c@(IfCon { ifConOcc = name }) =
  354. let nameStr = mkRdrUnqual name
  355. eSet = exportSyms mstate
  356. msymMap = modSyms mstate
  357. conSym = MConDecl c
  358. symSeq = case Map.lookup nameStr msymMap of
  359. (Just msyms) -> Set.insert conSym msyms
  360. Nothing -> Set.singleton conSym
  361. in if Set.member name eSet
  362. then mstate {
  363. exportSyms = Set.delete name eSet
  364. , modSyms = Map.insert nameStr symSeq msymMap
  365. }
  366. else mstate
  367. filterSig :: ModStateT -> IfaceClassOp -> ModStateT
  368. filterSig mstate op@(IfaceClassOp name _ _) =
  369. let nameStr = mkRdrUnqual name
  370. msymMap = modSyms mstate
  371. eSet = exportSyms mstate
  372. sigSym = MClassOp op
  373. symSeq = case Map.lookup nameStr msymMap of
  374. (Just msyms) -> Set.insert sigSym msyms
  375. Nothing -> Set.singleton sigSym
  376. in if Set.member name eSet
  377. then mstate {
  378. exportSyms = Set.delete name eSet
  379. , modSyms = Map.insert nameStr symSeq msymMap
  380. }
  381. else mstate
  382. -- | Load an interface file
  383. getInterfaceFile :: Module
  384. -> ScionM (Maybe (ModIface, FilePath))
  385. getInterfaceFile m =
  386. let iface = findAndReadIface empty m False
  387. gblEnv = IfGblEnv { if_rec_types = Nothing }
  388. ifaceLoader hscEnv = liftIO $ initTcRnIf 'a' hscEnv gblEnv () iface
  389. returnIFace (Maybes.Succeeded mIface) = return (Just mIface)
  390. returnIFace _ = return Nothing
  391. in getSession >>= ifaceLoader >>= returnIFace
  392. -- | Fabricate a module name that can be easily detected as bogus. The main source
  393. -- of these "unknown" modules is the exception raised by 'modLookup' (below) when
  394. -- GHC can't figure out to whom the module belongs. Consequently, these modules are
  395. -- not candidates from which names are extracted.
  396. unknownModule :: ModuleName
  397. -> Module
  398. unknownModule = mkModule unknownPackageId
  399. -- | Update a module's type constructor cache. This function extracts the current typechecked module's
  400. -- type constructors and stashes the resulting completion tuples in the session's module cache. N.B.:
  401. -- we assume that the current typecheck completed successfully, although that particular case is
  402. -- handled by @extractHomeModuleTyCons@.
  403. updateHomeModuleTyCons :: Maybe BgTcCache
  404. -> ModuleCache
  405. -> ScionM ModuleCache
  406. updateHomeModuleTyCons tychk mCache =
  407. let mcd = case Map.lookup theMod mCache of
  408. (Just msyms) -> msyms
  409. Nothing -> emptyModCacheData
  410. theMod = case tychk of
  411. (Just (Typechecked tcm)) -> (getPMModule . tm_parsed_module) tcm
  412. (Just (Parsed pm)) -> getPMModule pm
  413. Nothing -> error "updateHomeModuleTyCons: no module for type check?"
  414. getPMModule pm = (ms_mod . pm_mod_summary) pm
  415. in return $ Map.insert theMod (mcd { tyCons = extractHomeModuleTyCons tychk }) mCache
  416. -- | Fix missing symbols in the Prelude because GHC treats these symbols differently.
  417. fixPrelude :: Module
  418. -> ModStateT
  419. -> ModStateT
  420. fixPrelude m mState
  421. | moduleName m == mkModuleName "Prelude"
  422. = (boolDecl . charDecl . floatDecl . doubleDecl . intDecl . seqDecl . errorDecl) mState
  423. | otherwise
  424. = mState
  425. where
  426. seqDecl origMState = addExportDecl origMState (mkVarOcc "seq") MIdDecl
  427. errorDecl origMState = addExportDecl origMState (mkVarOcc "error") MIdDecl
  428. boolDecl origMState =
  429. let updMState = addExportDecl origMState boolOccName (MTypeDecl (mkVanillaType "Bool"))
  430. in addDataCons updMState (IfDataTyCon [trueConDeclData, falseConDeclData])
  431. charDecl origMState = addExportDecl origMState (mkTcOcc "Char") (MTypeDecl (mkVanillaType "Char"))
  432. floatDecl origMState = addExportDecl origMState (mkTcOcc "Float") (MTypeDecl (mkVanillaType "Float"))
  433. doubleDecl origMState = addExportDecl origMState (mkTcOcc "Double") (MTypeDecl (mkVanillaType "Double"))
  434. intDecl origMState = addExportDecl origMState (mkTcOcc "Int") (MTypeDecl (mkVanillaType "Int"))
  435. boolOccName = mkTcOcc "Bool"
  436. trueConDeclData = mkVanillaCon "True"
  437. falseConDeclData = mkVanillaCon "False"
  438. mkVanillaType n = IfaceData {
  439. ifName = mkTcOcc n
  440. , ifTyVars = []
  441. , ifCtxt = []
  442. , ifCons = IfAbstractTyCon -- note: just a dummy, ignored value
  443. , ifRec = NonRecursive
  444. , ifGadtSyntax = False
  445. , ifGeneric = False
  446. , ifFamInst = Nothing
  447. }
  448. mkVanillaCon n = IfCon {
  449. ifConOcc = mkDataOcc n
  450. , ifConWrapper = False
  451. , ifConInfix = False
  452. , ifConUnivTvs = []
  453. , ifConExTvs = []
  454. , ifConEqSpec = []
  455. , ifConCtxt = []
  456. , ifConArgTys = []
  457. , ifConFields = []
  458. , ifConStricts = []
  459. }
  460. -- ["Bool","Char","Double","False","Float","Int","True","error","seq"]
  461. -- | Get the type names for the current source in the background typecheck cache,
  462. -- both local and imported from modules.
  463. extractHomeModuleTyCons :: Maybe BgTcCache -> CompletionTuples
  464. extractHomeModuleTyCons tychk = localTypes tychk
  465. where
  466. -- Types local to the current source
  467. localTypes (Just (Typechecked tcm)) = map ((formatInfo (getTcmModuleName tcm)) . unLoc) $ typeDecls tcm
  468. localTypes (Just (Parsed pm)) = map (formatInfo (getModuleName pm)) $ typeDeclsParsed pm
  469. localTypes Nothing = error "Bad pattern match in extractHomeModuleTyCons/localTypes"
  470. -- Output format is a tuple ("type","module")
  471. formatInfo modname ty = (formatTyDecl ty, modname)
  472. -- The stuff you have to go through just to get the module's name... :-)
  473. getTcmModuleName tcm = (getModuleName . tm_parsed_module) tcm
  474. getModuleName pm = (moduleNameString . moduleName . ms_mod . pm_mod_summary) pm
  475. -- Format a type declaration
  476. formatTyDecl :: (Outputable t) => TyClDecl t -> String
  477. formatTyDecl (TyFamily { tcdLName = name }) = formatTyName name
  478. formatTyDecl (TyData { tcdLName = name }) = formatTyName name
  479. formatTyDecl (TySynonym { tcdLName = name }) = formatTyName name
  480. formatTyDecl (ClassDecl { tcdLName = name }) = formatTyName name
  481. -- Theoretically, this is never matched
  482. formatTyDecl _ = error "Bad filtering in cmdTypeNames"
  483. -- Type name formattter
  484. formatTyName :: (Outputable e) => Located e -> String
  485. formatTyName = (showSDocUnqual . ppr . unLoc)