Skip to content

Commit f00d381

Browse files
m-renaudphadej
authored andcommitted
Refactor shared TargetProblem data types into their own module.
Moved "problem rendering" to CmdErrorMessages module Additions by Oleg Grenrus: - There were CommonTargetProblem, but now TargetProblem has an extension point so we can have just one type. A lot of code is simplified as we don't need to pass in injection from CommonTargetProblem to the resulting `err` type.
1 parent 06c3eff commit f00d381

File tree

13 files changed

+422
-444
lines changed

13 files changed

+422
-444
lines changed

cabal-install/Distribution/Client/CmdBench.hs

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ module Distribution.Client.CmdBench (
88
benchAction,
99

1010
-- * Internals exposed for testing
11-
TargetProblem(..),
11+
componentNotBenchmarkProblem,
12+
isSubComponentProblem,
13+
noBenchmarksProblem,
1214
selectPackageTargets,
1315
selectComponentTarget
1416
) where
@@ -18,7 +20,11 @@ import Prelude ()
1820

1921
import Distribution.Client.ProjectOrchestration
2022
import Distribution.Client.CmdErrorMessages
21-
23+
( renderTargetSelector, showTargetSelector, renderTargetProblem,
24+
renderTargetProblemNoTargets, plural, targetSelectorPluralPkgs,
25+
targetSelectorFilter )
26+
import Distribution.Client.TargetProblem
27+
( TargetProblem (..) )
2228
import Distribution.Client.NixStyleOptions
2329
( NixStyleFlags (..), nixStyleOptions, defaultNixStyleFlags )
2430
import Distribution.Client.Setup
@@ -98,7 +104,6 @@ benchAction flags@NixStyleFlags {..} targetStrings globalFlags = do
98104
$ resolveTargets
99105
selectPackageTargets
100106
selectComponentTarget
101-
TargetProblemCommon
102107
elaboratedPlan
103108
Nothing
104109
targetSelectors
@@ -126,7 +131,7 @@ benchAction flags@NixStyleFlags {..} targetStrings globalFlags = do
126131
-- or fail if there are no benchmarks or no buildable benchmarks.
127132
--
128133
selectPackageTargets :: TargetSelector
129-
-> [AvailableTarget k] -> Either TargetProblem [k]
134+
-> [AvailableTarget k] -> Either BenchTargetProblem [k]
130135
selectPackageTargets targetSelector targets
131136

132137
-- If there are any buildable benchmark targets then we select those
@@ -139,7 +144,7 @@ selectPackageTargets targetSelector targets
139144

140145
-- If there are no benchmarks but some other targets then we report that
141146
| not (null targets)
142-
= Left (TargetProblemNoBenchmarks targetSelector)
147+
= Left (noBenchmarksProblem targetSelector)
143148

144149
-- If there are no targets at all then we report that
145150
| otherwise
@@ -161,34 +166,27 @@ selectPackageTargets targetSelector targets
161166
-- to the basic checks on being buildable etc.
162167
--
163168
selectComponentTarget :: SubComponentTarget
164-
-> AvailableTarget k -> Either TargetProblem k
169+
-> AvailableTarget k -> Either BenchTargetProblem k
165170
selectComponentTarget subtarget@WholeComponent t
166171
| CBenchName _ <- availableTargetComponentName t
167-
= either (Left . TargetProblemCommon) return $
168-
selectComponentTargetBasic subtarget t
172+
= selectComponentTargetBasic subtarget t
169173
| otherwise
170-
= Left (TargetProblemComponentNotBenchmark (availableTargetPackageId t)
171-
(availableTargetComponentName t))
174+
= Left (componentNotBenchmarkProblem
175+
(availableTargetPackageId t)
176+
(availableTargetComponentName t))
172177

173178
selectComponentTarget subtarget t
174-
= Left (TargetProblemIsSubComponent (availableTargetPackageId t)
175-
(availableTargetComponentName t)
176-
subtarget)
179+
= Left (isSubComponentProblem
180+
(availableTargetPackageId t)
181+
(availableTargetComponentName t)
182+
subtarget)
177183

