Skip to content

Commit dd50890

Browse files
committed
Generate expressive diagnostic messages
1 parent 9aaeadc commit dd50890

File tree

6 files changed

+74
-0
lines changed

6 files changed

+74
-0
lines changed

changelog/error-pretty.dd

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
dmd now supports expressive diagnostic error messages with `-verrors=pretty`
2+
3+
With the new CLI option `-verrors=pretty` dmd will now show the offending line directly in its error messages.
4+
Consider this faulty program `test.d`:
5+
6+
---
7+
void foo()
8+
{
9+
10+
a = 1;
11+
}
12+
---
13+
14+
Now run it with `-verrors=pretty`:
15+
16+
$(CONSOLE
17+
> dmd -verrors=pretty test.d
18+
ee.d(5): $(RED Error): undefined identifier a
19+
a = 1;
20+
^
21+
)

src/dmd/cli.d

+3
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,9 @@ dmd -cov -unittest myprog.d
553553
Option("verrors=spec",
554554
"show errors from speculative compiles such as __traits(compiles,...)"
555555
),
556+
Option("verrors=pretty",
557+
"Pretty-print error messages with annotation of the erroring source line"
558+
),
556559
Option("-version",
557560
"print compiler version and exit"
558561
),

src/dmd/errors.d

+30
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,36 @@ private void verrorPrint(const ref Loc loc, Color headerColor, const(char)* head
236236
else
237237
fputs(tmp.peekString(), stderr);
238238
fputc('\n', stderr);
239+
240+
if (global.params.prettyPrintErrors)
241+
{
242+
auto fp = fopen(loc.filename, "r");
243+
scope(exit) fclose(fp);
244+
245+
if (fp)
246+
{
247+
char* lineptr;
248+
ulong n = 1024;
249+
import core.sys.posix.stdio;
250+
foreach (_; 0 .. loc.linnum)
251+
{
252+
assert(getline(&lineptr, &n, fp) > 0);
253+
if (lineptr is null)
254+
goto end;
255+
}
256+
if (lineptr is null)
257+
goto end;
258+
fprintf(stderr, "%s", lineptr);
259+
260+
if (loc.charnum >= 1)
261+
foreach (_; 1 .. loc.charnum)
262+
fputc(' ', stderr);
263+
264+
fputc('^', stderr);
265+
}
266+
fputc('\n', stderr);
267+
}
268+
end:
239269
fflush(stderr); // ensure it gets written out in case of compiler aborts
240270
}
241271

src/dmd/globals.d

+1
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ struct Param
158158
*/
159159

160160
bool showGaggedErrors; // print gagged errors anyway
161+
bool prettyPrintErrors; // pretty print errors with the actual line
161162
bool manual; // open browser on compiler manual
162163
bool usage; // print usage and exit
163164
bool mcpuUsage; // print help on -mcpu switch

src/dmd/mars.d

+4
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,10 @@ private bool parseCommandLine(const ref Strings arguments, const size_t argc, re
17321732
{
17331733
params.showGaggedErrors = true;
17341734
}
1735+
else if (startsWith(p + 9, "pretty"))
1736+
{
1737+
params.prettyPrintErrors = true;
1738+
}
17351739
else
17361740
goto Lerror;
17371741
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
REQUIRED_ARGS: -verrors=pretty
3+
TEST_OUTPUT:
4+
---
5+
fail_compilation/fail_pretty_errors.d(14): Error: undefined identifier `a`
6+
a = 1;
7+
^
8+
---
9+
*/
10+
11+
void foo()
12+
{
13+
14+
a = 1;
15+
}

0 commit comments

Comments
 (0)