aboutsummaryrefslogtreecommitdiff
path: root/src/Main.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Main.hs')
-rw-r--r--src/Main.hs267
1 files changed, 246 insertions, 21 deletions
diff --git a/src/Main.hs b/src/Main.hs
index b2ea7709..dfc5ee99 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -7,24 +7,19 @@
module Main (main) where
-import Binary
-import Digraph
---import HaddockDB -- not compiling
+import HsSyn2
import HaddockHtml
import HaddockHoogle
-import HaddockLex
-import HaddockParse
import HaddockRename
import HaddockTypes
import HaddockUtil
import HaddockVersion
-import HsParseMonad
-import HsParser
-import HsSyn
-import Map ( Map )
-import qualified Map hiding ( Map )
import Set
import Paths_haddock ( getDataDir )
+import Binary2
+import Digraph2
+import HsParser
+import HsParseMonad
import Control.Exception ( bracket )
import Control.Monad ( when )
@@ -41,6 +36,10 @@ import System.IO ( stderr, IOMode(..), openFile, hClose, hGetContents, hPutStrLn
import Foreign
import Foreign.C
#endif
+import qualified Data.Map as Map
+import Data.Map (Map)
+import Data.Maybe
+
#if __GLASGOW_HASKELL__ >= 603
import System.Process
@@ -51,6 +50,10 @@ import System.Directory ( doesDirectoryExist, doesFileExist )
import Control.Concurrent
#endif
+import qualified GHC as GHC
+import Outputable
+import SrcLoc
+
-----------------------------------------------------------------------------
-- Top-level stuff
main :: IO ()
@@ -96,6 +99,7 @@ data Flag
| Flag_IgnoreAllExports
| Flag_HideModule String
| Flag_UsePackage String
+ | Flag_GHCFlag String
deriving (Eq)
options :: Bool -> [OptDescr Flag]
@@ -161,17 +165,21 @@ options backwardsCompat =
Option [] ["hide"] (ReqArg Flag_HideModule "MODULE")
"behave as if MODULE has the hide attribute",
Option [] ["use-package"] (ReqArg Flag_UsePackage "PACKAGE")
- "the modules being processed depend on PACKAGE"
+ "the modules being processed depend on PACKAGE",
+ Option [] ["ghc-flag"] (ReqArg Flag_GHCFlag "FLAG")
+ "send a one-word FLAG to the Glasgow Haskell Compiler"
]
run :: [Flag] -> [FilePath] -> IO ()
run flags files = do
- when (Flag_Help `elem` flags) $ do
+
+ whenFlag Flag_Help $ do
prog <- getProgramName
bye (usageInfo (usageHeader prog) (options False))
- when (Flag_Version `elem` flags) $
- bye ("Haddock version " ++ projectVersion ++ ", (c) Simon Marlow 2003\n")
+ whenFlag Flag_Version $
+ bye ("Haddock version " ++ projectVersion ++
+ ", (c) Simon Marlow 2003; port to GHC-api by David Waern 2006\n")
let title = case [str | Flag_Heading str <- flags] of
[] -> ""
@@ -249,12 +257,12 @@ run flags files = do
&& Flag_Html `elem` flags) $
die ("-h cannot be used with --gen-index or --gen-contents")
- when (Flag_GenContents `elem` flags) $ do
+{- when (Flag_GenContents `elem` flags) $ do
ppHtmlContents odir title package maybe_html_help_format
maybe_index_url maybe_source_urls maybe_wiki_urls
visible_read_ifaces prologue
copyHtmlBits odir libdir css_file
-
+-}
when (Flag_GenIndex `elem` flags) $ do
ppHtmlIndex odir title package maybe_html_help_format
maybe_contents_url maybe_source_urls maybe_wiki_urls
@@ -264,7 +272,41 @@ run flags files = do
when (Flag_GenContents `elem` flags && Flag_GenIndex `elem` flags) $ do
ppHtmlHelpFiles title package visible_read_ifaces odir maybe_html_help_format pkg_paths
- parsed_mods <- mapM parse_file files
+ GHC.init (Just "/home/davve/dev/lib/ghc-6.5.20060608")
+ let ghcMode = GHC.JustTypecheck
+ session <- GHC.newSession ghcMode
+ ghcFlags <- GHC.getSessionDynFlags session
+ ghcFlags' <- GHC.initPackages ghcFlags
+
+ let haddockGhcFlags = [ f | Flag_GHCFlag f <- flags ]
+ (ghcFlags'', rest) <- GHC.parseDynamicFlags ghcFlags' haddockGhcFlags
+ when (not (null rest)) (die $ "The following flags are not GHC flags: " ++ pprList rest ++ "\n")
+
+ GHC.defaultErrorHandler ghcFlags'' $ do
+ GHC.setSessionDynFlags session ghcFlags''
+ targets <- mapM (\s -> GHC.guessTarget s Nothing) files
+ GHC.setTargets session targets
+
+ -- find out the module names of the targets, and topologically sort those modules
+ maybe_module_graph <- GHC.depanal session [] True
+ module_graph <- case maybe_module_graph of
+ Just module_graph -> return module_graph
+ Nothing -> die "Failed to load modules"
+ let sorted_modules = flattenSCC (topSortModuleGraph False module_graph Nothing)
+ let modules = [ GHC.ms_mod modsum | modsum <- sorted_modules, GHC.ms_hspp_file modsum `elem` files ]
+ mb_checked_modules <- mapM (GHC.checkModule session) modules
+ let checked_modules = catMaybes mb_checked_modules
+
+{- let parsed_source = unLoc $ GHC.parsedSource (head checked_modules)
+ printSDoc (ppr parsed_source) defaultUserStyle
+-}
+
+ return ()
+ -- case successFlag of
+ -- GHC.Succeeded -> bye "Succeeded"
+ -- GHC.Failed -> bye "Could not load all targets"
+
+{- parsed_mods <- mapM parse_file files
sorted_mod_files <- sortModules (zip parsed_mods files)
-- emits an error message if there are recursive modules
@@ -330,7 +372,15 @@ run flags files = do
-- dump an interface if requested
case dump_iface of
Nothing -> return ()
- Just fn -> dumpInterfaces these_ifaces this_doc_env fn
+ Just fn -> dumpInterfaces these_ifaces this_doc_env fn -}
+ where
+ whenFlag flag action = when (flag `elem` flags) action
+
+ pprList [] = []
+ pprList [x] = show x
+ pprList (x:xs) = show x ++ ", " ++ pprList xs
+
+--moduleFromFilename filename =
parseIfaceOption :: String -> (FilePath,FilePath)
parseIfaceOption s =
@@ -359,6 +409,7 @@ parse_file file = do
Failed err -> die (file ++ ':':err ++ "\n")
)
+{-
getPrologue :: [Flag] -> IO (Maybe Doc)
getPrologue flags
= case [filename | Flag_Prologue filename <- flags ] of
@@ -369,6 +420,18 @@ getPrologue flags
Left err -> dieMsg err
Right doc -> return (Just doc)
_otherwise -> dieMsg "multiple -p/--prologue options"
+-}
+
+getPrologue :: [Flag] -> IO (Maybe (GHC.HsDoc GHC.RdrName))
+getPrologue flags
+ = case [filename | Flag_Prologue filename <- flags ] of
+ [] -> return Nothing
+ [filename] -> do
+ str <- readFile filename
+ case GHC.parseHaddockComment str of
+ Left err -> dieMsg err
+ Right doc -> return (Just doc)
+ _otherwise -> dieMsg "multiple -p/--prologue options"
-- ---------------------------------------------------------------------------
-- External packages
@@ -437,7 +500,7 @@ getPackageIfaces flags verbose =
--
-- 2. Convert all the entity references to "doc names". These are
-- the names we want to link to in the documentation.
-
+{-
mkInterfacePhase1
:: [Flag]
-> Bool -- verbose
@@ -598,6 +661,7 @@ mkInterfacePhase2 verbose iface gbl_doc_env =
iface_doc = orig_module_doc } ->
let
+ -- [ The export list from the renamed output (sort of) ]
exported_visible_names =
[orig | (nm,orig) <- Map.toAscList env, nm `notElem` reexports ]
@@ -719,12 +783,113 @@ derivedInstances mdl decl = case decl of
unknownConstraint :: HsQName
unknownConstraint = UnQual (HsTyClsName (HsIdent "???"))
+-}
-- -----------------------------------------------------------------------------
-- Build the list of items that will become the documentation, from the
-- export list. At this point, the list of ExportItems is in terms of
-- original names.
mkExportItems
+ :: ModuleMap2
+ -> GHC.Module -- this module
+ -> GHC.NameSet -- exported names (orig)
+ -> Map GHC.Name (GHC.HsDecl GHC.Name) -- maps local names to declarations
+ -> Map GHC.Name [GHC.Name] -- sub-map for this module
+ -> [GHC.HsDecl GHC.Name] -- decls in the current module
+ -> [DocOption]
+ -> Maybe [GHC.IE Name]
+ -> Bool -- --ignore-all-exports flag
+ -> ErrMsgM [ExportItem]
+
+mkExportItems mod_map this_mod exported_names decl_map sub_map decls
+ opts maybe_exps ignore_all_exports
+ | isNothing maybe_exps || ignore_all_exports || OptIgnoreExports `elem` opts
+ = everything_local_exported
+ | Just specs <- maybe_exps = do
+ exps <- mapM lookupExport specs
+ return (concat exps)
+ where
+ everything_local_exported = -- everything exported
+ return (fullContentsOfThisModule this_mod decls)
+
+ lookupExport (GHC.IEVar x) = declWith x
+ lookupExport (GHC.IEThingAbs t) = declWith t
+ lookupExport (GHC.IEThingAll t) = declWith t
+ lookupExport (GHC.IEThingWith t cs) = declWith t
+ lookupExport (GHC.IEModuleContents m) = fullContentsOf m
+ lookupExport (GHC.IEGroup lev doc) = return [ ExportGroup lev "" doc ]
+ lookupExport (GHC.IEDoc doc) = return [ ExportDoc doc ]
+ lookupExport (GHC.IEDocNamed str)
+ = do r <- findNamedDoc str decls
+ case r of
+ Nothing -> return []
+ Just found -> return [ ExportDoc found ]
+
+ -- NOTE: I'm unsure about this. Currently only "External" names are considered.
+ declWith :: GHC.Name -> ErrMsgM [ ExportItem ]
+ declWith t | not (isExternalName t) = return []
+ declWith t
+ | Just decl <- findDecl t
+ = return [ ExportDecl t (restrictTo subs (extractDecl x mdl decl)) [] ]
+ | otherwise
+ = return [ ExportNoDecl t t (map (Qual mdl) subs) ]
+ -- can't find the decl (it might be from another package), but let's
+ -- list the entity anyway. Later on, the renamer will change the
+ -- orig name into the import name, so we get a proper link to
+ -- the doc for this entity.
+ where
+ Just mdl = nameModule t
+ x = nameOccName
+ subs = map nameOfQName subs_qnames
+ subs_qnames = filter (`elem` exported_names) all_subs_qnames
+
+ all_subs_qnames = map (Qual mdl) all_subs
+
+ all_subs | mdl == this_mod = Map.findWithDefault [] x sub_map
+ | otherwise = all_subs_of_qname mod_map t
+
+ fullContentsOf m
+ | m == this_mod = return (fullContentsOfThisModule this_mod decls)
+ | otherwise =
+ case Map.lookup m mod_map of
+ Just hmod
+ | OptHide `elem` hmod_options hmod
+ -> return (hmod_orig_exports hmod)
+ | otherwise -> return [ ExportModule m ]
+ Nothing -> return [] -- already emitted a warning in exportedNames
+
+ findDecl :: GHC.Name -> Maybe (GHC.HsDecl GHC.Name)
+ findDecl n | not (isExternalName n) = Nothing
+ findDecl n =
+ | m == this_mod = Map.lookup n decl_map
+ | otherwise =
+ case Map.lookup m mod_map of
+ Just hmod -> Map.lookup n (hmod_decls hmod)
+ Nothing -> Nothing
+ where
+ m = nameModule n
+
+fullContentsOfThisModule :: GHC.Module -> [GHC.HsDecl GHC.Name] -> [ExportItem]
+fullContentsOfThisModule mdl decls =
+ map mkExportItem (filter keepDecl decls)
+ where mkExportItem (DocD (DocGroup lev doc)) = ExportGroup lev "" doc
+ mkExportItem decl = ExportDecl x decl [] -- NOTE: will this work? is x qualified correctly?
+ where Just x = GHC.getDeclMainBinder decl
+
+keepDecl :: GHC.HsDecl -> Bool
+keepDecl (GHC.SigD _) = True
+keepDecl (GHC.TyClD _) = True
+keepDecl (GHC.DocD _) = True
+keepDecl (GHC.ForD (GHC.ForeignImport _ _ _ _)) = True
+keepDecl _ = False
+
+{-
+--< -----------------------------------------------------------------------------
+-- Build the list of items that will become the documentation, from the
+-- export list. At this point, the list of ExportItems is in terms of
+-- original names.
+
+mkExportItems
:: ModuleMap
-> Module -- this module
-> [HsQName] -- exported names (orig)
@@ -803,6 +968,7 @@ mkExportItems mod_map this_mod exported_names decl_map sub_map decls
Just iface -> Map.lookup n (iface_decls iface)
Nothing -> Nothing
+
fullContentsOfThisModule :: Module -> [HsDecl] -> [ExportItem]
fullContentsOfThisModule mdl decls =
map mkExportItem (filter keepDecl decls)
@@ -820,11 +986,70 @@ keepDecl HsDocGroup{} = True
keepDecl HsForeignImport{} = True
keepDecl _ = False
+-}
+
-- Sometimes the declaration we want to export is not the "main" declaration:
-- it might be an individual record selector or a class method. In these
-- cases we have to extract the required declaration (and somehow cobble
-- together a type signature for it...)
+-- We put noSrcLoc everywhere in the cobbled together type signatures since
+-- they aren't actually located in the soure code.
+
+extractDecl :: GHC.Name -> GHC.Module -> GHC.HsDecl GHC.Name -> GHC.HsDecl GHC.Name
+extractDecl name mdl decl
+ | Just n <- getDeclMainBinder decl, n == name = decl
+ | otherwise =
+ case decl of
+ GHC.TyClD d | GHC.isClassDecl d ->
+ let matching_sigs = [ sig | sig <- GHC.tcdSigs d, GHC.sigName sig == Just name ]
+ in case matching_sigs of
+ [s0] -> let (n, tyvar_names) = name_and_tyvars d
+ in SigD (extractClassDecl n mdl tyvar_names s0)
+ _ -> error "internal: extractDecl"
+ GHC.TyClD d | GHC.isDataDecl d ->
+ let (n, tyvar_names) = name_and_tyvars d
+ in SigD (extractRecSel name mdl n tyvar_names (GHC.tcdCons d))
+ _ -> error "internal: extractDecl"
+ where
+ name_and_tyvars d = (GHC.unLoc (GHC.tcdLName d), hsLTyVarLocNames (GHC.tcdTyVars d))
+
+toTypeNoLoc :: Located GHC.Name -> LHsType GHC.Name
+toTypeNoLoc lname = mkNoLoc (GHC.HsTyVar (unLoc lname))
+mkNoLoc :: a -> Located a
+mkNoLoc a = Located noSrcLoc a
+
+-- originally expected unqualified 1:st name, now it doesn't
+extractClassDecl :: GHC.Name -> GHC.Module -> [GHC.Located GHC.Name] -> GHC.LSig GHC.Name -> GHC.Sig GHC.Name
+extractClassDecl c mdl tvs0 (GHC.Located p (GHC.TypeSig lname ltype)) = case ltype of
+ GHC.Located _ (GHC.HsForAllTy exp tvs (GHC.Located p'' preds) ty) ->
+ GHC.TypeSig lname (mkNoLoc (GHC.HsForAllTy exp tvs lctxt ty))
+ _ -> GHC.TypeSig lname (mkNoLoc (GHC.HsForAllTy exp [] lctxt ltype))
+ where
+ lctxt = mkNoLoc ctxt
+ ctxt = [mkNoLoc (GHC.HsClassP c (map toTypeNoLoc tvs0))] ++ preds
+
+extractClassDecl _ _ _ d = error $ "Main.extractClassDecl: unexpected decl"
+
+extractRecSel :: GHC.Located GHC.Name -> GHC.Module -> GHC.Name -> [GHC.Located GHC.Name] -> [GHC.LConDecl GHC.Name]
+ -> GHC.Sig Ghc.Name
+extractRecSel _ _ _ _ [] = error "extractRecSel: selector not found"
+
+-- originally expected unqualified 3:rd name, now it doesn't
+extractRecSel nm mdl t tvs (Located _ con : rest) =
+ case GHC.con_details con of
+ GHC.RecCon fields | (GHC.HsRecField n ty _ : _) <- matching_fields fields ->
+ GHC.TypeSig nm (mkNoLoc (GHC.HsFunTy data_ty (GHC.getBangType ty)))
+ _ -> extractRecSel nm mdl t tvs rest
+ where
+ matching_fields flds = [ f | HsRecField n _ _ <- flds, n == nm ]
+ data_ty = mkNoLoc (foldl HsAppTy (mkNoLoc (HsTyVar t)) (map toTypeNoLoc tvs))
+
+-- Sometimes the declaration we want to export is not the "main" declaration:
+-- it might be an individual record selector or a class method. In these
+-- cases we have to extract the required declaration (and somehow cobble
+-- together a type signature for it...)
+{-
extractDecl :: HsName -> Module -> HsDecl -> HsDecl
extractDecl name mdl decl
| Just n <- declMainBinder decl, n == name = decl
@@ -870,7 +1095,7 @@ extractRecSel nm mdl t tvs (HsRecDecl loc _ _tvs _ fields _mb_doc : rest)
nm `elem` ns ]
data_ty = foldl HsTyApp (HsTyCon (Qual mdl t)) (map HsTyVar tvs)
-
+-}
-- -----------------------------------------------------------------------------
-- Pruning
@@ -1170,7 +1395,7 @@ findNamedDoc name decls = search decls
where search [] = do
tell ["Cannot find documentation for: $" ++ name]
return Nothing
- search (HsDocCommentNamed _ name' doc : rest)
+ search ((DocD (DocCommentNamed name' doc)):rest)
| name == name' = return (Just doc)
| otherwise = search rest
search (_other_decl : rest) = search rest