178184
-- | The various error conditions that can occur when matching a
179185
-- 'TargetSelector' against 'AvailableTarget's for the @bench@ command.
180186
--
181-
data TargetProblem =
182-
TargetProblemCommon TargetProblemCommon
183-
184-
-- | The 'TargetSelector' matches benchmarks but none are buildable
185-
| TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]
186-
187-
-- | There are no targets at all
188-
| TargetProblemNoTargets TargetSelector
189-
187+
data BenchProblem =
190188
-- | The 'TargetSelector' matches targets but no benchmarks
191-
| TargetProblemNoBenchmarks TargetSelector
189+
TargetProblemNoBenchmarks TargetSelector
192190

193191
-- | The 'TargetSelector' refers to a component that is not a benchmark
194192
| TargetProblemComponentNotBenchmark PackageId ComponentName
@@ -197,42 +195,57 @@ data TargetProblem =
197195
| TargetProblemIsSubComponent PackageId ComponentName SubComponentTarget
198196
deriving (Eq, Show)
199197

200-
reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a
201-
reportTargetProblems verbosity =
202-
die' verbosity . unlines . map renderTargetProblem
203198

204-
renderTargetProblem :: TargetProblem -> String
205-
renderTargetProblem (TargetProblemCommon problem) =
206-
renderTargetProblemCommon "run" problem
199+
type BenchTargetProblem = TargetProblem BenchProblem
207200

208-
renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =
209-
renderTargetProblemNoneEnabled "benchmark" targetSelector targets
201+
noBenchmarksProblem :: TargetSelector -> TargetProblem BenchProblem
202+
noBenchmarksProblem = CustomTargetProblem . TargetProblemNoBenchmarks
210203

211-
renderTargetProblem (TargetProblemNoBenchmarks targetSelector) =
212-
"Cannot run benchmarks for the target '" ++ showTargetSelector targetSelector
213-
++ "' which refers to " ++ renderTargetSelector targetSelector
214-
++ " because "
215-
++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"
216-
++ " not contain any benchmarks."
204+
componentNotBenchmarkProblem :: PackageId -> ComponentName -> TargetProblem BenchProblem
205+
componentNotBenchmarkProblem pkgid name = CustomTargetProblem $
206+
TargetProblemComponentNotBenchmark pkgid name
217207

218-
renderTargetProblem (TargetProblemNoTargets targetSelector) =
208+
isSubComponentProblem
209+
:: PackageId
210+
-> ComponentName
211+
-> SubComponentTarget
212+
-> TargetProblem BenchProblem
213+
isSubComponentProblem pkgid name subcomponent = CustomTargetProblem $
214+
TargetProblemIsSubComponent pkgid name subcomponent
215+
216+
reportTargetProblems :: Verbosity -> [BenchTargetProblem] -> IO a
217+
reportTargetProblems verbosity =
218+
die' verbosity . unlines . map renderBenchTargetProblem
219+
220+
renderBenchTargetProblem :: BenchTargetProblem -> String
221+
renderBenchTargetProblem (TargetProblemNoTargets targetSelector) =
219222
case targetSelectorFilter targetSelector of
220223
Just kind | kind /= BenchKind
221224
-> "The bench command is for running benchmarks, but the target '"
222225
++ showTargetSelector targetSelector ++ "' refers to "
223226
++ renderTargetSelector targetSelector ++ "."
224227

225228
_ -> renderTargetProblemNoTargets "benchmark" targetSelector
229+
renderBenchTargetProblem problem =
230+
renderTargetProblem "benchmark" renderBenchProblem problem
231+
232+
renderBenchProblem :: BenchProblem -> String
233+
renderBenchProblem (TargetProblemNoBenchmarks targetSelector) =
234+
"Cannot run benchmarks for the target '" ++ showTargetSelector targetSelector
235+
++ "' which refers to " ++ renderTargetSelector targetSelector
236+
++ " because "
237+
++ plural (targetSelectorPluralPkgs targetSelector) "it does" "they do"
238+
++ " not contain any benchmarks."
226239

