- mv_map1, mv_map2 :: FiniteMap ModuleName (WhatsImported Name)
-
- -- mv_map1 records all the modules that have a "module M"
- -- in this module's export list with an "Everything"
- mv_map1 = foldr add_mod emptyFM export_mods
-
- -- mv_map2 adds the version numbers of things exported individually
- mv_map2 = foldr add_mv mv_map1 imp_names
-
- -- Build the result list by adding info for each module,
- -- *omitting* (a) library modules
- -- (b) source-imported modules
- mk_version_info mod_name (version, has_orphans, cts) so_far
- | omit cts = so_far -- Don't record usage info for this module
- | otherwise = (mod_name, version, has_orphans, whats_imported) : so_far
- where
- whats_imported = case lookupFM mv_map2 mod_name of
- Just wi -> wi
- Nothing -> Specifically []
-
- omit (Just (mod, boot_import, _)) = isLibModule mod || boot_import
- omit Nothing = False
+ mv_map :: FiniteMap ModuleName [(OccName,Version)]
+ mv_map = foldr add_mv emptyFM imp_names
+
+ add_mv (name, version) mv_map = addItem mv_map (moduleName (nameModule name))
+ (nameOccName name, version)
+
+ -- Build the result list by adding info for each module.
+ -- For (a) a library module, we don't record it at all unless it contains orphans
+ -- (We must never lose track of orphans.)
+ --
+ -- (b) a source-imported module, don't record the dependency at all
+ --
+ -- (b) may seem a bit strange. The idea is that the usages in a .hi file records
+ -- *all* the module's dependencies other than the loop-breakers. We use
+ -- this info in findAndReadInterface to decide whether to look for a .hi file or
+ -- a .hi-boot file.
+ --
+ -- This means we won't track version changes, or orphans, from .hi-boot files.
+ -- The former is potentially rather bad news. It could be fixed by recording
+ -- whether something is a boot file along with the usage info for it, but
+ -- I can't be bothered just now.
+
+ mk_imp_info mod_name (has_orphans, is_boot, contents) so_far
+ | mod_name == this_mod -- Check if M appears in the set of modules 'below' M
+ -- This seems like a convenient place to check
+ = WARN( not is_boot, ptext SLIT("Wierd:") <+> ppr this_mod <+>
+ ptext SLIT("imports itself (perhaps indirectly)") )
+ so_far
+
+ | otherwise
+ = let
+ go_for_it exports = (mod_name, has_orphans, is_boot, exports)
+ : so_far
+ in
+ case contents of
+ Nothing -> -- We didn't even open the interface
+ -- This happens when a module, Foo, that we explicitly imported has
+ -- 'import Baz' in its interface file, recording that Baz is below
+ -- Foo in the module dependency hierarchy. We want to propagate this
+ -- information. The Nothing says that we didn't even open the interface
+ -- file but we must still propagate the dependeny info.
+ -- The module in question must be a local module (in the same package)
+ go_for_it NothingAtAll
+
+ Just (mod, mod_vers, fix_vers, rule_vers, how_imported, _)
+ | is_sys_import && is_lib_module && not has_orphans
+ -> so_far
+
+ | is_lib_module -- Record the module but not detailed
+ || mod_name `elem` export_all_mods -- version information for the imports
+ -> go_for_it (Everything mod_vers)
+
+ | otherwise
+ -> case lookupFM mv_map mod_name of
+ Just whats_imported -> go_for_it (Specifically mod_vers fix_vers rule_vers
+ (sortImport whats_imported))
+ Nothing -> go_for_it NothingAtAll
+ -- This happens if you have
+ -- import Foo
+ -- but don't actually *use* anything from Foo
+ -- In which case record an empty dependency list
+ where
+ is_lib_module = not (isLocalModule mod)
+ is_sys_import = case how_imported of
+ ImportBySystem -> True
+ other -> False
+
+
+ import_info = foldFM mk_imp_info [] mod_map
+
+ -- Sort exports into groups by module
+ export_fm :: FiniteMap ModuleName [RdrAvailInfo]
+ export_fm = foldr insert emptyFM export_avails
+
+ insert avail efm = addItem efm (moduleName (nameModule (availName avail)))
+ (rdrAvailInfo avail)
+
+ export_info = [(m, sortExport as) | (m,as) <- fmToList export_fm]