1
- {-# LANGUAGE CPP, TupleSections, BangPatterns, LambdaCase #-}
1
+ {-# LANGUAGE CPP, TupleSections, BangPatterns, LambdaCase, NamedFieldPuns #-}
2
2
{-# LANGUAGE TypeFamilies #-}
3
3
{-# LANGUAGE ViewPatterns #-}
4
4
{-# OPTIONS_GHC -Wwarn #-}
18
18
-- which creates a Haddock 'Interface' from the typechecking
19
19
-- results 'TypecheckedModule' from GHC.
20
20
-----------------------------------------------------------------------------
21
- module Haddock.Interface.Create (createInterface ) where
21
+ module Haddock.Interface.Create (createInterface , createInterface1 ) where
22
22
23
23
import Documentation.Haddock.Doc (metaDocAppend )
24
24
import Haddock.Types
@@ -28,6 +28,7 @@ import Haddock.Utils
28
28
import Haddock.Convert
29
29
import Haddock.Interface.LexParseRn
30
30
31
+ import Control.Monad.IO.Class
31
32
import Data.Bifunctor
32
33
import Data.Bitraversable
33
34
import qualified Data.Map as M
@@ -39,6 +40,7 @@ import Control.Monad
39
40
import Data.Traversable
40
41
import GHC.Stack (HasCallStack )
41
42
43
+ import GHC.Tc.Utils.Monad (finalSafeMode )
42
44
import GHC.Types.Avail hiding (avail )
43
45
import qualified GHC.Types.Avail as Avail
44
46
import qualified GHC.Unit.Module as Module
@@ -62,6 +64,190 @@ mkExceptionContext :: TypecheckedModule -> String
62
64
mkExceptionContext =
63
65
(" creating Haddock interface for " ++ ) . moduleNameString . ms_mod_name . pm_mod_summary . tm_parsed_module
64
66
67
+ createInterface1
68
+ :: [Flag ]
69
+ -> ModSummary
70
+ -> TcGblEnv
71
+ -> IfaceMap
72
+ -> InstIfaceMap
73
+ -> ErrMsgGhc Interface
74
+ createInterface1 flags mod_sum tc_gbl_env ifaces inst_ifaces = do
75
+
76
+ let
77
+ ModSummary
78
+ {
79
+ -- Cached flags from OPTIONS, INCLUDE and LANGUAGE
80
+ -- pragmas in the modules source code. Used to infer
81
+ -- safety of module.
82
+ ms_hspp_opts
83
+ , ms_location = ModLocation
84
+ {
85
+ ml_hie_file
86
+ }
87
+ } = mod_sum
88
+
89
+ TcGblEnv
90
+ {
91
+ tcg_mod
92
+ , tcg_src
93
+ , tcg_semantic_mod
94
+ , tcg_rdr_env
95
+ , tcg_exports
96
+ , tcg_insts
97
+ , tcg_fam_insts
98
+ , tcg_warns
99
+
100
+ -- Renamed source
101
+ , tcg_rn_imports
102
+ , tcg_rn_exports
103
+ , tcg_rn_decls
104
+
105
+ , tcg_doc_hdr
106
+ } = tc_gbl_env
107
+
108
+ dflags = ms_hspp_opts
109
+
110
+ is_sig = tcg_src == HsigFile
111
+
112
+ (pkg_name_fs, _) =
113
+ modulePackageInfo dflags flags (Just tcg_mod)
114
+
115
+ pkg_name :: Maybe Package
116
+ pkg_name =
117
+ let
118
+ unpack (PackageName name) = unpackFS name
119
+ in
120
+ fmap unpack pkg_name_fs
121
+
122
+ fixities :: FixMap
123
+ fixities = case tcg_rn_decls of
124
+ Nothing -> mempty
125
+ Just dx -> mkFixMap dx
126
+
127
+ -- Locations of all the TH splices
128
+ loc_splices :: [SrcSpan ]
129
+ loc_splices = case tcg_rn_decls of
130
+ Nothing -> []
131
+ Just HsGroup { hs_splcds } -> [ loc | L loc _ <- hs_splcds ]
132
+
133
+ decls <- case tcg_rn_decls of
134
+ Nothing -> do
135
+ liftErrMsg $ tell [ " Warning: Renamed source is not available" ]
136
+ pure []
137
+ Just dx ->
138
+ pure (topDecls dx)
139
+
140
+ -- Derive final options to use for haddocking this module
141
+ doc_opts <- liftErrMsg $ mkDocOpts (haddockOptions ms_hspp_opts) flags tcg_mod
142
+
143
+ let
144
+ -- All elements of an explicit export list, if present
145
+ export_list :: Maybe [(IE GhcRn , Avails )]
146
+ export_list
147
+ | OptIgnoreExports `elem` doc_opts =
148
+ Nothing
149
+ | Just rn_exports <- tcg_rn_exports =
150
+ Just [ (ie, avail) | (L _ ie, avail) <- rn_exports ]
151
+ | otherwise =
152
+ Nothing
153
+
154
+ -- All the exported Names of this module.
155
+ exported_names :: [Name ]
156
+ exported_names =
157
+ concatMap availNamesWithSelectors tcg_exports
158
+
159
+ -- Module imports of the form `import X`. Note that there is
160
+ -- a) no qualification and
161
+ -- b) no import list
162
+ imported_modules :: Map ModuleName [ModuleName ]
163
+ imported_modules
164
+ | Just {} <- export_list =
165
+ unrestrictedModuleImports (map unLoc tcg_rn_imports)
166
+ | otherwise =
167
+ M. empty
168
+
169
+ -- TyThings that have instances defined in this module
170
+ local_instances :: [Name ]
171
+ local_instances =
172
+ [ name
173
+ | name <- map getName tcg_insts ++ map getName tcg_fam_insts
174
+ , nameIsLocalOrFrom tcg_semantic_mod name
175
+ ]
176
+
177
+ -- Infer module safety
178
+ safety <- liftIO (finalSafeMode ms_hspp_opts tc_gbl_env)
179
+
180
+ -- Process the top-level module header documentation.
181
+ (! info, header_doc) <- liftErrMsg $ processModuleHeader dflags pkg_name
182
+ tcg_rdr_env safety tcg_doc_hdr
183
+
184
+ -- Warnings on declarations in this module
185
+ decl_warnings <- liftErrMsg (mkWarningMap dflags tcg_warns tcg_rdr_env exported_names)
186
+
187
+ -- Warning on the module header
188
+ mod_warning <- liftErrMsg (moduleWarning dflags tcg_rdr_env tcg_warns)
189
+
190
+ let
191
+ -- Warnings in this module and transitive warnings from dependend modules
192
+ warnings :: Map Name (Doc Name )
193
+ warnings = M. unions (decl_warnings : map ifaceWarningMap (M. elems ifaces))
194
+
195
+ maps@ (! docs, ! arg_docs, ! decl_map, _) <-
196
+ liftErrMsg (mkMaps dflags pkg_name tcg_rdr_env local_instances decls)
197
+
198
+ export_items <- mkExportItems is_sig ifaces pkg_name tcg_mod tcg_semantic_mod
199
+ warnings tcg_rdr_env exported_names (map fst decls) maps fixities
200
+ imported_modules loc_splices export_list tcg_exports inst_ifaces dflags
201
+
202
+ let
203
+ visible_names :: [Name ]
204
+ visible_names = mkVisibleNames maps export_items doc_opts
205
+
206
+ -- Measure haddock documentation coverage.
207
+ pruned_export_items :: [ExportItem GhcRn ]
208
+ pruned_export_items = pruneExportItems export_items
209
+
210
+ ! haddockable = 1 + length export_items -- module + exports
211
+ ! haddocked = (if isJust tcg_doc_hdr then 1 else 0 ) + length pruned_export_items
212
+
213
+ coverage :: (Int , Int )
214
+ ! coverage = (haddockable, haddocked)
215
+
216
+ aliases :: Map Module ModuleName
217
+ aliases = mkAliasMap (unitState dflags) tcg_rn_imports
218
+
219
+ return $! Interface
220
+ {
221
+ ifaceMod = tcg_mod
222
+ , ifaceIsSig = is_sig
223
+ , ifaceOrigFilename = msHsFilePath mod_sum
224
+ , ifaceHieFile = Just ml_hie_file
225
+ , ifaceInfo = info
226
+ , ifaceDoc = Documentation header_doc mod_warning
227
+ , ifaceRnDoc = Documentation Nothing Nothing
228
+ , ifaceOptions = doc_opts
229
+ , ifaceDocMap = docs
230
+ , ifaceArgMap = arg_docs
231
+ , ifaceRnDocMap = M. empty
232
+ , ifaceRnArgMap = M. empty
233
+ , ifaceExportItems = if OptPrune `elem` doc_opts then
234
+ pruned_export_items else export_items
235
+ , ifaceRnExportItems = []
236
+ , ifaceExports = exported_names
237
+ , ifaceVisibleExports = visible_names
238
+ , ifaceDeclMap = decl_map
239
+ , ifaceFixMap = fixities
240
+ , ifaceModuleAliases = aliases
241
+ , ifaceInstances = tcg_insts
242
+ , ifaceFamInstances = tcg_fam_insts
243
+ , ifaceOrphanInstances = [] -- Filled in attachInstances
244
+ , ifaceRnOrphanInstances = [] -- Filled in attachInstances
245
+ , ifaceHaddockCoverage = coverage
246
+ , ifaceWarningMap = warnings
247
+ , ifaceDynFlags = dflags
248
+ }
249
+
250
+
65
251
-- | Use a 'TypecheckedModule' to produce an 'Interface'.
66
252
-- To do this, we need access to already processed modules in the topological
67
253
-- sort. That's what's in the 'IfaceMap'.
@@ -167,8 +353,7 @@ createInterface tm flags modMap instIfaceMap =
167
353
! prunedExportItems = seqList prunedExportItems' `seq` prunedExportItems'
168
354
169
355
let ! aliases =
170
- mkAliasMap (unitState dflags) $ tm_renamed_source tm
171
-
356
+ mkAliasMap (unitState dflags) imports
172
357
modWarn <- liftErrMsg (moduleWarning dflags gre warnings)
173
358
174
359
-- Prune the docstring 'Map's to keep only docstrings that are not private.
@@ -217,35 +402,32 @@ createInterface tm flags modMap instIfaceMap =
217
402
-- create a mapping from the module identity of M, to an alias N
218
403
-- (if there are multiple aliases, we pick the last one.) This
219
404
-- will go in 'ifaceModuleAliases'.
220
- mkAliasMap :: UnitState -> Maybe RenamedSource -> M. Map Module ModuleName
221
- mkAliasMap state mRenamedSource =
222
- case mRenamedSource of
223
- Nothing -> M. empty
224
- Just (_,impDecls,_,_) ->
225
- M. fromList $
226
- mapMaybe (\ (SrcLoc. L _ impDecl) -> do
227
- SrcLoc. L _ alias <- ideclAs impDecl
228
- return $
229
- (lookupModuleDyn state
230
- -- TODO: This is supremely dodgy, because in general the
231
- -- UnitId isn't going to look anything like the package
232
- -- qualifier (even with old versions of GHC, the
233
- -- IPID would be p-0.1, but a package qualifier never
234
- -- has a version number it. (Is it possible that in
235
- -- Haddock-land, the UnitIds never have version numbers?
236
- -- I, ezyang, have not quite understand Haddock's package
237
- -- identifier model.)
238
- --
239
- -- Additionally, this is simulating some logic GHC already
240
- -- has for deciding how to qualify names when it outputs
241
- -- them to the user. We should reuse that information;
242
- -- or at least reuse the renamed imports, which know what
243
- -- they import!
244
- (fmap Module. fsToUnit $
245
- fmap sl_fs $ ideclPkgQual impDecl)
246
- (case ideclName impDecl of SrcLoc. L _ name -> name),
247
- alias))
248
- impDecls
405
+ mkAliasMap :: UnitState -> [LImportDecl GhcRn ] -> M. Map Module ModuleName
406
+ mkAliasMap state impDecls =
407
+ M. fromList $
408
+ mapMaybe (\ (SrcLoc. L _ impDecl) -> do
409
+ SrcLoc. L _ alias <- ideclAs impDecl
410
+ return $
411
+ (lookupModuleDyn state
412
+ -- TODO: This is supremely dodgy, because in general the
413
+ -- UnitId isn't going to look anything like the package
414
+ -- qualifier (even with old versions of GHC, the
415
+ -- IPID would be p-0.1, but a package qualifier never
416
+ -- has a version number it. (Is it possible that in
417
+ -- Haddock-land, the UnitIds never have version numbers?
418
+ -- I, ezyang, have not quite understand Haddock's package
419
+ -- identifier model.)
420
+ --
421
+ -- Additionally, this is simulating some logic GHC already
422
+ -- has for deciding how to qualify names when it outputs
423
+ -- them to the user. We should reuse that information;
424
+ -- or at least reuse the renamed imports, which know what
425
+ -- they import!
426
+ (fmap Module. fsToUnit $
427
+ fmap sl_fs $ ideclPkgQual impDecl)
428
+ (case ideclName impDecl of SrcLoc. L _ name -> name),
429
+ alias))
430
+ impDecls
249
431
250
432
-- We want to know which modules are imported without any qualification. This
251
433
-- way we can display module reexports more compactly. This mapping also looks
0 commit comments