Skip to content

Commit f548cef

Browse files
committed
Error messages: Tweak how parse errors from parsec parser are displayed
* Error messages are indented by 2 spaces * 0:0 positions are never shown * More attempts are made to remove extra newlines.
1 parent 86c7153 commit f548cef

File tree

9 files changed

+149
-133
lines changed

9 files changed

+149
-133
lines changed

cabal-install/src/Distribution/Client/Errors/Parser.hs

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ renderInstalledPackageInfoSourceMsgs PInstalledPackageInfo (errors, warnings) =
154154

155155
renderParseErrorNoFile :: String -> [PError] -> [PWarning] -> String
156156
renderParseErrorNoFile herald errors warnings =
157-
renderParseErrorGeneral herald "" Nothing (const []) errors warnings
157+
renderParseErrorGeneral herald Nothing Nothing (const []) errors warnings
158158

159159
-- | Render a parse error which resulted from a file on disk
160160
renderParseErrorFile
@@ -169,7 +169,7 @@ renderParseErrorFile
169169
-> ([PError], [PWarning])
170170
-> String
171171
renderParseErrorFile herald filepath provenance contents (errors, warnings) =
172-
renderParseErrorGeneral (herald <> " file " <> filepath) (filepath' <> ":") provenance formatInput errors warnings
172+
renderParseErrorGeneral (herald <> " file " <> filepath) (Just (filepath' <> ":")) provenance formatInput errors warnings
173173
where
174174
filepath' = normalise filepath
175175

@@ -217,20 +217,25 @@ renderParseErrorFile herald filepath provenance contents (errors, warnings) =
217217
-- | A generic rendering function which can render from many sources.
218218
renderParseErrorGeneral
219219
:: String
220-
-> String
220+
-- ^ What we were parsing when the error occurred.
221+
-> Maybe String
222+
-- ^ A simpler/shorter header to display when displaying each error (normally a filepath)
221223
-> Maybe String
224+
-- ^ Provenance, used to print additional context about what file failed (used to print the import path of a project
225+
-- file which failed to parse)
222226
-> (Position -> [String])
223227
-- ^ Extra information to render based on the position
224228
-> [PError]
225229
-> [PWarning]
226230
-> String
227231
renderParseErrorGeneral header err_header provenance extra_info errors warnings =
228232
unlines $
229-
[ warningsOrErrors <> " encountered when parsing" <> header' <> ":"
233+
[ warningsOrErrors <> " parsing" <> header' <> ":"
230234
]
231235
++ [p | Just p <- [provenance]]
232-
++ renderedErrors
233-
++ renderedWarnings
236+
++ [""] -- Place a newline between the header and the errors/warnings
237+
-- Place a newline between each error and warning
238+
++ intersperse "" (renderedWarnings ++ renderedErrors)
234239
where
235240
warningsOrErrors = case errors of
236241
[] -> case warnings of
@@ -241,24 +246,36 @@ renderParseErrorGeneral header err_header provenance extra_info errors warnings
241246

242247
header' = if null header then "" else (" " <> header)
243248

244-
renderedErrors = concatMap renderError (sortBy (comparing perrorPosition) errors)
245-
renderedWarnings = concatMap renderWarning (sortBy (comparing pwarningPosition) warnings)
249+
renderedErrors = map renderError (sortBy (comparing perrorPosition) errors)
250+
renderedWarnings = map renderWarning (sortBy (comparing pwarningPosition) warnings)
246251

247-
renderError :: PError -> [String]
248-
renderError (PError pos msg)
252+
renderErrorOrWarning :: String -> Position -> String -> String
253+
renderErrorOrWarning err_type pos msg
249254
-- if position is 0:0, then it doesn't make sense to show input
250255
-- looks like, Parsec errors have line-feed in them
251-
| pos == zeroPos = msgs
252-
| otherwise = msgs ++ extra_info pos
253-
where
254-
msgs = ["", err_header ++ showPos pos ++ ": error:", trimLF msg, ""]
255-
256-
renderWarning :: PWarning -> [String]
257-
renderWarning (PWarning _ pos msg)
258-
| pos == zeroPos = msgs
259-
| otherwise = msgs ++ extra_info pos
256+
| pos == zeroPos = unlines (herald : map indent user_msg)
257+
| otherwise = unlines (herald : map indent (user_msg ++ extra_info pos))
260258
where
261-
msgs = ["", err_header ++ showPos pos ++ ": warning:", trimLF msg, ""]
259+
herald = renderErrorHerald pos ++ err_type ++ ":"
260+
user_msg = lines (trimLF msg)
261+
262+
indent :: String -> String
263+
indent s = replicate 2 ' ' ++ s
264+
265+
-- Don't render the 0:0 position
266+
renderErrorHerald :: Position -> String
267+
renderErrorHerald pos =
268+
case (err_header, pos == zeroPos) of
269+
(Nothing, True) -> ""
270+
(Nothing, False) -> showPos pos ++ ": "
271+
(Just herald, True) -> herald ++ " "
272+
(Just herald, False) -> herald ++ showPos pos ++ ": "
273+
274+
renderError :: PError -> String
275+
renderError (PError pos msg) = renderErrorOrWarning "error" pos msg
276+
277+
renderWarning :: PWarning -> String
278+
renderWarning (PWarning _ pos msg) = renderErrorOrWarning "warning" pos msg
262279

263280
-- sometimes there are (especially trailing) newlines.
264281
trimLF :: String -> String

cabal-install/src/Distribution/Client/ProjectFlags.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@ defaultProjectFlags =
5959
{ flagProjectDir = mempty
6060
, flagProjectFile = mempty
6161
, flagIgnoreProject = toFlag False
62-
, -- Should we use 'Last' here?
63-
flagProjectFileParser = mempty
62+
, flagProjectFileParser = mempty
6463
}
6564

6665
projectFlagsOptions :: ShowOrParseArgs -> [OptionField ProjectFlags]
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# cabal check
22
Error: [Cabal-7035]
3-
Error encountered when parsing cabal file pkg.cabal:
3+
Error parsing cabal file pkg.cabal:
44

5-
pkg.cabal:0:0: error:
6-
"name" field missing
5+
pkg.cabal: error:
6+
"name" field missing
77

88

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# cabal check
22
Error: [Cabal-7035]
3-
Error encountered when parsing cabal file pkg.cabal:
3+
Error parsing cabal file pkg.cabal:
44

5-
pkg.cabal:0:0: error:
6-
"version" field missing
5+
pkg.cabal: error:
6+
"version" field missing
77

88

cabal-testsuite/PackageTests/ConditionalAndImport/cabal.out

Lines changed: 73 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -13,98 +13,98 @@ Warning: The directory <ROOT>/cabal.dist/home/.cabal/store/ghc-<GHCVER>/incoming
1313
# checking cyclical loopback of a project importing itself
1414
# cabal v2-build
1515
Error: [Cabal-7167]
16-
Error encountered when parsing project file cyclical-0-self.project:
16+
Error parsing project file cyclical-0-self.project:
1717

1818
cyclical-0-self.project:3:1: error:
19-
cyclical import of cyclical-0-self.project;
20-
cyclical-0-self.project
21-
imported by: cyclical-0-self.project
19+
cyclical import of cyclical-0-self.project;
20+
cyclical-0-self.project
21+
imported by: cyclical-0-self.project
22+
1 | packages: .
23+
2 |
24+
3 | import: cyclical-0-self.project
25+
| ^
2226

23-
1 | packages: .
24-
2 |
25-
3 | import: cyclical-0-self.project
26-
| ^
2727

2828
# checking cyclical with hops; out and back
2929
# cabal v2-build
3030
Error: [Cabal-7167]
31-
Error encountered when parsing project file cyclical-1-out-back.config:
31+
Error parsing project file cyclical-1-out-back.config:
3232
imported by: cyclical-1-out-back.project
3333

3434
cyclical-1-out-back.config:1:1: error:
35-
cyclical import of cyclical-1-out-back.project;
36-
cyclical-1-out-back.project
37-
imported by: cyclical-1-out-back.config
38-
imported by: cyclical-1-out-back.project
35+
cyclical import of cyclical-1-out-back.project;
36+
cyclical-1-out-back.project
37+
imported by: cyclical-1-out-back.config
38+
imported by: cyclical-1-out-back.project
39+
1 | import: cyclical-1-out-back.project
40+
| ^
3941

40-
1 | import: cyclical-1-out-back.project
41-
| ^
4242

4343
# checking cyclical with hops; out to a config that imports itself
4444
# cabal v2-build
4545
Error: [Cabal-7167]
46-
Error encountered when parsing project file cyclical-1-out-self.config:
46+
Error parsing project file cyclical-1-out-self.config:
4747
imported by: cyclical-1-out-self.project
4848

4949
cyclical-1-out-self.config:1:1: error:
50-
cyclical import of cyclical-1-out-self.config;
51-
cyclical-1-out-self.config
52-
imported by: cyclical-1-out-self.config
53-
imported by: cyclical-1-out-self.project
50+
cyclical import of cyclical-1-out-self.config;
51+
cyclical-1-out-self.config
52+
imported by: cyclical-1-out-self.config
53+
imported by: cyclical-1-out-self.project
54+
1 | import: cyclical-1-out-self.config
55+
| ^
5456

55-
1 | import: cyclical-1-out-self.config
56-
| ^
5757

5858
# checking cyclical with hops; out, out, twice back
5959
# cabal v2-build
6060
Error: [Cabal-7167]
61-
Error encountered when parsing project file cyclical-2-out-out-backback-b.config:
61+
Error parsing project file cyclical-2-out-out-backback-b.config:
6262
imported by: cyclical-2-out-out-backback-a.config
6363
imported by: cyclical-2-out-out-backback.project
6464

6565
cyclical-2-out-out-backback-b.config:1:1: error:
66-
cyclical import of cyclical-2-out-out-backback.project;
67-
cyclical-2-out-out-backback.project
68-
imported by: cyclical-2-out-out-backback-b.config
69-
imported by: cyclical-2-out-out-backback-a.config
70-
imported by: cyclical-2-out-out-backback.project
66+
cyclical import of cyclical-2-out-out-backback.project;
67+
cyclical-2-out-out-backback.project
68+
imported by: cyclical-2-out-out-backback-b.config
69+
imported by: cyclical-2-out-out-backback-a.config
70+
imported by: cyclical-2-out-out-backback.project
71+
1 | import: cyclical-2-out-out-backback.project
72+
| ^
7173

72-
1 | import: cyclical-2-out-out-backback.project
73-
| ^
7474

7575
# checking cyclical with hops; out, out, once back
7676
# cabal v2-build
7777
Error: [Cabal-7167]
78-
Error encountered when parsing project file cyclical-2-out-out-back-b.config:
78+
Error parsing project file cyclical-2-out-out-back-b.config:
7979
imported by: cyclical-2-out-out-back-a.config
8080
imported by: cyclical-2-out-out-back.project
8181

8282
cyclical-2-out-out-back-b.config:1:1: error:
83-
cyclical import of cyclical-2-out-out-back-a.config;
84-
cyclical-2-out-out-back-a.config
85-
imported by: cyclical-2-out-out-back-b.config
86-
imported by: cyclical-2-out-out-back-a.config
87-
imported by: cyclical-2-out-out-back.project
83+
cyclical import of cyclical-2-out-out-back-a.config;
84+
cyclical-2-out-out-back-a.config
85+
imported by: cyclical-2-out-out-back-b.config
86+
imported by: cyclical-2-out-out-back-a.config
87+
imported by: cyclical-2-out-out-back.project
88+
1 | import: cyclical-2-out-out-back-a.config
89+
| ^
8890

89-
1 | import: cyclical-2-out-out-back-a.config
90-
| ^
9191

9292
# checking cyclical with hops; out, out to a config that imports itself
9393
# cabal v2-build
9494
Error: [Cabal-7167]
95-
Error encountered when parsing project file cyclical-2-out-out-self-b.config:
95+
Error parsing project file cyclical-2-out-out-self-b.config:
9696
imported by: cyclical-2-out-out-self-a.config
9797
imported by: cyclical-2-out-out-self.project
9898

9999
cyclical-2-out-out-self-b.config:1:1: error:
100-
cyclical import of cyclical-2-out-out-self-b.config;
101-
cyclical-2-out-out-self-b.config
102-
imported by: cyclical-2-out-out-self-b.config
103-
imported by: cyclical-2-out-out-self-a.config
104-
imported by: cyclical-2-out-out-self.project
100+
cyclical import of cyclical-2-out-out-self-b.config;
101+
cyclical-2-out-out-self-b.config
102+
imported by: cyclical-2-out-out-self-b.config
103+
imported by: cyclical-2-out-out-self-a.config
104+
imported by: cyclical-2-out-out-self.project
105+
1 | import: cyclical-2-out-out-self-b.config
106+
| ^
105107

106-
1 | import: cyclical-2-out-out-self-b.config
107-
| ^
108108

109109
# checking that cyclical check doesn't false-positive on same file names in different folders; hoping within a folder and then into a subfolder
110110
# cabal v2-build
@@ -121,53 +121,53 @@ Up to date
121121
# checking that cyclical check catches a same file name that imports itself
122122
# cabal v2-build
123123
Error: [Cabal-7167]
124-
Error encountered when parsing project file same-filename/cyclical-same-filename-out-out-self.config:
124+
Error parsing project file same-filename/cyclical-same-filename-out-out-self.config:
125125
imported by: cyclical-same-filename-out-out-self.config
126126
imported by: cyclical-same-filename-out-out-self.project
127127

128128
same-filename/cyclical-same-filename-out-out-self.config:1:1: error:
129-
cyclical import of same-filename/cyclical-same-filename-out-out-self.config;
130-
same-filename/cyclical-same-filename-out-out-self.config
131-
imported by: same-filename/cyclical-same-filename-out-out-self.config
132-
imported by: cyclical-same-filename-out-out-self.config
133-
imported by: cyclical-same-filename-out-out-self.project
129+
cyclical import of same-filename/cyclical-same-filename-out-out-self.config;
130+
same-filename/cyclical-same-filename-out-out-self.config
131+
imported by: same-filename/cyclical-same-filename-out-out-self.config
132+
imported by: cyclical-same-filename-out-out-self.config
133+
imported by: cyclical-same-filename-out-out-self.project
134+
1 | import: cyclical-same-filename-out-out-self.config
135+
| ^
134136

135-
1 | import: cyclical-same-filename-out-out-self.config
136-
| ^
137137

138138
# checking that cyclical check catches importing its importer (with the same file name)
139139
# cabal v2-build
140140
Error: [Cabal-7167]
141-
Error encountered when parsing project file same-filename/cyclical-same-filename-out-out-backback.config:
141+
Error parsing project file same-filename/cyclical-same-filename-out-out-backback.config:
142142
imported by: cyclical-same-filename-out-out-backback.config
143143
imported by: cyclical-same-filename-out-out-backback.project
144144

145145
same-filename/cyclical-same-filename-out-out-backback.config:1:1: error:
146-
cyclical import of cyclical-same-filename-out-out-backback.project;
147-
cyclical-same-filename-out-out-backback.project
148-
imported by: same-filename/cyclical-same-filename-out-out-backback.config
149-
imported by: cyclical-same-filename-out-out-backback.config
150-
imported by: cyclical-same-filename-out-out-backback.project
146+
cyclical import of cyclical-same-filename-out-out-backback.project;
147+
cyclical-same-filename-out-out-backback.project
148+
imported by: same-filename/cyclical-same-filename-out-out-backback.config
149+
imported by: cyclical-same-filename-out-out-backback.config
150+
imported by: cyclical-same-filename-out-out-backback.project
151+
1 | import: ../cyclical-same-filename-out-out-backback.project
152+
| ^
151153

152-
1 | import: ../cyclical-same-filename-out-out-backback.project
153-
| ^
154154

155155
# checking that cyclical check catches importing its importer's importer (hopping over same file names)
156156
# cabal v2-build
157157
Error: [Cabal-7167]
158-
Error encountered when parsing project file same-filename/cyclical-same-filename-out-out-back.config:
158+
Error parsing project file same-filename/cyclical-same-filename-out-out-back.config:
159159
imported by: cyclical-same-filename-out-out-back.config
160160
imported by: cyclical-same-filename-out-out-back.project
161161

162162
same-filename/cyclical-same-filename-out-out-back.config:1:1: error:
163-
cyclical import of cyclical-same-filename-out-out-back.config;
164-
cyclical-same-filename-out-out-back.config
165-
imported by: same-filename/cyclical-same-filename-out-out-back.config
166-
imported by: cyclical-same-filename-out-out-back.config
167-
imported by: cyclical-same-filename-out-out-back.project
163+
cyclical import of cyclical-same-filename-out-out-back.config;
164+
cyclical-same-filename-out-out-back.config
165+
imported by: same-filename/cyclical-same-filename-out-out-back.config
166+
imported by: cyclical-same-filename-out-out-back.config
167+
imported by: cyclical-same-filename-out-out-back.project
168+
1 | import: ../cyclical-same-filename-out-out-back.config
169+
| ^
168170

169-
1 | import: ../cyclical-same-filename-out-out-back.config
170-
| ^
171171

172172
# checking that imports work skipping into a subfolder and then back out again and again
173173
# cabal v2-build
@@ -200,10 +200,10 @@ Up to date
200200
# checking bad conditional
201201
# cabal v2-build
202202
Error: [Cabal-7167]
203-
Error encountered when parsing project file bad-conditional.project:
203+
Error parsing project file bad-conditional.project:
204204

205-
bad-conditional.project:0:0: error:
206-
Cannot set compiler in a conditional clause of a cabal project file
205+
bad-conditional.project: error:
206+
Cannot set compiler in a conditional clause of a cabal project file
207207

208208

209209
# checking that missing package message lists configuration provenance

0 commit comments

Comments
 (0)