@@ -8,27 +8,31 @@ module Development.IDE.Types.Exports
8
8
rendered,
9
9
moduleNameText,
10
10
occNameText,
11
+ renderOcc,
12
+ mkTypeOcc,
13
+ mkVarOrDataOcc,
11
14
isDatacon,
12
15
createExportsMap,
13
16
createExportsMapMg,
14
- createExportsMapTc,
15
17
buildModuleExportMapFrom,
16
18
createExportsMapHieDb,
17
19
size,
20
+ exportsMapSize,
18
21
updateExportsMapMg
19
22
) where
20
23
21
24
import Control.DeepSeq (NFData (.. ))
22
25
import Control.Monad
23
26
import Data.Bifunctor (Bifunctor (second ))
27
+ import Data.Char (isUpper )
24
28
import Data.Hashable (Hashable )
25
29
import Data.HashMap.Strict (HashMap , elems )
26
30
import qualified Data.HashMap.Strict as Map
27
31
import Data.HashSet (HashSet )
28
32
import qualified Data.HashSet as Set
29
33
import Data.List (foldl' , isSuffixOf )
30
- import Data.Text (Text , pack )
31
- import Data.Text.Encoding (decodeUtf8 )
34
+ import Data.Text (Text , uncons )
35
+ import Data.Text.Encoding (decodeUtf8 , encodeUtf8 )
32
36
import Development.IDE.GHC.Compat
33
37
import Development.IDE.GHC.Orphans ()
34
38
import Development.IDE.GHC.Util
@@ -37,52 +41,72 @@ import HieDb
37
41
38
42
39
43
data ExportsMap = ExportsMap
40
- { getExportsMap :: ! (HashMap IdentifierText (HashSet IdentInfo ))
41
- , getModuleExportsMap :: ! (HashMap ModuleNameText (HashSet IdentInfo ))
44
+ { getExportsMap :: ! (OccEnv (HashSet IdentInfo ))
45
+ , getModuleExportsMap :: ! (ModuleNameEnv (HashSet IdentInfo ))
42
46
}
43
- deriving (Show )
44
-
45
- deleteEntriesForModule :: ModuleNameText -> ExportsMap -> ExportsMap
46
- deleteEntriesForModule m em = ExportsMap
47
- { getExportsMap =
48
- let moduleIds = Map. lookupDefault mempty m (getModuleExportsMap em)
49
- in deleteAll
50
- (rendered <$> Set. toList moduleIds)
51
- (getExportsMap em)
52
- , getModuleExportsMap = Map. delete m (getModuleExportsMap em)
53
- }
54
- where
55
- deleteAll keys map = foldr Map. delete map keys
47
+
48
+ instance Show ExportsMap where
49
+ show (ExportsMap occs mods) =
50
+ unwords [ " ExportsMap { getExportsMap ="
51
+ , printWithoutUniques $ mapOccEnv (text . show ) occs
52
+ , " getModuleExportsMap ="
53
+ , printWithoutUniques $ mapUFM (text . show ) mods
54
+ , " }"
55
+ ]
56
+
57
+ -- | `updateExportsMap old new` results in an export map containing
58
+ -- the union of old and new, but with all the module entries new overriding
59
+ -- those in old.
60
+ updateExportsMap :: ExportsMap -> ExportsMap -> ExportsMap
61
+ updateExportsMap old new = ExportsMap
62
+ { getExportsMap = delListFromOccEnv (getExportsMap old) old_occs `plusOccEnv` getExportsMap new -- plusOccEnv is right biased
63
+ , getModuleExportsMap = (getModuleExportsMap old) `plusUFM` (getModuleExportsMap new) -- plusUFM is right biased
64
+ }
65
+ where old_occs = concat [map name $ Set. toList (lookupWithDefaultUFM_Directly (getModuleExportsMap old) mempty m_uniq)
66
+ | m_uniq <- nonDetKeysUFM (getModuleExportsMap new)]
56
67
57
68
size :: ExportsMap -> Int
58
- size = sum . map length . elems . getExportsMap
69
+ size = sum . map ( Set. size) . occEnvElts . getExportsMap
59
70
60
- instance Semigroup ExportsMap where
61
- ExportsMap a b <> ExportsMap c d = ExportsMap (Map. unionWith (<>) a c) (Map. unionWith (<>) b d)
71
+ mkVarOrDataOcc :: Text -> OccName
72
+ mkVarOrDataOcc t = mkOcc $ mkFastStringByteString $ encodeUtf8 t
73
+ where
74
+ mkOcc
75
+ | Just (c,_) <- uncons t
76
+ , c == ' :' || isUpper c = mkDataOccFS
77
+ | otherwise = mkVarOccFS
62
78
63
- instance Monoid ExportsMap where
64
- mempty = ExportsMap Map. empty Map. empty
79
+ mkTypeOcc :: Text -> OccName
80
+ mkTypeOcc t = mkTcOccFS $ mkFastStringByteString $ encodeUtf8 t
65
81
66
- type IdentifierText = Text
67
- type ModuleNameText = Text
82
+ exportsMapSize :: ExportsMap -> Int
83
+ exportsMapSize = foldOccEnv ( \ _ x -> x + 1 ) 0 . getExportsMap
68
84
85
+ instance Semigroup ExportsMap where
86
+ ExportsMap a b <> ExportsMap c d = ExportsMap (plusOccEnv_C (<>) a c) (plusUFM_C (<>) b d)
69
87
70
- rendered :: IdentInfo -> IdentifierText
88
+ instance Monoid ExportsMap where
89
+ mempty = ExportsMap emptyOccEnv emptyUFM
90
+
91
+ rendered :: IdentInfo -> Text
71
92
rendered = occNameText . name
72
93
73
94
-- | Render an identifier as imported or exported style.
74
95
-- TODO: pattern synonymoccNameText :: OccName -> Text
75
- occNameText :: OccName -> IdentifierText
96
+ occNameText :: OccName -> Text
76
97
occNameText name
77
- | isTcOcc name && isSymOcc name = " type " <> renderOcc
78
- | otherwise = renderOcc
98
+ | isTcOcc name && isSymOcc name = " type " <> renderedOcc
99
+ | otherwise = renderedOcc
79
100
where
80
- renderOcc = decodeUtf8 . bytesFS . occNameFS $ name
101
+ renderedOcc = renderOcc name
102
+
103
+ renderOcc :: OccName -> Text
104
+ renderOcc = decodeUtf8 . bytesFS . occNameFS
81
105
82
- moduleNameText :: IdentInfo -> ModuleNameText
106
+ moduleNameText :: IdentInfo -> Text
83
107
moduleNameText = moduleNameText' . identModuleName
84
108
85
- moduleNameText' :: ModuleName -> ModuleNameText
109
+ moduleNameText' :: ModuleName -> Text
86
110
moduleNameText' = decodeUtf8 . bytesFS . moduleNameFS
87
111
88
112
data IdentInfo = IdentInfo
@@ -129,39 +153,27 @@ mkIdentInfos mod (AvailTC _ nn flds)
129
153
createExportsMap :: [ModIface ] -> ExportsMap
130
154
createExportsMap modIface = do
131
155
let exportList = concatMap doOne modIface
132
- let exportsMap = Map. fromListWith (<>) $ map (\ (a,_,c) -> (a, c)) exportList
156
+ let exportsMap = mkOccEnv_C (<>) $ map (\ (a,_,c) -> (a, c)) exportList
133
157
ExportsMap exportsMap $ buildModuleExportMap $ map (\ (_,b,c) -> (b, c)) exportList
134
158
where
135
159
doOne modIFace = do
136
160
let getModDetails = unpackAvail $ moduleName $ mi_module modIFace
137
- concatMap (fmap (second Set. fromList) . getModDetails) (mi_exports modIFace)
161
+ concatMap (getModDetails) (mi_exports modIFace)
138
162
139
163
createExportsMapMg :: [ModGuts ] -> ExportsMap
140
164
createExportsMapMg modGuts = do
141
165
let exportList = concatMap doOne modGuts
142
- let exportsMap = Map. fromListWith (<>) $ map (\ (a,_,c) -> (a, c)) exportList
166
+ let exportsMap = mkOccEnv_C (<>) $ map (\ (a,_,c) -> (a, c)) exportList
143
167
ExportsMap exportsMap $ buildModuleExportMap $ map (\ (_,b,c) -> (b, c)) exportList
144
168
where
145
169
doOne mi = do
146
170
let getModuleName = moduleName $ mg_module mi
147
- concatMap (fmap (second Set. fromList) . unpackAvail getModuleName) (mg_exports mi)
171
+ concatMap (unpackAvail getModuleName) (mg_exports mi)
148
172
149
173
updateExportsMapMg :: [ModGuts ] -> ExportsMap -> ExportsMap
150
- updateExportsMapMg modGuts old = old' <> new
174
+ updateExportsMapMg modGuts old = updateExportsMap old new
151
175
where
152
176
new = createExportsMapMg modGuts
153
- old' = deleteAll old (Map. keys $ getModuleExportsMap new)
154
- deleteAll = foldl' (flip deleteEntriesForModule)
155
-
156
- createExportsMapTc :: [TcGblEnv ] -> ExportsMap
157
- createExportsMapTc modIface = do
158
- let exportList = concatMap doOne modIface
159
- let exportsMap = Map. fromListWith (<>) $ map (\ (a,_,c) -> (a, c)) exportList
160
- ExportsMap exportsMap $ buildModuleExportMap $ map (\ (_,b,c) -> (b, c)) exportList
161
- where
162
- doOne mi = do
163
- let getModuleName = moduleName $ tcg_mod mi
164
- concatMap (fmap (second Set. fromList) . unpackAvail getModuleName) (tcg_exports mi)
165
177
166
178
nonInternalModules :: ModuleName -> Bool
167
179
nonInternalModules = not . (" .Internal" `isSuffixOf` ) . moduleNameString
@@ -171,44 +183,44 @@ type WithHieDb = forall a. (HieDb -> IO a) -> IO a
171
183
createExportsMapHieDb :: WithHieDb -> IO ExportsMap
172
184
createExportsMapHieDb withHieDb = do
173
185
mods <- withHieDb getAllIndexedMods
174
- idents <- forM (filter (nonInternalModules . modInfoName . hieModInfo) mods) $ \ m -> do
186
+ idents' <- forM (filter (nonInternalModules . modInfoName . hieModInfo) mods) $ \ m -> do
175
187
let mn = modInfoName $ hieModInfo m
176
- fmap (wrap . unwrap mn) <$> withHieDb (\ hieDb -> getExportsForModule hieDb mn)
177
- let exportsMap = Map. fromListWith (<>) (concat idents)
178
- return $! ExportsMap exportsMap $ buildModuleExportMap (concat idents)
188
+ fmap (unwrap mn) <$> withHieDb (\ hieDb -> getExportsForModule hieDb mn)
189
+ let idents = concat idents'
190
+ let exportsMap = mkOccEnv_C (<>) (keyWith name idents)
191
+ return $! ExportsMap exportsMap $ buildModuleExportMap (keyWith identModuleName idents)
179
192
where
180
- wrap identInfo = (rendered identInfo, Set. fromList [identInfo])
181
- -- unwrap :: ExportRow -> IdentInfo
182
193
unwrap m ExportRow {.. } = IdentInfo exportName exportParent m
194
+ keyWith f xs = [(f x, Set. singleton x) | x <- xs]
183
195
184
- unpackAvail :: ModuleName -> IfaceExport -> [(Text , Text , [ IdentInfo ] )]
196
+ unpackAvail :: ModuleName -> IfaceExport -> [(OccName , ModuleName , HashSet IdentInfo )]
185
197
unpackAvail mn
186
198
| nonInternalModules mn = map f . mkIdentInfos mn
187
199
| otherwise = const []
188
200
where
189
- f id @ IdentInfo {.. } = (printOutputable name, moduleNameText id ,[ id ] )
201
+ f id @ IdentInfo {.. } = (name, mn, Set. singleton id )
190
202
191
203
192
- identInfoToKeyVal :: IdentInfo -> (ModuleNameText , IdentInfo )
204
+ identInfoToKeyVal :: IdentInfo -> (ModuleName , IdentInfo )
193
205
identInfoToKeyVal identInfo =
194
- (moduleNameText identInfo, identInfo)
206
+ (identModuleName identInfo, identInfo)
195
207
196
- buildModuleExportMap :: [(Text , HashSet IdentInfo )] -> Map. HashMap ModuleNameText (HashSet IdentInfo )
208
+ buildModuleExportMap :: [(ModuleName , HashSet IdentInfo )] -> ModuleNameEnv (HashSet IdentInfo )
197
209
buildModuleExportMap exportsMap = do
198
210
let lst = concatMap (Set. toList. snd ) exportsMap
199
211
let lstThree = map identInfoToKeyVal lst
200
212
sortAndGroup lstThree
201
213
202
- buildModuleExportMapFrom :: [ModIface ] -> Map. HashMap Text (HashSet IdentInfo )
214
+ buildModuleExportMapFrom :: [ModIface ] -> ModuleNameEnv (HashSet IdentInfo )
203
215
buildModuleExportMapFrom modIfaces = do
204
216
let exports = map extractModuleExports modIfaces
205
- Map. fromListWith (<>) exports
217
+ listToUFM_C (<>) exports
206
218
207
- extractModuleExports :: ModIface -> (Text , HashSet IdentInfo )
219
+ extractModuleExports :: ModIface -> (ModuleName , HashSet IdentInfo )
208
220
extractModuleExports modIFace = do
209
221
let modName = moduleName $ mi_module modIFace
210
222
let functionSet = Set. fromList $ concatMap (mkIdentInfos modName) $ mi_exports modIFace
211
- (moduleNameText' modName, functionSet)
223
+ (modName, functionSet)
212
224
213
- sortAndGroup :: [(ModuleNameText , IdentInfo )] -> Map. HashMap ModuleNameText (HashSet IdentInfo )
214
- sortAndGroup assocs = Map. fromListWith (<>) [(k, Set. fromList [v]) | (k, v) <- assocs]
225
+ sortAndGroup :: [(ModuleName , IdentInfo )] -> ModuleNameEnv (HashSet IdentInfo )
226
+ sortAndGroup assocs = listToUFM_C (<>) [(k, Set. fromList [v]) | (k, v) <- assocs]
0 commit comments