227-
renderTargetProblem (TargetProblemComponentNotBenchmark pkgid cname) =
240+
renderBenchProblem (TargetProblemComponentNotBenchmark pkgid cname) =
228241
"The bench command is for running benchmarks, but the target '"
229242
++ showTargetSelector targetSelector ++ "' refers to "
230243
++ renderTargetSelector targetSelector ++ " from the package "
231244
++ prettyShow pkgid ++ "."
232245
where
233246
targetSelector = TargetComponent pkgid cname WholeComponent
234247

235-
renderTargetProblem (TargetProblemIsSubComponent pkgid cname subtarget) =
248+
renderBenchProblem (TargetProblemIsSubComponent pkgid cname subtarget) =
236249
"The bench command can only run benchmarks as a whole, "
237250
++ "not files or modules within them, but the target '"
238251
++ showTargetSelector targetSelector ++ "' refers to "

cabal-install/Distribution/Client/CmdBuild.hs

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module Distribution.Client.CmdBuild (
77
buildAction,
88

99
-- * Internals exposed for testing
10-
TargetProblem(..),
1110
selectPackageTargets,
1211
selectComponentTarget
1312
) where
@@ -16,6 +15,8 @@ import Prelude ()
1615
import Distribution.Client.Compat.Prelude
1716

