diff options
| -rw-r--r-- | src/Main.hs | 58 | 
1 files changed, 38 insertions, 20 deletions
diff --git a/src/Main.hs b/src/Main.hs index 6ff83401..9dc9b912 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -29,6 +29,7 @@ import Data.Maybe            ( Maybe(..), isJust, isNothing, maybeToList,                                 listToMaybe, fromJust, catMaybes )  import Data.Word  import Data.Typeable +import Data.Graph hiding ( flattenSCC )  import System.Console.GetOpt ( getOpt, usageInfo, ArgOrder(..), OptDescr(..),                                  ArgDescr(..) )  import System.Environment    ( getArgs ) @@ -58,6 +59,7 @@ import TyCon  import PrelNames  import Bag  import Binary +import HscTypes  import FastString  #define FSLIT(x) (mkFastString# (x#)) @@ -1195,11 +1197,9 @@ type ErrMsgM a = Writer [ErrMsg] a  -- Packages   -------------------------------------------------------------------------------- -type PackageEnv = Map Name Name -  data PackageData = PackageData {    pdModules  :: [Module], -  pdDocEnv   :: PackageEnv, +  pdDocEnv   :: Map Name Name,    pdHtmlPath :: FilePath  } @@ -1217,8 +1217,15 @@ pkgId = mkPackageId . package  -- | Topologically sort a list of modules that belong to an external package,  -- using the dependency information available in the ModIface structure for   -- each module.  -sortPackageModules :: [Module] -> IO [Module] -sortPackageModules mods = return mods +sortPackageModules :: [ModuleInfo] -> [ModuleInfo] +sortPackageModules modinfos = flattenSCCs $ stronglyConnComp nodes +  where  +    nodes = map mkNode modinfos +      where +       mkNode modinfo = let iface = minf_iface modinfo +                            modNames = (map fst . dep_mods . mi_deps) iface +                            modName  = moduleName (mi_module iface) +                        in (modinfo, modName, modNames)  -- | For each module in the list, try to retrieve a ModuleInfo structure    moduleInfo :: Session -> [Module] -> IO (Maybe [ModuleInfo]) @@ -1248,31 +1255,40 @@ getIface pkgInfo = case haddockInterfaces pkgInfo of  getPackage :: Session -> InstalledPackageInfo -> IO PackageData   getPackage session pkgInfo = do    html <- getHtml pkgInfo - -  -- get a sorted list of the exposed modules      let modules = packageModules pkgInfo -  modules' <- sortPackageModules modules    -- try to get a ModuleInfo struct for each module -  mbModInfo <- moduleInfo session modules' -  modInfo <- case mbModInfo of  +  mbModInfos <- moduleInfo session modules +  modInfos <- case mbModInfos of       Just x -> return x      Nothing -> throwE "Could not get ModuleInfo for all exposed modules."  +  let modInfos' = sortPackageModules modInfos +    return $ PackageData { -    pdModules  = modules', -    pdDocEnv   = packageDocEnv modules' modInfo, +    pdModules  = map modInfoMod modInfos', +    pdDocEnv   = packageDocEnv modInfos',      pdHtmlPath = html    }   -- | Build a package doc env out of a topologically sorted list of modules -packageDocEnv :: [Module] -> [ModuleInfo] -> PackageEnv -packageDocEnv mods infos = Map.fromList $ concatMap moduleDocEnv (zip mods infos) +packageDocEnv :: [ModuleInfo] -> Map Name Name +packageDocEnv modInfos = foldl addModuleEnv Map.empty (reverse modInfos)    where -    moduleDocEnv (mod, modInfo)  -      | "GHC" `isPrefixOf` moduleString mod = [] -      | otherwise = [ (n, nameSetMod n mod) | n <- (modInfoExports modInfo) ] - +    addModuleEnv oldEnv thisMod  +      | "GHC" `isPrefixOf` modStr = oldEnv  +      | DocOptHide `elem` options = oldEnv +      | DocOptNotHome `elem` options = foldl' keepOld oldEnv visibleNames +      | otherwise = foldl' keepNew oldEnv visibleNames +      where  +        modStr = moduleNameString (modInfoName thisMod) +        options = mi_docopts $ minf_iface thisMod +        visibleNames = modInfoExports thisMod +        modName = modInfoMod thisMod +        keepOld env n = Map.insertWith (\new old -> old) n  +                        (nameSetMod n modName) env +        keepNew env n = Map.insert n (nameSetMod n modName) env +          -- | Try to create a PackageData for each package in the session except for   -- rts. Print a warning on stdout if a PackageData could not be created.  getPackages :: Session -> DynFlags -> [Flag] -> IO [PackageData] @@ -1300,6 +1316,8 @@ getPackages session dynflags flags = do            return Nothing          ) --- | Build one big doc env out of a list of packages -packagesDocEnv :: [PackageData] -> PackageEnv +-- | Build one big doc env out of a list of packages. If multiple packages  +-- export the same (original) name, we just pick one of the packages as the  +-- documentation site. +packagesDocEnv :: [PackageData] -> Map Name Name  packagesDocEnv packages = Map.unions (map pdDocEnv packages)  | 
