diff options
author | Duncan Coutts <duncan@well-typed.com> | 2014-08-29 14:00:57 +0100 |
---|---|---|
committer | Duncan Coutts <duncan@well-typed.com> | 2014-08-29 15:07:16 +0100 |
commit | 7efde4c1d6433eab349ab38ffa8540c21af3f796 (patch) | |
tree | 1a78e14649ce2df37f91388d099c20c123e23cad | |
parent | efb43758065f5311a51b12a6f8126c008aade5a7 (diff) | |
download | haskell-wip/cabal-head-updates.tar.gz |
Add extra ghc-pkg sanity check for module re-exports and duplicateswip/cabal-head-updates
For re-exports, check that the defining package exists and that it
exposes the defining module (or for self-rexport exposed or hidden
modules). Also check that the defining package is actually a direct
or indirect dependency of the package doing the re-exporting.
Also add a check for duplicate modules in a package, including
re-exported modules.
-rw-r--r-- | utils/ghc-pkg/Main.hs | 66 |
1 files changed, 62 insertions, 4 deletions
diff --git a/utils/ghc-pkg/Main.hs b/utils/ghc-pkg/Main.hs index 4d4f8e9c22..f063db4fdb 100644 --- a/utils/ghc-pkg/Main.hs +++ b/utils/ghc-pkg/Main.hs @@ -14,6 +14,7 @@ module Main (main) where import Version ( version, targetOS, targetARCH ) import qualified GHC.PackageDb as GhcPkg import qualified Distribution.Simple.PackageIndex as PackageIndex +import qualified Data.Graph as Graph import qualified Distribution.ModuleName as ModuleName import Distribution.ModuleName (ModuleName) import Distribution.InstalledPackageInfo as Cabal @@ -1519,7 +1520,9 @@ checkPackageConfig pkg verbosity db_stack auto_ghci_libs mapM_ (checkDir True "framework-dirs") (frameworkDirs pkg) mapM_ (checkFile True "haddock-interfaces") (haddockInterfaces pkg) mapM_ (checkDirURL True "haddock-html") (haddockHTMLs pkg) - checkModules pkg + checkDuplicateModules pkg + checkModuleFiles pkg + checkModuleReexports db_stack pkg mapM_ (checkHSLib verbosity (libraryDirs pkg) auto_ghci_libs) (hsLibraries pkg) -- ToDo: check these somehow? -- extra_libraries :: [String], @@ -1653,9 +1656,8 @@ doesFileExistOnPath filenames paths = go fullFilenames go ((p, fp) : xs) = do b <- doesFileExist fp if b then return (Just p) else go xs --- XXX maybe should check reexportedModules too -checkModules :: InstalledPackageInfo -> Validate () -checkModules pkg = do +checkModuleFiles :: InstalledPackageInfo -> Validate () +checkModuleFiles pkg = do mapM_ findModule (exposedModules pkg ++ hiddenModules pkg) where findModule modl = @@ -1667,6 +1669,62 @@ checkModules pkg = do when (isNothing m) $ verror ForceFiles ("cannot find any of " ++ show files) +checkDuplicateModules :: InstalledPackageInfo -> Validate () +checkDuplicateModules pkg + | null dups = return () + | otherwise = verror ForceAll ("package has duplicate modules: " ++ + unwords (map display dups)) + where + dups = [ m | (m:_:_) <- group (sort mods) ] + mods = exposedModules pkg ++ hiddenModules pkg + ++ map moduleReexportName (reexportedModules pkg) + +checkModuleReexports :: PackageDBStack -> InstalledPackageInfo -> Validate () +checkModuleReexports db_stack pkg = + mapM_ checkReexport (reexportedModules pkg) + where + all_pkgs = allPackagesInStack db_stack + ipix = PackageIndex.fromList all_pkgs + + checkReexport ModuleReexport { + moduleReexportDefiningPackage = definingPkgId, + moduleReexportDefiningName = definingModule + } = case PackageIndex.lookupInstalledPackageId ipix definingPkgId of + Nothing + -> verror ForceAll ("module re-export refers to a non-existant " ++ + "(or not visible) defining package: " ++ + display definingPkgId) + + Just definingPkg + | not (isIndirectDependency definingPkgId) + -> verror ForceAll ("module re-export refers to a defining " ++ + "package that is not a direct (or indirect) " ++ + "dependency of this package: " ++ + display definingPkgId) + + | definingPkgId == installedPackageId pkg + && definingModule `notElem` (exposedModules definingPkg + ++ hiddenModules definingPkg) + -> verror ForceAll ("module (self) re-export refers to a module " ++ + "that is not defined in this package " ++ + display definingModule) + + | definingPkgId /= installedPackageId pkg + && definingModule `notElem` exposedModules definingPkg + -> verror ForceAll ("module re-export refers to a module that is " ++ + "not exposed by the defining package " ++ + display definingModule) + + | otherwise + -> return () + + isIndirectDependency pkgid = fromMaybe False $ do + thispkg <- graphVertex (installedPackageId pkg) + otherpkg <- graphVertex pkgid + return (Graph.path depgraph thispkg otherpkg) + (depgraph, _, graphVertex) = PackageIndex.dependencyGraph ipix + + checkGHCiLib :: Verbosity -> String -> String -> String -> Bool -> IO () checkGHCiLib verbosity batch_lib_dir batch_lib_file lib auto_build | auto_build = autoBuildGHCiLib verbosity batch_lib_dir batch_lib_file ghci_lib_file |