1817
import Distribution.Client.ProjectOrchestration
18+
import Distribution.Client.TargetProblem
19+
( TargetProblem (..), TargetProblem' )
1920
import Distribution.Client.CmdErrorMessages
2021

2122
import Distribution.Client.NixStyleOptions
@@ -112,11 +113,10 @@ buildAction flags@NixStyleFlags { extraFlags = buildFlags, ..} targetStrings glo
112113

113114
-- Interpret the targets on the command line as build targets
114115
-- (as opposed to say repl or haddock targets).
115-
targets <- either (reportTargetProblems verbosity) return
116+
targets <- either (reportBuildTargetProblems verbosity) return
116117
$ resolveTargets
117118
selectPackageTargets
118119
selectComponentTarget
119-
TargetProblemCommon
120120
elaboratedPlan
121121
Nothing
122122
targetSelectors
@@ -152,7 +152,7 @@ buildAction flags@NixStyleFlags { extraFlags = buildFlags, ..} targetStrings glo
152152
-- components
153153
--
154154
selectPackageTargets :: TargetSelector
155-
-> [AvailableTarget k] -> Either TargetProblem [k]
155+
-> [AvailableTarget k] -> Either TargetProblem' [k]
156156
selectPackageTargets targetSelector targets
157157

158158
-- If there are any buildable targets then we select those
@@ -185,36 +185,12 @@ selectPackageTargets targetSelector targets
185185
-- For the @build@ command we just need the basic checks on being buildable etc.
186186
--
187187
selectComponentTarget :: SubComponentTarget
188-
-> AvailableTarget k -> Either TargetProblem k
189-
selectComponentTarget subtarget =
190-
either (Left . TargetProblemCommon) Right
191-
. selectComponentTargetBasic subtarget
188+
-> AvailableTarget k -> Either TargetProblem' k
189+
selectComponentTarget = selectComponentTargetBasic
192190

193-
194-
-- | The various error conditions that can occur when matching a
195-
-- 'TargetSelector' against 'AvailableTarget's for the @build@ command.
196-
--
197-
data TargetProblem =
198-
TargetProblemCommon TargetProblemCommon
199-
200-
-- | The 'TargetSelector' matches targets but none are buildable
201-
| TargetProblemNoneEnabled TargetSelector [AvailableTarget ()]
202-
203-
-- | There are no targets at all
204-
| TargetProblemNoTargets TargetSelector
205-
deriving (Eq, Show)
206-
207-
reportTargetProblems :: Verbosity -> [TargetProblem] -> IO a
208-
reportTargetProblems verbosity =
209-
die' verbosity . unlines . map renderTargetProblem
210-
211-
renderTargetProblem :: TargetProblem -> String
212-
renderTargetProblem (TargetProblemCommon problem) =
213-
renderTargetProblemCommon "build" problem
214-
renderTargetProblem (TargetProblemNoneEnabled targetSelector targets) =
215-
renderTargetProblemNoneEnabled "build" targetSelector targets
216-
renderTargetProblem(TargetProblemNoTargets targetSelector) =
217-
renderTargetProblemNoTargets "build" targetSelector
191+
reportBuildTargetProblems :: Verbosity -> [TargetProblem'] -> IO a
192+
reportBuildTargetProblems verbosity problems =
193+
reportTargetProblems verbosity "build" problems
218194

219195
reportCannotPruneDependencies :: Verbosity -> CannotPruneDependencies -> IO a
220196
reportCannotPruneDependencies verbosity =

cabal-install/Distribution/Client/CmdErrorMessages.hs

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
{-# LANGUAGE RecordWildCards, NamedFieldPuns #-}
1+
{-# LANGUAGE LambdaCase #-}
2+
{-# LANGUAGE NamedFieldPuns #-}
3+
{-# LANGUAGE RecordWildCards #-}
4+
25

36
-- | Utilities to help format error messages for the various CLI commands.
47
--
@@ -10,14 +13,23 @@ module Distribution.Client.CmdErrorMessages (
1013
import Distribution.Client.Compat.Prelude
1114
import Prelude ()
1215

13-
import Distribution.Client.ProjectOrchestration
16+
import Distribution.Client.ProjectPlanning
17+
( AvailableTarget(..), AvailableTargetStatus(..),
18+
CannotPruneDependencies(..), TargetRequested(..) )
19+
import Distribution.Client.TargetSelector
20+
( SubComponentTarget(..) )
21+
import Distribution.Client.TargetProblem
22+
( TargetProblem(..), TargetProblem' )
1423
import Distribution.Client.TargetSelector
15-
( ComponentKindFilter, componentKind, showTargetSelector )
24+
( ComponentKind(..), ComponentKindFilter, TargetSelector(..),
25+
componentKind, showTargetSelector )
1626

1727
import Distribution.Package
18-
( packageId, PackageName, packageName )
28+
( PackageId, packageId, PackageName, packageName )
29+
import Distribution.Simple.Utils
30+
( die' )
1931
import Distribution.Types.ComponentName
20-
( showComponentName )
32+
( ComponentName(..), showComponentName )
2133
import Distribution.Types.LibraryName
2234
( LibraryName(..) )
2335
import Distribution.Solver.Types.OptionalStanza
@@ -189,30 +201,46 @@ renderComponentKind Plural ckind = case ckind of
189201

190202

191203
-------------------------------------------------------
192-
-- Renderering error messages for TargetProblemCommon
204+
-- Renderering error messages for TargetProblem
193205
--
194206

195-
renderTargetProblemCommon :: String -> TargetProblemCommon -> String
196-
renderTargetProblemCommon verb (TargetNotInProject pkgname) =
207+
-- | Default implementation of 'reportTargetProblems' simply renders one problem per line.
208+
reportTargetProblems :: Verbosity -> String -> [TargetProblem'] -> IO a
209+
reportTargetProblems verbosity verb =
210+
die' verbosity . unlines . map (renderTargetProblem verb absurd)
211+
212+
-- | Default implementation of 'renderTargetProblem'.
213+
renderTargetProblem
214+
:: String -- ^ verb
215+
-> (a -> String) -- ^ how to render custom problems
216+
-> TargetProblem a
217+
-> String
218+
renderTargetProblem _verb f (CustomTargetProblem x) = f x
219+
renderTargetProblem verb _ (TargetProblemNoneEnabled targetSelector targets) =
220+
renderTargetProblemNoneEnabled verb targetSelector targets
221+
renderTargetProblem verb _ (TargetProblemNoTargets targetSelector) =
222+
renderTargetProblemNoTargets verb targetSelector
223+
224+
renderTargetProblem verb _ (TargetNotInProject pkgname) =
197225
"Cannot " ++ verb ++ " the package " ++ prettyShow pkgname ++ ", it is not "
198226
++ "in this project (either directly or indirectly). If you want to add it "
199227
++ "to the project then edit the cabal.project file."
200228

201-
renderTargetProblemCommon verb (TargetAvailableInIndex pkgname) =
229+
renderTargetProblem verb _ (TargetAvailableInIndex pkgname) =
202230
"Cannot " ++ verb ++ " the package " ++ prettyShow pkgname ++ ", it is not "
203231
++ "in this project (either directly or indirectly), but it is in the current "
204232
++ "package index. If you want to add it to the project then edit the "
205233
++ "cabal.project file."
206234

207-
renderTargetProblemCommon verb (TargetComponentNotProjectLocal pkgid cname _) =
235+
renderTargetProblem verb _ (TargetComponentNotProjectLocal pkgid cname _) =
208236
"Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because the "
209237
++ "package " ++ prettyShow pkgid ++ " is not local to the project, and cabal "
210238
++ "does not currently support building test suites or benchmarks of "
211239
++ "non-local dependencies. To run test suites or benchmarks from "
212240
++ "dependencies you can unpack the package locally and adjust the "
213241
++ "cabal.project file to include that package directory."
214242

215-
renderTargetProblemCommon verb (TargetComponentNotBuildable pkgid cname _) =
243+
renderTargetProblem verb _ (TargetComponentNotBuildable pkgid cname _) =
216244
"Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because it is "
217245
++ "marked as 'buildable: False' within the '" ++ prettyShow (packageName pkgid)
218246
++ ".cabal' file (at least for the current configuration). If you believe it "
@@ -221,7 +249,7 @@ renderTargetProblemCommon verb (TargetComponentNotBuildable pkgid cname _) =
221249
++ "edit the .cabal file to declare it as buildable and fix any resulting "
222250
++ "build problems."
223251

224-
renderTargetProblemCommon verb (TargetOptionalStanzaDisabledByUser _ cname _) =
252+
renderTargetProblem verb _ (TargetOptionalStanzaDisabledByUser _ cname _) =
225253
"Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because "
226254
++ "building " ++ compkinds ++ " has been explicitly disabled in the "
227255
++ "configuration. You can adjust this configuration in the "
@@ -234,7 +262,7 @@ renderTargetProblemCommon verb (TargetOptionalStanzaDisabledByUser _ cname _) =
234262
where
235263
compkinds = renderComponentKind Plural (componentKind cname)
236264

237-
renderTargetProblemCommon verb (TargetOptionalStanzaDisabledBySolver pkgid cname _) =
265+
renderTargetProblem verb _ (TargetOptionalStanzaDisabledBySolver pkgid cname _) =
238266
"Cannot " ++ verb ++ " the " ++ showComponentName cname ++ " because the "
239267
++ "solver did not find a plan that included the " ++ compkinds
240268
++ " for " ++ prettyShow pkgid ++ ". It is probably worth trying again with "
@@ -247,7 +275,7 @@ renderTargetProblemCommon verb (TargetOptionalStanzaDisabledBySolver pkgid cname
247275
where
248276
compkinds = renderComponentKind Plural (componentKind cname)
249277

250-
renderTargetProblemCommon verb (TargetProblemUnknownComponent pkgname ecname) =
278+
renderTargetProblem verb _ (TargetProblemUnknownComponent pkgname ecname) =
251279
"Cannot " ++ verb ++ " the "
252280
++ (case ecname of
253281
Left ucname -> "component " ++ prettyShow ucname
@@ -259,13 +287,13 @@ renderTargetProblemCommon verb (TargetProblemUnknownComponent pkgname ecname) =
259287
Right cname -> renderComponentKind Singular (componentKind cname))
260288
++ " with that name."
261289

262-
renderTargetProblemCommon verb (TargetProblemNoSuchPackage pkgid) =
290+
renderTargetProblem verb _ (TargetProblemNoSuchPackage pkgid) =
263291
"Internal error when trying to " ++ verb ++ " the package "
264292
++ prettyShow pkgid ++ ". The package is not in the set of available targets "
265293
++ "for the project plan, which would suggest an inconsistency "
266294
++ "between readTargetSelectors and resolveTargets."
267295

268-
renderTargetProblemCommon verb (TargetProblemNoSuchComponent pkgid cname) =
296+
renderTargetProblem verb _ (TargetProblemNoSuchComponent pkgid cname) =
269297
"Internal error when trying to " ++ verb ++ " the "
270298
++ showComponentName cname ++ " from the package " ++ prettyShow pkgid
271299
++ ". The package,component pair is not in the set of available targets "

0 commit comments

Comments
 (0)