Skip to content

Commit 35af7d1

Browse files
authored
Merge pull request #6736 from commercialhaskell/prettier
Make `stack ghci`'s Stack errors prettier
2 parents 845a282 + 22c5c66 commit 35af7d1

File tree

2 files changed

+50
-50
lines changed

2 files changed

+50
-50
lines changed

doc/maintainers/stack_errors.md

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
In connection with considering Stack's support of the
66
[Haskell Error Index](https://errors.haskell.org/) initiative, this page seeks
77
to take stock of the errors that Stack itself can raise, by reference to the
8-
`master` branch of the Stack repository. Last updated: 2025-04-09.
8+
`master` branch of the Stack repository. Last updated: 2025-05-12.
99

1010
* `Stack.main`: catches exceptions from action `commandLineHandler`.
1111

@@ -132,21 +132,15 @@ to take stock of the errors that Stack itself can raise, by reference to the
132132

133133
`[S-6716]` used in `unregisterGhcPkgIds`
134134

135-
- `Stack.Ghci.GhciException`
136-
137-
~~~haskell
138-
[S-6716] = InvalidPackageOption String
139-
[S-9632] | LoadingDuplicateModules
140-
[S-3600] | MissingFileTarget String
141-
[S-9906] | Can'tSpecifyFilesAndTargets
142-
[S-5188] | Can'tSpecifyFilesAndMainIs
143-
~~~
144-
145135
- `Stack.Ghci.GhciPrettyException`
146136

147137
~~~haskell
148138
[S-6948] = GhciTargetParseException [StyleDoc]
149139
[S-1939] | CandidatesIndexOutOfRangeBug
140+
[S-6716] | InvalidPackageOption String
141+
[S-3600] | FileTargetIsInvalidAbsFile String
142+
[S-9906] | Can'tSpecifyFilesAndTargets
143+
[S-5188] | Can'tSpecifyFilesAndMainIs
150144
~~~
151145

152146
- `Stack.Hoogle.HoogleException`

src/Stack/Ghci.hs

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ Types and functions related to Stack's @ghci@ and @repl@ commands.
1414
module Stack.Ghci
1515
( GhciOpts (..)
1616
, GhciPkgInfo (..)
17-
, GhciException (..)
1817
, GhciPrettyException (..)
1918
, ModuleMap
2019
, ghciCmd
@@ -102,42 +101,15 @@ import Stack.Types.SourceMap
102101
import System.IO ( putStrLn )
103102
import System.Permissions ( setScriptPerms )
104103

105-
-- | Type representing exceptions thrown by functions exported by the
106-
-- "Stack.Ghci" module.
107-
data GhciException
108-
= InvalidPackageOption !String
109-
| LoadingDuplicateModules
110-
| MissingFileTarget !String
111-
| Can'tSpecifyFilesAndTargets
112-
| Can'tSpecifyFilesAndMainIs
113-
deriving (Show, Typeable)
114-
115-
instance Exception GhciException where
116-
displayException (InvalidPackageOption name) =
117-
"Error: [S-6716]\n"
118-
++ "Failed to parse '--package' option " ++ name ++ "."
119-
displayException LoadingDuplicateModules = unlines
120-
[ "Error: [S-9632]"
121-
, "Not attempting to start ghci due to these duplicate modules."
122-
, "Use '--no-load' to try to start it anyway, without loading any \
123-
\modules (but these are still likely to cause errors)."
124-
]
125-
displayException (MissingFileTarget name) =
126-
"Error: [S-3600]\n"
127-
++ "Cannot find file target " ++ name ++ "."
128-
displayException Can'tSpecifyFilesAndTargets =
129-
"Error: [S-9906]\n"
130-
++ "Cannot use 'stack ghci' with both file targets and package targets."
131-
displayException Can'tSpecifyFilesAndMainIs =
132-
"Error: [S-5188]\n"
133-
++ "Cannot use 'stack ghci' with both file targets and '--main-is' \
134-
\flag."
135-
136104
-- | Type representing \'pretty\' exceptions thrown by functions exported by the
137105
-- "Stack.Ghci" module.
138106
data GhciPrettyException
139107
= GhciTargetParseException ![StyleDoc]
140108
| CandidatesIndexOutOfRangeBug
109+
| InvalidPackageOption !String
110+
| FileTargetIsInvalidAbsFile !String
111+
| Can'tSpecifyFilesAndTargets
112+
| Can'tSpecifyFilesAndMainIs
141113
deriving (Show, Typeable)
142114

143115
instance Pretty GhciPrettyException where
@@ -152,6 +124,40 @@ instance Pretty GhciPrettyException where
152124
]
153125
pretty CandidatesIndexOutOfRangeBug = bugPrettyReport "[S-1939]" $
154126
flow "figureOutMainFile: index out of range."
127+
pretty (InvalidPackageOption name) =
128+
"[S-6716]"
129+
<> line
130+
<> fillSep
131+
[ flow "Failed to parse"
132+
, style Shell "--package"
133+
, "option"
134+
, style Target (fromString name) <> "."
135+
]
136+
pretty (FileTargetIsInvalidAbsFile name) =
137+
"[S-3600]"
138+
<> line
139+
<> fillSep
140+
[ flow "Cannot work out a valid path for file target"
141+
, style File (fromString name) <> "."
142+
]
143+
pretty Can'tSpecifyFilesAndTargets =
144+
"[S-9906]"
145+
<> line
146+
<> fillSep
147+
[ flow "Cannot use"
148+
, style Shell "stack ghci"
149+
, flow "with both file targets and package targets."
150+
]
151+
pretty Can'tSpecifyFilesAndMainIs =
152+
"[S-5188]"
153+
<> line
154+
<> fillSep
155+
[ flow "Cannot use"
156+
, style Shell "stack ghci"
157+
, flow "with both file targets and"
158+
, style Shell "--main-is"
159+
, "flag."
160+
]
155161

156162
instance Exception GhciPrettyException
157163

@@ -237,7 +243,7 @@ ghci opts = do
237243
(inputTargets, mfileTargets) <- case etargets of
238244
Right packageTargets -> pure (packageTargets, Nothing)
239245
Left rawFileTargets -> do
240-
whenJust mainIsTargets $ \_ -> throwM Can'tSpecifyFilesAndMainIs
246+
whenJust mainIsTargets $ \_ -> prettyThrowM Can'tSpecifyFilesAndMainIs
241247
-- Figure out targets based on filepath targets
242248
(targetMap, fileInfo, extraFiles) <- findFileTargets locals rawFileTargets
243249
pure (targetMap, Just (fileInfo, extraFiles))
@@ -305,7 +311,7 @@ preprocessTargets buildOptsCLI sma rawTargets = do
305311
let fp = T.unpack fp0
306312
mpath <- forgivingResolveFile' fp
307313
case mpath of
308-
Nothing -> throwM (MissingFileTarget fp)
314+
Nothing -> prettyThrowM (FileTargetIsInvalidAbsFile fp)
309315
Just path -> pure path
310316
pure (Left fileTargets)
311317
else do
@@ -318,7 +324,7 @@ preprocessTargets buildOptsCLI sma rawTargets = do
318324
Just (TargetParseException xs) ->
319325
prettyThrowM $ GhciTargetParseException xs
320326
_ -> throwM pex
321-
unless (null fileTargetsRaw) $ throwM Can'tSpecifyFilesAndTargets
327+
unless (null fileTargetsRaw) $ prettyThrowM Can'tSpecifyFilesAndTargets
322328
pure (Right normalTargets.targets)
323329

324330
parseMainIsTargets ::
@@ -472,7 +478,7 @@ checkAdditionalPackages :: MonadThrow m => [String] -> m [PackageName]
472478
checkAdditionalPackages pkgs = forM pkgs $ \name -> do
473479
let mres = (pkgName <$> parsePackageIdentifier name)
474480
<|> parsePackageNameThrowing name
475-
maybe (throwM $ InvalidPackageOption name) pure mres
481+
maybe (prettyThrowM $ InvalidPackageOption name) pure mres
476482

477483
runGhci ::
478484
HasEnvConfig env
@@ -1081,14 +1087,14 @@ checkForIssues pkgs =
10811087
checkForDuplicateModules :: HasTerm env => [GhciPkgInfo] -> RIO env ()
10821088
checkForDuplicateModules pkgs =
10831089
unless (null duplicates) $
1090+
-- Two or more files with the same module name are treated as a warning
1091+
-- rather than an error. See:
1092+
-- https://github.com/commercialhaskell/stack/issues/5407#issuecomment-707339928
10841093
prettyWarn $
10851094
flow "Multiple files use the same module name:"
10861095
<> line
10871096
<> bulletedList (map prettyDuplicate duplicates)
10881097
<> line
1089-
-- MSS 2020-10-13 Disabling, may remove entirely in the future
1090-
-- See: https://github.com/commercialhaskell/stack/issues/5407#issuecomment-707339928
1091-
-- throwM LoadingDuplicateModules
10921098
where
10931099
duplicates ::
10941100
[(ModuleName, Map (Path Abs File) (Set (PackageName, NamedComponent)))]

0 commit comments

Comments
 (0)