@@ -36,20 +36,20 @@ import Module
37-- | Unprocessed results that we get from following all imports recursively starting from a module.
37-- | Unprocessed results that we get from following all imports recursively starting from a module.
38data RawDependencyInformation = RawDependencyInformation
38data RawDependencyInformation = RawDependencyInformation
39− { moduleDependencies :: Map FilePath (Either ModuleParseError [(Located ModuleName, Maybe FilePath)])
39+ { moduleDependencies :: Map NormalizedFilePath (Either ModuleParseError [(Located ModuleName, Maybe NormalizedFilePath)])
40− , pkgDependencies :: Map FilePath (Set InstalledUnitId)
40+ , pkgDependencies :: Map NormalizedFilePath (Set InstalledUnitId)
41 -- ^ Transitive dependencies on pkgs of this file, i.e. immidiate package dependencies and the
41 -- ^ Transitive dependencies on pkgs of this file, i.e. immidiate package dependencies and the
42 -- transitive package dependencies of those packages.
42 -- transitive package dependencies of those packages.
45data DependencyInformation =
45data DependencyInformation =
46 DependencyInformation
46 DependencyInformation
47− { depErrorNodes :: Map FilePath (NonEmpty NodeError)
47+ { depErrorNodes :: Map NormalizedFilePath (NonEmpty NodeError)
48 -- ^ Nodes that cannot be processed correctly.
48 -- ^ Nodes that cannot be processed correctly.
49− , depModuleDeps :: Map FilePath (Set FilePath)
49+ , depModuleDeps :: Map NormalizedFilePath (Set NormalizedFilePath)
50 -- ^ For a non-error node, this contains the set of module immediate dependencies
50 -- ^ For a non-error node, this contains the set of module immediate dependencies
51 -- in the same package.
51 -- in the same package.
52− , depPkgDeps :: Map FilePath (Set InstalledUnitId)
52+ , depPkgDeps :: Map NormalizedFilePath (Set InstalledUnitId)
53 -- ^ For a non-error node, this contains the set of immediate pkg deps.
53 -- ^ For a non-error node, this contains the set of immediate pkg deps.
54 } deriving (Show, Generic)
54 } deriving (Show, Generic)
@@ -69,7 +69,7 @@ instance NFData LocateError
70-- | An error attached to a node in the dependency graph.
70-- | An error attached to a node in the dependency graph.
71data NodeError
71data NodeError
72− = PartOfCycle (Located ModuleName) [FilePath]
72+ = PartOfCycle (Located ModuleName) [NormalizedFilePath]
73 -- ^ This module is part of an import cycle. The module name corresponds
73 -- ^ This module is part of an import cycle. The module name corresponds
74 -- to the import that enters the cycle starting from this module.
74 -- to the import that enters the cycle starting from this module.
75 -- The list of filepaths represents the elements
75 -- The list of filepaths represents the elements
@@ -94,10 +94,12 @@ instance NFData NodeError where
94-- `ErrorNode`. Otherwise it is a `SuccessNode`.
94-- `ErrorNode`. Otherwise it is a `SuccessNode`.
95data NodeResult
95data NodeResult
96 = ErrorNode (NonEmpty NodeError)
96 = ErrorNode (NonEmpty NodeError)
97− | SuccessNode [(Located ModuleName, FilePath)]
97+ | SuccessNode [(Located ModuleName, NormalizedFilePath)]
98 deriving Show
98 deriving Show
101+ :: [(a, NodeResult)]
100−partitionNodeResults :: [(a, NodeResult)] -> ([(a, NonEmpty NodeError)], [(a, [(Located ModuleName, FilePath)])])
102+ -> ([(a, NonEmpty NodeError)], [(a, [(Located ModuleName, NormalizedFilePath)])])
101partitionNodeResults = partitionEithers . map f
103partitionNodeResults = partitionEithers . map f
102 where f (a, ErrorNode errs) = Left (a, errs)
104 where f (a, ErrorNode errs) = Left (a, errs)
103 f (a, SuccessNode imps) = Right (a, imps)
105 f (a, SuccessNode imps) = Right (a, imps)
@@ -116,7 +118,7 @@ processDependencyInformation rawResults =
116 , depPkgDeps = pkgDependencies rawResults
118 , depPkgDeps = pkgDependencies rawResults
118 where resultGraph = buildResultGraph rawResults
120 where resultGraph = buildResultGraph rawResults
119− successEdges :: [(FilePath, FilePath, [FilePath])]
121+ successEdges :: [(NormalizedFilePath, NormalizedFilePath, [NormalizedFilePath])]
120 successEdges = map (\(k,ks) -> (k,k,ks)) $ MS.toList $
122 successEdges = map (\(k,ks) -> (k,k,ks)) $ MS.toList $
121 MS.map (map snd) $ MS.mapMaybe successNode resultGraph
123 MS.map (map snd) $ MS.mapMaybe successNode resultGraph
122 moduleDeps =
124 moduleDeps =
@@ -131,22 +133,22 @@ processDependencyInformation rawResults =
131-- 2. Mark each node that has a parse error as an error node.
133-- 2. Mark each node that has a parse error as an error node.
132-- 3. Mark each node whose immediate children could not be located as an error.
134-- 3. Mark each node whose immediate children could not be located as an error.
133-- 4. Recursively propagate errors to parents if they are not already error nodes.
135-- 4. Recursively propagate errors to parents if they are not already error nodes.
134−buildResultGraph :: RawDependencyInformation -> Map FilePath NodeResult
136+buildResultGraph :: RawDependencyInformation -> Map NormalizedFilePath NodeResult
135buildResultGraph g = propagatedErrors
137buildResultGraph g = propagatedErrors
137 sccs = stronglyConnComp (graphEdges g)
139 sccs = stronglyConnComp (graphEdges g)
138 (_, cycles) = partitionSCC sccs
140 (_, cycles) = partitionSCC sccs
139− cycleErrors :: Map FilePath NodeResult
141+ cycleErrors :: Map NormalizedFilePath NodeResult
140 cycleErrors = MS.unionsWith (<>) $ map errorsForCycle cycles
142 cycleErrors = MS.unionsWith (<>) $ map errorsForCycle cycles
141− errorsForCycle :: [FilePath] -> Map FilePath NodeResult
143+ errorsForCycle :: [NormalizedFilePath] -> Map NormalizedFilePath NodeResult
142 errorsForCycle files =
144 errorsForCycle files =
143 MS.fromListWith (<>) (concatMap (cycleErrorsForFile files) files)
145 MS.fromListWith (<>) (concatMap (cycleErrorsForFile files) files)
144− cycleErrorsForFile :: [FilePath] -> FilePath -> [(FilePath,NodeResult)]
146+ cycleErrorsForFile :: [NormalizedFilePath] -> NormalizedFilePath -> [(NormalizedFilePath,NodeResult)]
145 cycleErrorsForFile cycle f =
147 cycleErrorsForFile cycle f =
146 let entryPoints = mapMaybe (findImport f) cycle
148 let entryPoints = mapMaybe (findImport f) cycle
147 in map (\imp -> (f, ErrorNode (PartOfCycle imp cycle :| []))) entryPoints
149 in map (\imp -> (f, ErrorNode (PartOfCycle imp cycle :| []))) entryPoints
148 otherErrors = MS.map otherErrorsForFile (moduleDependencies g)
150 otherErrors = MS.map otherErrorsForFile (moduleDependencies g)
149− otherErrorsForFile :: Either ModuleParseError [(Located ModuleName, Maybe FilePath)] -> NodeResult
151+ otherErrorsForFile :: Either ModuleParseError [(Located ModuleName, Maybe NormalizedFilePath)] -> NodeResult
150 otherErrorsForFile (Left err) = ErrorNode (ParseError err :| [])
152 otherErrorsForFile (Left err) = ErrorNode (ParseError err :| [])
151 otherErrorsForFile (Right imports) =
153 otherErrorsForFile (Right imports) =
152 let toEither (imp, Nothing) = Left imp
154 let toEither (imp, Nothing) = Left imp
@@ -171,17 +173,17 @@ buildResultGraph g = propagatedErrors
171 in case nonEmpty errs of
173 in case nonEmpty errs of
172 Nothing -> n
174 Nothing -> n
173 Just errs' -> ErrorNode (NonEmpty.map (ParentOfErrorNode . fst) errs')
175 Just errs' -> ErrorNode (NonEmpty.map (ParentOfErrorNode . fst) errs')
174− findImport :: FilePath -> FilePath -> Maybe (Located ModuleName)
176+ findImport :: NormalizedFilePath -> NormalizedFilePath -> Maybe (Located ModuleName)
175 findImport file importedFile =
177 findImport file importedFile =
176 case moduleDependencies g MS.! file of
178 case moduleDependencies g MS.! file of
177 Left _ -> error "Tried to call findImport on a module with a parse error"
179 Left _ -> error "Tried to call findImport on a module with a parse error"
178 Right imports ->
180 Right imports ->
179 fmap fst $ find (\(_, resolvedImp) -> resolvedImp == Just importedFile) imports
181 fmap fst $ find (\(_, resolvedImp) -> resolvedImp == Just importedFile) imports
181−graphEdges :: RawDependencyInformation -> [(FilePath, FilePath, [FilePath])]
183+graphEdges :: RawDependencyInformation -> [(NormalizedFilePath, NormalizedFilePath, [NormalizedFilePath])]
182graphEdges g =
184graphEdges g =
183 map (\(k, ks) -> (k, k, ks)) $ MS.toList $ MS.map deps $ moduleDependencies g
185 map (\(k, ks) -> (k, k, ks)) $ MS.toList $ MS.map deps $ moduleDependencies g
184− where deps :: Either e [(i, Maybe FilePath)] -> [FilePath]
186+ where deps :: Either e [(i, Maybe NormalizedFilePath)] -> [NormalizedFilePath]
185 deps (Left _) = []
187 deps (Left _) = []
186 deps (Right imports) = mapMaybe snd imports
188 deps (Right imports) = mapMaybe snd imports
@@ -190,17 +192,17 @@ partitionSCC (CyclicSCC xs:rest) = second (xs:) $ partitionSCC rest
190partitionSCC (AcyclicSCC x:rest) = first (x:) $ partitionSCC rest
192partitionSCC (AcyclicSCC x:rest) = first (x:) $ partitionSCC rest
191partitionSCC [] = ([], [])
193partitionSCC [] = ([], [])
193−transitiveDeps :: DependencyInformation -> FilePath -> Maybe TransitiveDependencies
195+transitiveDeps :: DependencyInformation -> NormalizedFilePath -> Maybe TransitiveDependencies
194transitiveDeps DependencyInformation{..} f = do
196transitiveDeps DependencyInformation{..} f = do
195 reachableVs <- Set.delete f . Set.fromList . map (fst3 . fromVertex) . reachable g <$> toVertex f
197 reachableVs <- Set.delete f . Set.fromList . map (fst3 . fromVertex) . reachable g <$> toVertex f
196 let transitiveModuleDeps = filter (\v -> v `Set.member` reachableVs) $ map (fst3 . fromVertex) vs
198 let transitiveModuleDeps = filter (\v -> v `Set.member` reachableVs) $ map (fst3 . fromVertex) vs
197 let transitivePkgDeps = Set.toList $ foldMap (\f -> MS.findWithDefault Set.empty f depPkgDeps) (f : transitiveModuleDeps)
199 let transitivePkgDeps = Set.toList $ foldMap (\f -> MS.findWithDefault Set.empty f depPkgDeps) (f : transitiveModuleDeps)
198− pure $ TransitiveDependencies {..}
200+ pure TransitiveDependencies {..}
199 where (g, fromVertex, toVertex) = graphFromEdges (map (\(f, fs) -> (f, f, Set.toList fs)) $ MS.toList depModuleDeps)
201 where (g, fromVertex, toVertex) = graphFromEdges (map (\(f, fs) -> (f, f, Set.toList fs)) $ MS.toList depModuleDeps)
200 vs = topSort g
202 vs = topSort g
202data TransitiveDependencies = TransitiveDependencies
204data TransitiveDependencies = TransitiveDependencies
203− { transitiveModuleDeps :: [FilePath]
205+ { transitiveModuleDeps :: [NormalizedFilePath]
204 -- ^ Transitive module dependencies in topological order.
206 -- ^ Transitive module dependencies in topological order.
205 -- The module itself is not included.
207 -- The module itself is not included.
206 , transitivePkgDeps :: [InstalledUnitId]
208 , transitivePkgDeps :: [InstalledUnitId]