PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/compiler/main/Finder.lhs

https://bitbucket.org/carter/ghc
Haskell | 645 lines | 433 code | 106 blank | 106 comment | 20 complexity | 9350f2f3e3d207c70b253e8c00ea79bd MD5 | raw file
  1. %
  2. % (c) The University of Glasgow, 2000-2006
  3. %
  4. \section[Finder]{Module Finder}
  5. \begin{code}
  6. module Finder (
  7. flushFinderCaches,
  8. FindResult(..),
  9. findImportedModule,
  10. findExactModule,
  11. findHomeModule,
  12. findExposedPackageModule,
  13. mkHomeModLocation,
  14. mkHomeModLocation2,
  15. mkHiOnlyModLocation,
  16. addHomeModuleToFinder,
  17. uncacheModule,
  18. mkStubPaths,
  19. findObjectLinkableMaybe,
  20. findObjectLinkable,
  21. cannotFindModule,
  22. cannotFindInterface,
  23. ) where
  24. #include "HsVersions.h"
  25. import Module
  26. import HscTypes
  27. import Packages
  28. import FastString
  29. import Util
  30. import PrelNames ( gHC_PRIM )
  31. import DynFlags
  32. import Outputable
  33. import UniqFM
  34. import Maybes ( expectJust )
  35. import Exception ( evaluate )
  36. import Distribution.Text
  37. import Distribution.Package hiding (PackageId)
  38. import Data.IORef ( IORef, writeIORef, readIORef, atomicModifyIORef )
  39. import System.Directory
  40. import System.FilePath
  41. import Control.Monad
  42. import Data.List ( partition )
  43. import Data.Time
  44. type FileExt = String -- Filename extension
  45. type BaseName = String -- Basename of file
  46. -- -----------------------------------------------------------------------------
  47. -- The Finder
  48. -- The Finder provides a thin filesystem abstraction to the rest of
  49. -- the compiler. For a given module, it can tell you where the
  50. -- source, interface, and object files for that module live.
  51. -- It does *not* know which particular package a module lives in. Use
  52. -- Packages.lookupModuleInAllPackages for that.
  53. -- -----------------------------------------------------------------------------
  54. -- The finder's cache
  55. -- remove all the home modules from the cache; package modules are
  56. -- assumed to not move around during a session.
  57. flushFinderCaches :: HscEnv -> IO ()
  58. flushFinderCaches hsc_env = do
  59. -- Ideally the update to both caches be a single atomic operation.
  60. writeIORef fc_ref emptyUFM
  61. flushModLocationCache this_pkg mlc_ref
  62. where
  63. this_pkg = thisPackage (hsc_dflags hsc_env)
  64. fc_ref = hsc_FC hsc_env
  65. mlc_ref = hsc_MLC hsc_env
  66. flushModLocationCache :: PackageId -> IORef ModLocationCache -> IO ()
  67. flushModLocationCache this_pkg ref = do
  68. atomicModifyIORef ref $ \fm -> (filterModuleEnv is_ext fm, ())
  69. _ <- evaluate =<< readIORef ref
  70. return ()
  71. where is_ext mod _ | modulePackageId mod /= this_pkg = True
  72. | otherwise = False
  73. addToFinderCache :: IORef FinderCache -> ModuleName -> FindResult -> IO ()
  74. addToFinderCache ref key val =
  75. atomicModifyIORef ref $ \c -> (addToUFM c key val, ())
  76. addToModLocationCache :: IORef ModLocationCache -> Module -> ModLocation -> IO ()
  77. addToModLocationCache ref key val =
  78. atomicModifyIORef ref $ \c -> (extendModuleEnv c key val, ())
  79. removeFromFinderCache :: IORef FinderCache -> ModuleName -> IO ()
  80. removeFromFinderCache ref key =
  81. atomicModifyIORef ref $ \c -> (delFromUFM c key, ())
  82. removeFromModLocationCache :: IORef ModLocationCache -> Module -> IO ()
  83. removeFromModLocationCache ref key =
  84. atomicModifyIORef ref $ \c -> (delModuleEnv c key, ())
  85. lookupFinderCache :: IORef FinderCache -> ModuleName -> IO (Maybe FindResult)
  86. lookupFinderCache ref key = do
  87. c <- readIORef ref
  88. return $! lookupUFM c key
  89. lookupModLocationCache :: IORef ModLocationCache -> Module
  90. -> IO (Maybe ModLocation)
  91. lookupModLocationCache ref key = do
  92. c <- readIORef ref
  93. return $! lookupModuleEnv c key
  94. -- -----------------------------------------------------------------------------
  95. -- The two external entry points
  96. -- | Locate a module that was imported by the user. We have the
  97. -- module's name, and possibly a package name. Without a package
  98. -- name, this function will use the search path and the known exposed
  99. -- packages to find the module, if a package is specified then only
  100. -- that package is searched for the module.
  101. findImportedModule :: HscEnv -> ModuleName -> Maybe FastString -> IO FindResult
  102. findImportedModule hsc_env mod_name mb_pkg =
  103. case mb_pkg of
  104. Nothing -> unqual_import
  105. Just pkg | pkg == fsLit "this" -> home_import -- "this" is special
  106. | otherwise -> pkg_import
  107. where
  108. home_import = findHomeModule hsc_env mod_name
  109. pkg_import = findExposedPackageModule hsc_env mod_name mb_pkg
  110. unqual_import = home_import
  111. `orIfNotFound`
  112. findExposedPackageModule hsc_env mod_name Nothing
  113. -- | Locate a specific 'Module'. The purpose of this function is to
  114. -- create a 'ModLocation' for a given 'Module', that is to find out
  115. -- where the files associated with this module live. It is used when
  116. -- reading the interface for a module mentioned by another interface,
  117. -- for example (a "system import").
  118. findExactModule :: HscEnv -> Module -> IO FindResult
  119. findExactModule hsc_env mod =
  120. let dflags = hsc_dflags hsc_env
  121. in if modulePackageId mod == thisPackage dflags
  122. then findHomeModule hsc_env (moduleName mod)
  123. else findPackageModule hsc_env mod
  124. -- -----------------------------------------------------------------------------
  125. -- Helpers
  126. orIfNotFound :: IO FindResult -> IO FindResult -> IO FindResult
  127. orIfNotFound this or_this = do
  128. res <- this
  129. case res of
  130. NotFound { fr_paths = paths1, fr_mods_hidden = mh1
  131. , fr_pkgs_hidden = ph1, fr_suggestions = s1 }
  132. -> do res2 <- or_this
  133. case res2 of
  134. NotFound { fr_paths = paths2, fr_pkg = mb_pkg2, fr_mods_hidden = mh2
  135. , fr_pkgs_hidden = ph2, fr_suggestions = s2 }
  136. -> return (NotFound { fr_paths = paths1 ++ paths2
  137. , fr_pkg = mb_pkg2 -- snd arg is the package search
  138. , fr_mods_hidden = mh1 ++ mh2
  139. , fr_pkgs_hidden = ph1 ++ ph2
  140. , fr_suggestions = s1 ++ s2 })
  141. _other -> return res2
  142. _other -> return res
  143. homeSearchCache :: HscEnv -> ModuleName -> IO FindResult -> IO FindResult
  144. homeSearchCache hsc_env mod_name do_this = do
  145. m <- lookupFinderCache (hsc_FC hsc_env) mod_name
  146. case m of
  147. Just result -> return result
  148. Nothing -> do
  149. result <- do_this
  150. addToFinderCache (hsc_FC hsc_env) mod_name result
  151. case result of
  152. Found loc mod -> addToModLocationCache (hsc_MLC hsc_env) mod loc
  153. _other -> return ()
  154. return result
  155. findExposedPackageModule :: HscEnv -> ModuleName -> Maybe FastString
  156. -> IO FindResult
  157. findExposedPackageModule hsc_env mod_name mb_pkg
  158. -- not found in any package:
  159. = case lookupModuleWithSuggestions (hsc_dflags hsc_env) mod_name of
  160. Left suggest -> return (NotFound { fr_paths = [], fr_pkg = Nothing
  161. , fr_pkgs_hidden = [], fr_mods_hidden = []
  162. , fr_suggestions = suggest })
  163. Right found
  164. | null found_exposed -- Found, but with no exposed copies
  165. -> return (NotFound { fr_paths = [], fr_pkg = Nothing
  166. , fr_pkgs_hidden = pkg_hiddens, fr_mods_hidden = mod_hiddens
  167. , fr_suggestions = [] })
  168. | [(pkg_conf,_)] <- found_exposed -- Found uniquely
  169. -> let pkgid = packageConfigId pkg_conf in
  170. findPackageModule_ hsc_env (mkModule pkgid mod_name) pkg_conf
  171. | otherwise -- Found in more than one place
  172. -> return (FoundMultiple (map (packageConfigId.fst) found_exposed))
  173. where
  174. for_this_pkg = case mb_pkg of
  175. Nothing -> found
  176. Just p -> filter ((`matches` p) . fst) found
  177. found_exposed = filter is_exposed for_this_pkg
  178. is_exposed (pkg_conf,exposed_mod) = exposed pkg_conf && exposed_mod
  179. mod_hiddens = [ packageConfigId pkg_conf
  180. | (pkg_conf,False) <- found ]
  181. pkg_hiddens = [ packageConfigId pkg_conf
  182. | (pkg_conf,_) <- found, not (exposed pkg_conf) ]
  183. pkg_conf `matches` pkg
  184. = case packageName pkg_conf of
  185. PackageName n -> pkg == mkFastString n
  186. modLocationCache :: HscEnv -> Module -> IO FindResult -> IO FindResult
  187. modLocationCache hsc_env mod do_this = do
  188. mb_loc <- lookupModLocationCache mlc mod
  189. case mb_loc of
  190. Just loc -> return (Found loc mod)
  191. Nothing -> do
  192. result <- do_this
  193. case result of
  194. Found loc mod -> addToModLocationCache (hsc_MLC hsc_env) mod loc
  195. _other -> return ()
  196. return result
  197. where
  198. mlc = hsc_MLC hsc_env
  199. addHomeModuleToFinder :: HscEnv -> ModuleName -> ModLocation -> IO Module
  200. addHomeModuleToFinder hsc_env mod_name loc = do
  201. let mod = mkModule (thisPackage (hsc_dflags hsc_env)) mod_name
  202. addToFinderCache (hsc_FC hsc_env) mod_name (Found loc mod)
  203. addToModLocationCache (hsc_MLC hsc_env) mod loc
  204. return mod
  205. uncacheModule :: HscEnv -> ModuleName -> IO ()
  206. uncacheModule hsc_env mod = do
  207. let this_pkg = thisPackage (hsc_dflags hsc_env)
  208. removeFromFinderCache (hsc_FC hsc_env) mod
  209. removeFromModLocationCache (hsc_MLC hsc_env) (mkModule this_pkg mod)
  210. -- -----------------------------------------------------------------------------
  211. -- The internal workers
  212. -- | Search for a module in the home package only.
  213. findHomeModule :: HscEnv -> ModuleName -> IO FindResult
  214. findHomeModule hsc_env mod_name =
  215. homeSearchCache hsc_env mod_name $
  216. let
  217. dflags = hsc_dflags hsc_env
  218. home_path = importPaths dflags
  219. hisuf = hiSuf dflags
  220. mod = mkModule (thisPackage dflags) mod_name
  221. source_exts =
  222. [ ("hs", mkHomeModLocationSearched dflags mod_name "hs")
  223. , ("lhs", mkHomeModLocationSearched dflags mod_name "lhs")
  224. ]
  225. hi_exts = [ (hisuf, mkHiOnlyModLocation dflags hisuf)
  226. , (addBootSuffix hisuf, mkHiOnlyModLocation dflags hisuf)
  227. ]
  228. -- In compilation manager modes, we look for source files in the home
  229. -- package because we can compile these automatically. In one-shot
  230. -- compilation mode we look for .hi and .hi-boot files only.
  231. exts | isOneShot (ghcMode dflags) = hi_exts
  232. | otherwise = source_exts
  233. in
  234. -- special case for GHC.Prim; we won't find it in the filesystem.
  235. -- This is important only when compiling the base package (where GHC.Prim
  236. -- is a home module).
  237. if mod == gHC_PRIM
  238. then return (Found (error "GHC.Prim ModLocation") mod)
  239. else searchPathExts home_path mod exts
  240. -- | Search for a module in external packages only.
  241. findPackageModule :: HscEnv -> Module -> IO FindResult
  242. findPackageModule hsc_env mod = do
  243. let
  244. dflags = hsc_dflags hsc_env
  245. pkg_id = modulePackageId mod
  246. pkg_map = pkgIdMap (pkgState dflags)
  247. --
  248. case lookupPackage pkg_map pkg_id of
  249. Nothing -> return (NoPackage pkg_id)
  250. Just pkg_conf -> findPackageModule_ hsc_env mod pkg_conf
  251. findPackageModule_ :: HscEnv -> Module -> PackageConfig -> IO FindResult
  252. findPackageModule_ hsc_env mod pkg_conf =
  253. modLocationCache hsc_env mod $
  254. -- special case for GHC.Prim; we won't find it in the filesystem.
  255. if mod == gHC_PRIM
  256. then return (Found (error "GHC.Prim ModLocation") mod)
  257. else
  258. let
  259. dflags = hsc_dflags hsc_env
  260. tag = buildTag dflags
  261. -- hi-suffix for packages depends on the build tag.
  262. package_hisuf | null tag = "hi"
  263. | otherwise = tag ++ "_hi"
  264. mk_hi_loc = mkHiOnlyModLocation dflags package_hisuf
  265. import_dirs = importDirs pkg_conf
  266. -- we never look for a .hi-boot file in an external package;
  267. -- .hi-boot files only make sense for the home package.
  268. in
  269. case import_dirs of
  270. [one] | MkDepend <- ghcMode dflags -> do
  271. -- there's only one place that this .hi file can be, so
  272. -- don't bother looking for it.
  273. let basename = moduleNameSlashes (moduleName mod)
  274. loc <- mk_hi_loc one basename
  275. return (Found loc mod)
  276. _otherwise ->
  277. searchPathExts import_dirs mod [(package_hisuf, mk_hi_loc)]
  278. -- -----------------------------------------------------------------------------
  279. -- General path searching
  280. searchPathExts
  281. :: [FilePath] -- paths to search
  282. -> Module -- module name
  283. -> [ (
  284. FileExt, -- suffix
  285. FilePath -> BaseName -> IO ModLocation -- action
  286. )
  287. ]
  288. -> IO FindResult
  289. searchPathExts paths mod exts
  290. = do result <- search to_search
  291. {-
  292. hPutStrLn stderr (showSDoc $
  293. vcat [text "Search" <+> ppr mod <+> sep (map (text. fst) exts)
  294. , nest 2 (vcat (map text paths))
  295. , case result of
  296. Succeeded (loc, p) -> text "Found" <+> ppr loc
  297. Failed fs -> text "not found"])
  298. -}
  299. return result
  300. where
  301. basename = moduleNameSlashes (moduleName mod)
  302. to_search :: [(FilePath, IO ModLocation)]
  303. to_search = [ (file, fn path basename)
  304. | path <- paths,
  305. (ext,fn) <- exts,
  306. let base | path == "." = basename
  307. | otherwise = path </> basename
  308. file = base <.> ext
  309. ]
  310. search [] = return (NotFound { fr_paths = map fst to_search
  311. , fr_pkg = Just (modulePackageId mod)
  312. , fr_mods_hidden = [], fr_pkgs_hidden = []
  313. , fr_suggestions = [] })
  314. search ((file, mk_result) : rest) = do
  315. b <- doesFileExist file
  316. if b
  317. then do { loc <- mk_result; return (Found loc mod) }
  318. else search rest
  319. mkHomeModLocationSearched :: DynFlags -> ModuleName -> FileExt
  320. -> FilePath -> BaseName -> IO ModLocation
  321. mkHomeModLocationSearched dflags mod suff path basename = do
  322. mkHomeModLocation2 dflags mod (path </> basename) suff
  323. -- -----------------------------------------------------------------------------
  324. -- Constructing a home module location
  325. -- This is where we construct the ModLocation for a module in the home
  326. -- package, for which we have a source file. It is called from three
  327. -- places:
  328. --
  329. -- (a) Here in the finder, when we are searching for a module to import,
  330. -- using the search path (-i option).
  331. --
  332. -- (b) The compilation manager, when constructing the ModLocation for
  333. -- a "root" module (a source file named explicitly on the command line
  334. -- or in a :load command in GHCi).
  335. --
  336. -- (c) The driver in one-shot mode, when we need to construct a
  337. -- ModLocation for a source file named on the command-line.
  338. --
  339. -- Parameters are:
  340. --
  341. -- mod
  342. -- The name of the module
  343. --
  344. -- path
  345. -- (a): The search path component where the source file was found.
  346. -- (b) and (c): "."
  347. --
  348. -- src_basename
  349. -- (a): (moduleNameSlashes mod)
  350. -- (b) and (c): The filename of the source file, minus its extension
  351. --
  352. -- ext
  353. -- The filename extension of the source file (usually "hs" or "lhs").
  354. mkHomeModLocation :: DynFlags -> ModuleName -> FilePath -> IO ModLocation
  355. mkHomeModLocation dflags mod src_filename = do
  356. let (basename,extension) = splitExtension src_filename
  357. mkHomeModLocation2 dflags mod basename extension
  358. mkHomeModLocation2 :: DynFlags
  359. -> ModuleName
  360. -> FilePath -- Of source module, without suffix
  361. -> String -- Suffix
  362. -> IO ModLocation
  363. mkHomeModLocation2 dflags mod src_basename ext = do
  364. let mod_basename = moduleNameSlashes mod
  365. obj_fn <- mkObjPath dflags src_basename mod_basename
  366. hi_fn <- mkHiPath dflags src_basename mod_basename
  367. return (ModLocation{ ml_hs_file = Just (src_basename <.> ext),
  368. ml_hi_file = hi_fn,
  369. ml_obj_file = obj_fn })
  370. mkHiOnlyModLocation :: DynFlags -> Suffix -> FilePath -> String
  371. -> IO ModLocation
  372. mkHiOnlyModLocation dflags hisuf path basename
  373. = do let full_basename = path </> basename
  374. obj_fn <- mkObjPath dflags full_basename basename
  375. return ModLocation{ ml_hs_file = Nothing,
  376. ml_hi_file = full_basename <.> hisuf,
  377. -- Remove the .hi-boot suffix from
  378. -- hi_file, if it had one. We always
  379. -- want the name of the real .hi file
  380. -- in the ml_hi_file field.
  381. ml_obj_file = obj_fn
  382. }
  383. -- | Constructs the filename of a .o file for a given source file.
  384. -- Does /not/ check whether the .o file exists
  385. mkObjPath
  386. :: DynFlags
  387. -> FilePath -- the filename of the source file, minus the extension
  388. -> String -- the module name with dots replaced by slashes
  389. -> IO FilePath
  390. mkObjPath dflags basename mod_basename
  391. = do let
  392. odir = objectDir dflags
  393. osuf = objectSuf dflags
  394. obj_basename | Just dir <- odir = dir </> mod_basename
  395. | otherwise = basename
  396. return (obj_basename <.> osuf)
  397. -- | Constructs the filename of a .hi file for a given source file.
  398. -- Does /not/ check whether the .hi file exists
  399. mkHiPath
  400. :: DynFlags
  401. -> FilePath -- the filename of the source file, minus the extension
  402. -> String -- the module name with dots replaced by slashes
  403. -> IO FilePath
  404. mkHiPath dflags basename mod_basename
  405. = do let
  406. hidir = hiDir dflags
  407. hisuf = hiSuf dflags
  408. hi_basename | Just dir <- hidir = dir </> mod_basename
  409. | otherwise = basename
  410. return (hi_basename <.> hisuf)
  411. -- -----------------------------------------------------------------------------
  412. -- Filenames of the stub files
  413. -- We don't have to store these in ModLocations, because they can be derived
  414. -- from other available information, and they're only rarely needed.
  415. mkStubPaths
  416. :: DynFlags
  417. -> ModuleName
  418. -> ModLocation
  419. -> FilePath
  420. mkStubPaths dflags mod location
  421. = let
  422. stubdir = stubDir dflags
  423. mod_basename = moduleNameSlashes mod
  424. src_basename = dropExtension $ expectJust "mkStubPaths"
  425. (ml_hs_file location)
  426. stub_basename0
  427. | Just dir <- stubdir = dir </> mod_basename
  428. | otherwise = src_basename
  429. stub_basename = stub_basename0 ++ "_stub"
  430. in
  431. stub_basename <.> "h"
  432. -- -----------------------------------------------------------------------------
  433. -- findLinkable isn't related to the other stuff in here,
  434. -- but there's no other obvious place for it
  435. findObjectLinkableMaybe :: Module -> ModLocation -> IO (Maybe Linkable)
  436. findObjectLinkableMaybe mod locn
  437. = do let obj_fn = ml_obj_file locn
  438. maybe_obj_time <- modificationTimeIfExists obj_fn
  439. case maybe_obj_time of
  440. Nothing -> return Nothing
  441. Just obj_time -> liftM Just (findObjectLinkable mod obj_fn obj_time)
  442. -- Make an object linkable when we know the object file exists, and we know
  443. -- its modification time.
  444. findObjectLinkable :: Module -> FilePath -> UTCTime -> IO Linkable
  445. findObjectLinkable mod obj_fn obj_time = return (LM obj_time mod [DotO obj_fn])
  446. -- We used to look for _stub.o files here, but that was a bug (#706)
  447. -- Now GHC merges the stub.o into the main .o (#3687)
  448. -- -----------------------------------------------------------------------------
  449. -- Error messages
  450. cannotFindModule :: DynFlags -> ModuleName -> FindResult -> SDoc
  451. cannotFindModule = cantFindErr (sLit "Could not find module")
  452. (sLit "Ambiguous module name")
  453. cannotFindInterface :: DynFlags -> ModuleName -> FindResult -> SDoc
  454. cannotFindInterface = cantFindErr (sLit "Failed to load interface for")
  455. (sLit "Ambiguous interface for")
  456. cantFindErr :: LitString -> LitString -> DynFlags -> ModuleName -> FindResult
  457. -> SDoc
  458. cantFindErr _ multiple_found _ mod_name (FoundMultiple pkgs)
  459. = hang (ptext multiple_found <+> quotes (ppr mod_name) <> colon) 2 (
  460. sep [ptext (sLit "it was found in multiple packages:"),
  461. hsep (map (text.packageIdString) pkgs)]
  462. )
  463. cantFindErr cannot_find _ dflags mod_name find_result
  464. = ptext cannot_find <+> quotes (ppr mod_name)
  465. $$ more_info
  466. where
  467. pkg_map :: PackageConfigMap
  468. pkg_map = pkgIdMap (pkgState dflags)
  469. more_info
  470. = case find_result of
  471. NoPackage pkg
  472. -> ptext (sLit "no package matching") <+> quotes (ppr pkg) <+>
  473. ptext (sLit "was found")
  474. NotFound { fr_paths = files, fr_pkg = mb_pkg
  475. , fr_mods_hidden = mod_hiddens, fr_pkgs_hidden = pkg_hiddens
  476. , fr_suggestions = suggest }
  477. | Just pkg <- mb_pkg, pkg /= thisPackage dflags
  478. -> not_found_in_package pkg files
  479. | not (null suggest)
  480. -> pp_suggestions suggest $$ tried_these files
  481. | null files && null mod_hiddens && null pkg_hiddens
  482. -> ptext (sLit "It is not a module in the current program, or in any known package.")
  483. | otherwise
  484. -> vcat (map pkg_hidden pkg_hiddens) $$
  485. vcat (map mod_hidden mod_hiddens) $$
  486. tried_these files
  487. _ -> panic "cantFindErr"
  488. build_tag = buildTag dflags
  489. not_found_in_package pkg files
  490. | build_tag /= ""
  491. = let
  492. build = if build_tag == "p" then "profiling"
  493. else "\"" ++ build_tag ++ "\""
  494. in
  495. ptext (sLit "Perhaps you haven't installed the ") <> text build <>
  496. ptext (sLit " libraries for package ") <> quotes (ppr pkg) <> char '?' $$
  497. tried_these files
  498. | otherwise
  499. = ptext (sLit "There are files missing in the ") <> quotes (ppr pkg) <>
  500. ptext (sLit " package,") $$
  501. ptext (sLit "try running 'ghc-pkg check'.") $$
  502. tried_these files
  503. tried_these files
  504. | null files = empty
  505. | verbosity dflags < 3 =
  506. ptext (sLit "Use -v to see a list of the files searched for.")
  507. | otherwise =
  508. hang (ptext (sLit "Locations searched:")) 2 $ vcat (map text files)
  509. pkg_hidden pkg =
  510. ptext (sLit "It is a member of the hidden package") <+> quotes (ppr pkg)
  511. <> dot $$ cabal_pkg_hidden_hint pkg
  512. cabal_pkg_hidden_hint pkg
  513. | dopt Opt_BuildingCabalPackage dflags
  514. = case simpleParse (packageIdString pkg) of
  515. Just pid ->
  516. ptext (sLit "Perhaps you need to add") <+>
  517. quotes (text (display (pkgName pid))) <+>
  518. ptext (sLit "to the build-depends in your .cabal file.")
  519. Nothing -> empty
  520. | otherwise = empty
  521. mod_hidden pkg =
  522. ptext (sLit "it is a hidden module in the package") <+> quotes (ppr pkg)
  523. pp_suggestions :: [Module] -> SDoc
  524. pp_suggestions sugs
  525. | null sugs = empty
  526. | otherwise = hang (ptext (sLit "Perhaps you meant"))
  527. 2 (vcat [ vcat (map pp_exp exposed_sugs)
  528. , vcat (map pp_hid hidden_sugs) ])
  529. where
  530. (exposed_sugs, hidden_sugs) = partition from_exposed_pkg sugs
  531. from_exposed_pkg m = case lookupPackage pkg_map (modulePackageId m) of
  532. Just pkg_config -> exposed pkg_config
  533. Nothing -> WARN( True, ppr m ) -- Should not happen
  534. False
  535. pp_exp mod = ppr (moduleName mod)
  536. <+> parens (ptext (sLit "from") <+> ppr (modulePackageId mod))
  537. pp_hid mod = ppr (moduleName mod)
  538. <+> parens (ptext (sLit "needs flag -package") <+> ppr (modulePackageId mod))
  539. \end{code}