aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Waern <david.waern@gmail.com>2010-08-26 20:31:58 +0000
committerDavid Waern <david.waern@gmail.com>2010-08-26 20:31:58 +0000
commit5a5c656c9817e1f0d83531cec4eeca38333519df (patch)
treea98396a5784e5e2717a3c380ab51facb858dcfb1
parenta127473902c8d833f15ad7fd83f29cc786827f14 (diff)
Follow recent API additions with some refactorings
Simon Hegel's patch prompted me to do some refactorings in Main, Haddock.Documentation and Haddock.Interface.
-rw-r--r--src/Documentation/Haddock.hs16
-rw-r--r--src/Haddock/Interface.hs126
-rw-r--r--src/Main.hs76
3 files changed, 120 insertions, 98 deletions
diff --git a/src/Documentation/Haddock.hs b/src/Documentation/Haddock.hs
index f277bf78..cfa1220d 100644
--- a/src/Documentation/Haddock.hs
+++ b/src/Documentation/Haddock.hs
@@ -17,7 +17,7 @@ module Documentation.Haddock (
Interface(..),
InstalledInterface(..),
createInterfaces,
- createInterfaces',
+ processModules,
-- * Export items & declarations
ExportItem(..),
@@ -63,3 +63,17 @@ import Haddock.Types
import Haddock.Options
import Haddock.Utils
import Main
+
+
+-- | Create 'Interface' structures from a given list of Haddock command-line
+-- flags and file or module names (as accepted by 'haddock' executable). Flags
+-- that control documentation generation or show help or version information
+-- are ignored.
+createInterfaces
+ :: [Flag] -- ^ A list of command-line flags
+ -> [String] -- ^ File or module names
+ -> IO [Interface] -- ^ Resulting list of interfaces
+createInterfaces flags modules = do
+ (_, ifaces, _) <- readPackagesAndProcessModules flags modules
+ return ifaces
+
diff --git a/src/Haddock/Interface.hs b/src/Haddock/Interface.hs
index b25ed4ec..fbc2a7d3 100644
--- a/src/Haddock/Interface.hs
+++ b/src/Haddock/Interface.hs
@@ -27,7 +27,7 @@
-- using this environment.
-----------------------------------------------------------------------------
module Haddock.Interface (
- createInterfaces
+ processModules
) where
@@ -54,26 +54,27 @@ import GHC hiding (verbosity, flags)
import HscTypes
--- | Create 'Interface' structures by typechecking the list of modules
--- using the GHC API and processing the resulting syntax trees.
-createInterfaces
- :: Verbosity -- ^ Verbosity of logging to 'stdout'
- -> [String] -- ^ A list of file or module names sorted by module topology
- -> [Flag] -- ^ Command-line flags
- -> [InterfaceFile] -- ^ Interface files of package dependencies
- -> Ghc ([Interface], LinkEnv)
- -- ^ Resulting list of interfaces and renaming environment
-createInterfaces verbosity modules flags extIfaces = do
+-- | Create 'Interface's and a link environment by typechecking the list of
+-- modules using the GHC API and processing the resulting syntax trees.
+processModules
+ :: Verbosity -- ^ Verbosity of logging to 'stdout'
+ -> [String] -- ^ A list of file or module names sorted by
+ -- module topology
+ -> [Flag] -- ^ Command-line flags
+ -> [InterfaceFile] -- ^ Interface files of package dependencies
+ -> Ghc ([Interface], LinkEnv) -- ^ Resulting list of interfaces and renaming
+ -- environment
+processModules verbosity modules flags extIfaces = do
out verbosity verbose "Creating interfaces..."
let instIfaceMap = Map.fromList [ (instMod iface, iface) | ext <- extIfaces
, iface <- ifInstalledIfaces ext ]
- interfaces <- createInterfaces' verbosity modules flags instIfaceMap
+ interfaces <- createIfaces0 verbosity modules flags instIfaceMap
out verbosity verbose "Attaching instances..."
interfaces' <- attachInstances interfaces instIfaceMap
- out verbosity verbose "Building link environment..."
+ out verbosity verbose "Building cross-linking environment..."
-- Combine the link envs of the external packages into one
let extLinks = Map.unions (map ifLinkEnv extIfaces)
homeLinks = buildHomeLinks interfaces -- Build the environment for the home
@@ -89,51 +90,58 @@ createInterfaces verbosity modules flags extIfaces = do
return (interfaces'', homeLinks)
-createInterfaces' :: Verbosity -> [String] -> [Flag] -> InstIfaceMap -> Ghc [Interface]
-createInterfaces' verbosity modules flags instIfaceMap = do
- let useTempDir = Flag_NoTmpCompDir `notElem` flags
+--------------------------------------------------------------------------------
+-- * Module typechecking and Interface creation
+--------------------------------------------------------------------------------
- -- Output dir needs to be set before calling depanal since it uses it to
+
+createIfaces0 :: Verbosity -> [String] -> [Flag] -> InstIfaceMap -> Ghc [Interface]
+createIfaces0 verbosity modules flags instIfaceMap =
+ -- Output dir needs to be set before calling depanal since depanal uses it to
-- compute output file names that are stored in the DynFlags of the
-- resulting ModSummaries.
- tmp <- liftIO getTemporaryDirectory
- x <- liftIO getProcessID
- let tempDir = tmp </> ".haddock-" ++ show x
- when useTempDir $ modifySessionDynFlags (setOutputDir tempDir)
-
- targets <- mapM (\f -> guessTarget f Nothing) modules
- setTargets targets
- -- Dependency analysis.
- modgraph <- depanal [] False
-
- -- If template haskell is used by the package, we can't use HscNothing as
- -- target since we might need to run code generated from one or more of the
- -- modules during typechecking.
- if needsTemplateHaskell modgraph
- then
- -- Create a temporary directory in wich to write compilation output,
- -- unless the user has asked us not to.
- (if useTempDir then withTempDir tempDir else id) $ do
- -- Turn on compilation.
- let enableComp d = d { hscTarget = defaultObjectTarget }
- modifySessionDynFlags enableComp
- -- We need to update the DynFlags of the ModSummaries as well.
- let upd m = m { ms_hspp_opts = enableComp (ms_hspp_opts m) }
- let modgraph' = map upd modgraph
-
- processModules verbosity flags instIfaceMap modgraph'
- else
- processModules verbosity flags instIfaceMap modgraph
+ (if useTempDir then withTempOutputDir else id) $ do
+ modGraph <- depAnalysis
+ if needsTemplateHaskell modGraph
+ then do
+ modGraph' <- enableCompilation modGraph
+ createIfaces verbosity flags instIfaceMap modGraph'
+ else
+ createIfaces verbosity flags instIfaceMap modGraph
+ where
+ useTempDir :: Bool
+ useTempDir = Flag_NoTmpCompDir `notElem` flags
-withTempDir :: (ExceptionMonad m, MonadIO m) => FilePath -> m a -> m a
-withTempDir dir = gbracket_ (liftIO $ createDirectory dir)
- (liftIO $ removeDirectoryRecursive dir)
+
+ withTempOutputDir :: Ghc a -> Ghc a
+ withTempOutputDir action = do
+ tmp <- liftIO getTemporaryDirectory
+ x <- liftIO getProcessID
+ let dir = tmp </> ".haddock-" ++ show x
+ modifySessionDynFlags (setOutputDir dir)
+ withTempDir dir action
+
+
+ depAnalysis :: Ghc ModuleGraph
+ depAnalysis = do
+ targets <- mapM (\f -> guessTarget f Nothing) modules
+ setTargets targets
+ depanal [] False
+
+
+ enableCompilation :: ModuleGraph -> Ghc ModuleGraph
+ enableCompilation modGraph = do
+ let enableComp d = d { hscTarget = defaultObjectTarget }
+ modifySessionDynFlags enableComp
+ -- We need to update the DynFlags of the ModSummaries as well.
+ let upd m = m { ms_hspp_opts = enableComp (ms_hspp_opts m) }
+ let modGraph' = map upd modGraph
+ return modGraph'
-processModules :: Verbosity -> [Flag] -> InstIfaceMap -> [ModSummary]
- -> Ghc [Interface]
-processModules verbosity flags instIfaceMap mods = do
+createIfaces :: Verbosity -> [Flag] -> InstIfaceMap -> ModuleGraph -> Ghc [Interface]
+createIfaces verbosity flags instIfaceMap mods = do
let sortedMods = flattenSCCs $ topSortModuleGraph False mods Nothing
(ifaces, _) <- foldM f ([], Map.empty) sortedMods
return (reverse ifaces)
@@ -200,6 +208,11 @@ mkGhcModule (mdl, file, checkedMod) dynflags = GhcModule {
(_, renamed, _, modInfo) = checkedMod
+--------------------------------------------------------------------------------
+-- * Building of cross-linking environment
+--------------------------------------------------------------------------------
+
+
-- | Build a mapping which for each original name, points to the "best"
-- place to link to in the documentation. For the definition of
-- "best", we use "the module nearest the bottom of the dependency
@@ -221,3 +234,14 @@ buildHomeLinks ifaces = foldl upd Map.empty (reverse ifaces)
mdl = ifaceMod iface
keep_old env n = Map.insertWith (\_ old -> old) n mdl env
keep_new env n = Map.insert n mdl env
+
+
+--------------------------------------------------------------------------------
+-- * Utils
+--------------------------------------------------------------------------------
+
+
+withTempDir :: (ExceptionMonad m, MonadIO m) => FilePath -> m a -> m a
+withTempDir dir = gbracket_ (liftIO $ createDirectory dir)
+ (liftIO $ removeDirectoryRecursive dir)
+
diff --git a/src/Main.hs b/src/Main.hs
index 5c0d0174..1192b1fb 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -15,7 +15,7 @@
--
-- Program entry point and top-level code.
-----------------------------------------------------------------------------
-module Main (main, createInterfaces') where
+module Main (main, readPackagesAndProcessModules) where
import Haddock.Backends.Xhtml
@@ -115,59 +115,22 @@ handleGhcExceptions =
-------------------------------------------------------------------------------
--- | Create 'Interface' structures from a given list of Haddock command-line
--- flags and file or module names (as accepted by 'haddock' executable). Flags
--- that control documentation generation or show help or version information
--- are ignored.
---
--- This is a more high-level alternative to 'createInterfaces'.
-createInterfaces'
- :: [String] -- ^ A list of command-line flags and file or module names
- -> IO [Interface] -- ^ Resulting list of interfaces
-createInterfaces' args = do
- (flags, fileArgs) <- parseHaddockOpts args
- (_, ifaces) <- readPackagesAndCreateInterfaces flags fileArgs
- return ifaces
-
-
-readPackagesAndCreateInterfaces :: [Flag] -> [String] -> IO ([(InterfaceFile, FilePath)], [Interface])
-readPackagesAndCreateInterfaces flags fileArgs = do
- libDir <- getGhcLibDir flags
-
- -- Catches all GHC source errors, then prints and re-throws them.
- let handleSrcErrors action' = flip handleSourceError action' $ \err -> do
- printExceptionAndWarnings err
- liftIO exitFailure
-
- -- Initialize GHC.
- withGhc libDir (ghcFlags flags) $ \_ -> handleSrcErrors $ do
-
- -- Get packages supplied with --read-interface.
- packages <- readInterfaceFiles nameCacheFromGhc (ifacePairs flags)
-
- -- Create the interfaces -- this is the core part of Haddock.
- (ifaces, homeLinks) <- createInterfaces (verbosity flags) fileArgs flags
- (map fst packages)
-
- -- Dump an "interface file" (.haddock file), if requested.
- liftIO $ case optDumpInterfaceFile flags of
- Just f -> dumpInterfaceFile f (map toInstalledIface ifaces) homeLinks
- Nothing -> return ()
-
- return (packages, ifaces)
-
-
main :: IO ()
main = handleTopExceptions $ do
-- Parse command-line flags and handle some of them initially.
args <- getArgs
- (flags, fileArgs) <- parseHaddockOpts args
+ (flags, files) <- parseHaddockOpts args
shortcutFlags flags
- if not (null fileArgs)
+ if not (null files)
then do
- (packages, ifaces) <- readPackagesAndCreateInterfaces flags fileArgs
+ (packages, ifaces, homeLinks) <- readPackagesAndProcessModules flags files
+
+ -- Dump an "interface file" (.haddock file), if requested.
+ case optDumpInterfaceFile flags of
+ Just f -> dumpInterfaceFile f (map toInstalledIface ifaces) homeLinks
+ Nothing -> return ()
-- Render the interfaces.
renderStep flags packages ifaces
@@ -183,6 +146,27 @@ main = handleTopExceptions $ do
renderStep flags packages []
+readPackagesAndProcessModules flags files = do
+ libDir <- getGhcLibDir flags
+
+ -- Catches all GHC source errors, then prints and re-throws them.
+ let handleSrcErrors action' = flip handleSourceError action' $ \err -> do
+ printExceptionAndWarnings err
+ liftIO exitFailure
+
+ -- Initialize GHC.
+ withGhc libDir (ghcFlags flags) $ \_ -> handleSrcErrors $ do
+
+ -- Get packages supplied with --read-interface.
+ packages <- readInterfaceFiles nameCacheFromGhc (ifacePairs flags)
+
+ -- Create the interfaces -- this is the core part of Haddock.
+ let ifaceFiles = map fst packages
+ (ifaces, homeLinks) <- processModules (verbosity flags) files flags ifaceFiles
+
+ return (packages, ifaces, homeLinks)
+
+
renderStep :: [Flag] -> [(InterfaceFile, FilePath)] -> [Interface] -> IO ()
renderStep flags packages interfaces = do
updateHTMLXRefs packages