@@ -9,6 +9,7 @@ module Development.IDE.Import.DependencyInformation
9
9
, ModuleParseError (.. )
10
10
, TransitiveDependencies (.. )
11
11
, FilePathId (.. )
12
+ , NamedModuleDep (.. )
12
13
13
14
, PathIdMap
14
15
, emptyPathIdMap
@@ -17,7 +18,7 @@ module Development.IDE.Import.DependencyInformation
17
18
, pathToId
18
19
, idToPath
19
20
, reachableModules
20
-
21
+ , modLocationToNormalizedFilePath
21
22
, processDependencyInformation
22
23
, transitiveDeps
23
24
) where
@@ -46,6 +47,7 @@ import GHC.Generics (Generic)
46
47
47
48
import Development.IDE.Types.Diagnostics
48
49
import Development.IDE.Types.Location
50
+ import Development.IDE.Import.FindImports (ArtifactsLocation (.. ))
49
51
50
52
import GHC
51
53
import Module
@@ -67,27 +69,34 @@ newtype FilePathId = FilePathId { getFilePathId :: Int }
67
69
deriving (Show , NFData , Eq , Ord )
68
70
69
71
data PathIdMap = PathIdMap
70
- { idToPathMap :: ! (IntMap NormalizedFilePath )
72
+ { idToPathMap :: ! (IntMap ArtifactsLocation )
71
73
, pathToIdMap :: ! (HashMap NormalizedFilePath FilePathId )
72
74
}
73
75
deriving (Show , Generic )
74
76
75
77
instance NFData PathIdMap
76
78
79
+ modLocationToNormalizedFilePath :: ArtifactsLocation -> NormalizedFilePath
80
+ modLocationToNormalizedFilePath (ArtifactsLocation loc) =
81
+ case ml_hs_file loc of
82
+ Just filePath -> toNormalizedFilePath filePath
83
+ -- Since we craete all 'ModLocation' values via 'mkHomeModLocation'
84
+ Nothing -> error " Has something changed in mkHomeModLocation?"
85
+
77
86
emptyPathIdMap :: PathIdMap
78
87
emptyPathIdMap = PathIdMap IntMap. empty HMS. empty
79
88
80
- getPathId :: NormalizedFilePath -> PathIdMap -> (FilePathId , PathIdMap )
89
+ getPathId :: ArtifactsLocation -> PathIdMap -> (FilePathId , PathIdMap )
81
90
getPathId path m@ PathIdMap {.. } =
82
- case HMS. lookup path pathToIdMap of
91
+ case HMS. lookup (modLocationToNormalizedFilePath path) pathToIdMap of
83
92
Nothing ->
84
93
let ! newId = FilePathId $ HMS. size pathToIdMap
85
94
in (newId, insertPathId path newId m)
86
95
Just id -> (id , m)
87
96
88
- insertPathId :: NormalizedFilePath -> FilePathId -> PathIdMap -> PathIdMap
97
+ insertPathId :: ArtifactsLocation -> FilePathId -> PathIdMap -> PathIdMap
89
98
insertPathId path id PathIdMap {.. } =
90
- PathIdMap (IntMap. insert (getFilePathId id ) path idToPathMap) (HMS. insert path id pathToIdMap)
99
+ PathIdMap (IntMap. insert (getFilePathId id ) path idToPathMap) (HMS. insert (modLocationToNormalizedFilePath path) id pathToIdMap)
91
100
92
101
insertImport :: FilePathId -> Either ModuleParseError ModuleImports -> RawDependencyInformation -> RawDependencyInformation
93
102
insertImport (FilePathId k) v rawDepInfo = rawDepInfo { rawImports = IntMap. insert k v (rawImports rawDepInfo) }
@@ -96,7 +105,11 @@ pathToId :: PathIdMap -> NormalizedFilePath -> FilePathId
96
105
pathToId PathIdMap {pathToIdMap} path = pathToIdMap HMS. ! path
97
106
98
107
idToPath :: PathIdMap -> FilePathId -> NormalizedFilePath
99
- idToPath PathIdMap {idToPathMap} (FilePathId id ) = idToPathMap IntMap. ! id
108
+ idToPath pathIdMap filePathId = modLocationToNormalizedFilePath $ idToModLocation pathIdMap filePathId
109
+
110
+ idToModLocation :: PathIdMap -> FilePathId -> ArtifactsLocation
111
+ idToModLocation PathIdMap {idToPathMap} (FilePathId id ) = idToPathMap IntMap. ! id
112
+
100
113
101
114
-- | Unprocessed results that we find by following imports recursively.
102
115
data RawDependencyInformation = RawDependencyInformation
@@ -112,6 +125,7 @@ data DependencyInformation =
112
125
DependencyInformation
113
126
{ depErrorNodes :: ! (IntMap (NonEmpty NodeError ))
114
127
-- ^ Nodes that cannot be processed correctly.
128
+ , depModuleNames :: ! (IntMap ShowableModuleName )
115
129
, depModuleDeps :: ! (IntMap IntSet )
116
130
-- ^ For a non-error node, this contains the set of module immediate dependencies
117
131
-- in the same package.
@@ -120,6 +134,12 @@ data DependencyInformation =
120
134
, depPathIdMap :: ! PathIdMap
121
135
} deriving (Show , Generic )
122
136
137
+ newtype ShowableModuleName =
138
+ ShowableModuleName { showableModuleName :: ModuleName }
139
+ deriving NFData
140
+
141
+ instance Show ShowableModuleName where show = moduleNameString . showableModuleName
142
+
123
143
reachableModules :: DependencyInformation -> [NormalizedFilePath ]
124
144
reachableModules DependencyInformation {.. } =
125
145
map (idToPath depPathIdMap . FilePathId ) $ IntMap. keys depErrorNodes <> IntMap. keys depModuleDeps
@@ -186,16 +206,24 @@ processDependencyInformation rawDepInfo@RawDependencyInformation{..} =
186
206
DependencyInformation
187
207
{ depErrorNodes = IntMap. fromList errorNodes
188
208
, depModuleDeps = moduleDeps
209
+ , depModuleNames = IntMap. fromList $ coerce moduleNames
189
210
, depPkgDeps = pkgDependencies rawDepInfo
190
211
, depPathIdMap = rawPathIdMap
191
212
}
192
213
where resultGraph = buildResultGraph rawImports
193
214
(errorNodes, successNodes) = partitionNodeResults $ IntMap. toList resultGraph
215
+ moduleNames :: [(FilePathId , ModuleName )]
216
+ moduleNames =
217
+ [ (fId, modName) | (_, imports) <- successNodes, (L _ modName, fId) <- imports]
194
218
successEdges :: [(FilePathId , FilePathId , [FilePathId ])]
195
219
successEdges =
196
- map (\ (file, imports) -> (FilePathId file, FilePathId file, map snd imports)) successNodes
220
+ map
221
+ (\ (file, imports) -> (FilePathId file, FilePathId file, map snd imports))
222
+ successNodes
197
223
moduleDeps =
198
- IntMap. fromList $ map (\ (_, FilePathId v, vs) -> (v, IntSet. fromList $ coerce vs)) successEdges
224
+ IntMap. fromList $
225
+ map (\ (_, FilePathId v, vs) -> (v, IntSet. fromList $ coerce vs))
226
+ successEdges
199
227
200
228
-- | Given a dependency graph, buildResultGraph detects and propagates errors in that graph as follows:
201
229
-- 1. Mark each node that is part of an import cycle as an error node.
@@ -268,22 +296,52 @@ transitiveDeps DependencyInformation{..} file = do
268
296
IntSet. delete (getFilePathId fileId) .
269
297
IntSet. fromList . map (fst3 . fromVertex) .
270
298
reachable g <$> toVertex (getFilePathId fileId)
271
- let transitiveModuleDepIds = filter (\ v -> v `IntSet.member` reachableVs) $ map (fst3 . fromVertex) vs
299
+ let transitiveModuleDepIds =
300
+ filter (\ v -> v `IntSet.member` reachableVs) $ map (fst3 . fromVertex) vs
272
301
let transitivePkgDeps =
273
302
Set. toList $ Set. unions $
274
303
map (\ f -> IntMap. findWithDefault Set. empty f depPkgDeps) $
275
304
getFilePathId fileId : transitiveModuleDepIds
276
- let transitiveModuleDeps = map (idToPath depPathIdMap . FilePathId ) transitiveModuleDepIds
305
+ let transitiveModuleDeps =
306
+ map (idToPath depPathIdMap . FilePathId ) transitiveModuleDepIds
307
+ let transitiveNamedModuleDeps =
308
+ [ NamedModuleDep (idToPath depPathIdMap (FilePathId fid)) mn ml
309
+ | (fid, ShowableModuleName mn) <- IntMap. toList depModuleNames
310
+ , let ArtifactsLocation ml = idToPathMap depPathIdMap IntMap. ! fid
311
+ ]
277
312
pure TransitiveDependencies {.. }
278
- where (g, fromVertex, toVertex) = graphFromEdges (map (\ (f, fs) -> (f, f, IntSet. toList fs)) $ IntMap. toList depModuleDeps)
279
- vs = topSort g
313
+ where
314
+ (g, fromVertex, toVertex) = graphFromEdges (map (\ (f, fs) -> (f, f, IntSet. toList fs)) $ IntMap. toList depModuleDeps)
315
+ vs = topSort g
280
316
281
317
data TransitiveDependencies = TransitiveDependencies
282
318
{ transitiveModuleDeps :: [NormalizedFilePath ]
319
+ , transitiveNamedModuleDeps :: [NamedModuleDep ]
283
320
-- ^ Transitive module dependencies in topological order.
284
321
-- The module itself is not included.
285
322
, transitivePkgDeps :: [InstalledUnitId ]
286
323
-- ^ Transitive pkg dependencies in unspecified order.
287
324
} deriving (Eq , Show , Generic )
288
325
289
326
instance NFData TransitiveDependencies
327
+
328
+ data NamedModuleDep = NamedModuleDep {
329
+ nmdFilePath :: ! NormalizedFilePath ,
330
+ nmdModuleName :: ! ModuleName ,
331
+ nmdModLocation :: ! ModLocation
332
+ }
333
+ deriving Generic
334
+
335
+ instance Eq NamedModuleDep where
336
+ a == b = nmdFilePath a == nmdFilePath b
337
+
338
+ instance NFData NamedModuleDep where
339
+ rnf NamedModuleDep {.. } =
340
+ rnf nmdFilePath `seq`
341
+ rnf nmdModuleName `seq`
342
+ -- 'ModLocation' lacks an 'NFData' instance
343
+ rwhnf nmdModLocation
344
+
345
+ instance Show NamedModuleDep where
346
+ show NamedModuleDep {.. } = show nmdFilePath
347
+
0 commit comments