Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 156 additions & 1 deletion src/ddmd/errors.d
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,15 @@ extern (C++) void verrorPrint(const ref Loc loc, COLOR headerColor, const(char)*
fprintf(stderr, "%s ", p2);
OutBuffer tmp;
tmp.vprintf(format, ap);
fprintf(stderr, "%s\n", tmp.peekString());

if (global.params.color && strchr(tmp.peekString(), '`'))
{
colorSyntaxHighlight(&tmp);
writeHighlights(&tmp);
resetConsoleColor();
}
else
fprintf(stderr, "%s\n", tmp.peekString());
fflush(stderr);
}

Expand Down Expand Up @@ -309,3 +317,150 @@ extern (C++) void halt()
{
assert(0);
}

/**********************************************
* Scan characters in `buf`. Assume text enclosed by `...`
* is D source code, and color syntax highlight it.
* Modify contents of `buf` with highlighted result.
* Many parallels to ddoc.highlightText().
* Params:
* buf = text containing `...` code to highlight
*/
private void colorSyntaxHighlight(OutBuffer* buf)
{
//printf("colorSyntaxHighlight('%.*s')\n", buf.offset, buf.data);
bool inBacktick = false;
size_t iCodeStart = 0;
size_t offset = 0;
for (size_t i = offset; i < buf.offset; ++i)
{
char c = buf.data[i];
switch (c)
{
case '`':
if (inBacktick)
{
inBacktick = false;
OutBuffer codebuf;
codebuf.write(buf.peekSlice().ptr + iCodeStart + 1, i - (iCodeStart + 1));
codebuf.writeByte(0);
// escape the contents, but do not perform highlighting except for DDOC_PSYMBOL
colorHighlightCode(&codebuf);
buf.remove(iCodeStart, i - iCodeStart + 1); // also trimming off the current `
immutable pre = "";
i = buf.insert(iCodeStart, pre);
i = buf.insert(i, codebuf.peekSlice());
i--; // point to the ending ) so when the for loop does i++, it will see the next character
break;
}
inBacktick = true;
iCodeStart = i;
break;

default:
break;
}
}
}


/****************************
* Embed these highlighting commands in the text stream.
* HIGHLIGHT.Escape indicats a COLOR follows.
*/
enum HIGHLIGHT : ubyte
{
Default = COLOR_BLACK, // back to whatever the console is set at
Escape = '\xFF', // highlight COLOR follows
Identifier = COLOR_MAGENTA,
Keyword = COLOR_BLUE,
String = COLOR_RED,
Comment = COLOR_CYAN,
Other = COLOR_GREEN, // other tokens
}

/**************************************************
* Highlight code for CODE section.
* Rewrite the contents of `buf` with embedded highlights.
* Analogous to doc.highlightCode2()
*/

private void colorHighlightCode(OutBuffer* buf)
{
import ddmd.lexer;
import ddmd.tokens;

uint errorsave = global.errors;
scope Lexer lex = new Lexer(null, cast(char*)buf.data, 0, buf.offset - 1, 0, 0);
OutBuffer res;
const(char)* lastp = cast(char*)buf.data;
//printf("colorHighlightCode('%.*s')\n", buf.offset - 1, buf.data);
res.reserve(buf.offset);
res.writeByte(HIGHLIGHT.Escape);
res.writeByte(HIGHLIGHT.Other);
while (1)
{
Token tok;
lex.scan(&tok);
res.writestring(lastp[0 .. tok.ptr - lastp]);
HIGHLIGHT highlight;
switch (tok.value)
{
case TOKidentifier:
highlight = HIGHLIGHT.Identifier;
break;
case TOKcomment:
highlight = HIGHLIGHT.Comment;
break;
case TOKstring:
highlight = HIGHLIGHT.String;
break;
default:
if (tok.isKeyword())
highlight = HIGHLIGHT.Keyword;
break;
}
if (highlight != HIGHLIGHT.Default)
{
res.writeByte(HIGHLIGHT.Escape);
res.writeByte(highlight);
res.writestring(tok.ptr[0 .. lex.p - tok.ptr]);
res.writeByte(HIGHLIGHT.Escape);
res.writeByte(HIGHLIGHT.Other);
}
else
res.writestring(tok.ptr[0 .. lex.p - tok.ptr]);
if (tok.value == TOKeof)
break;
lastp = lex.p;
}
res.writeByte(HIGHLIGHT.Escape);
res.writeByte(HIGHLIGHT.Default);
//printf("res = '%.*s'\n", buf.offset, buf.data);
buf.setsize(0);
buf.write(&res);
global.errors = errorsave;
}

/*************************************
* Write the buffer contents with embedded highights to stderr.
* Params:
* buf = highlighted text
*/
private void writeHighlights(const OutBuffer *buf)
{
for (size_t i = 0; i < buf.offset; ++i)
{
const c = buf.data[i];
if (c == HIGHLIGHT.Escape)
{
const color = buf.data[++i];
if (color == HIGHLIGHT.Default)
resetConsoleColor();
else
setConsoleColor(cast(COLOR)color, true);
}
else
fputc(c, stderr);
}
}
2 changes: 1 addition & 1 deletion src/ddmd/sideeffect.d
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ extern (C++) bool discardValue(Expression e)
default:
break;
}
e.error("%s has no effect in expression (%s)", Token.toChars(e.op), e.toChars());
e.error("`%s` has no effect in expression `%s`", Token.toChars(e.op), e.toChars());
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail11.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail11.d(12): Error: type has no effect in expression (int*)
fail_compilation/fail11.d(12): Error: `type` has no effect in expression `int*`
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail12390.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail12390.d(14): Error: == has no effect in expression (fun().i == 4)
fail_compilation/fail12390.d(14): Error: `==` has no effect in expression `fun().i == 4`
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/fail136.d
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail136.d(10): Error: string has no effect in expression ("\xef\xbb\xbf")
fail_compilation/fail136.d(10): Error: `string` has no effect in expression `"\xef\xbb\xbf"`
---
*/

Expand Down
20 changes: 10 additions & 10 deletions test/fail_compilation/fail14089.d
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail14089.d(41): Error: long has no effect in expression (1)
fail_compilation/fail14089.d(41): Error: long has no effect in expression (1)
fail_compilation/fail14089.d(42): Error: long has no effect in expression (1)
fail_compilation/fail14089.d(42): Error: var has no effect in expression (n)
fail_compilation/fail14089.d(43): Error: long has no effect in expression (1)
fail_compilation/fail14089.d(43): Error: dotvar has no effect in expression (s.val)
fail_compilation/fail14089.d(44): Error: var has no effect in expression (n)
fail_compilation/fail14089.d(44): Error: long has no effect in expression (1)
fail_compilation/fail14089.d(45): Error: dotvar has no effect in expression (s.val)
fail_compilation/fail14089.d(45): Error: long has no effect in expression (1)
fail_compilation/fail14089.d(41): Error: `long` has no effect in expression `1`
fail_compilation/fail14089.d(41): Error: `long` has no effect in expression `1`
fail_compilation/fail14089.d(42): Error: `long` has no effect in expression `1`
fail_compilation/fail14089.d(42): Error: `var` has no effect in expression `n`
fail_compilation/fail14089.d(43): Error: `long` has no effect in expression `1`
fail_compilation/fail14089.d(43): Error: `dotvar` has no effect in expression `s.val`
fail_compilation/fail14089.d(44): Error: `var` has no effect in expression `n`
fail_compilation/fail14089.d(44): Error: `long` has no effect in expression `1`
fail_compilation/fail14089.d(45): Error: `dotvar` has no effect in expression `s.val`
fail_compilation/fail14089.d(45): Error: `long` has no effect in expression `1`
---
*/

Expand Down
2 changes: 1 addition & 1 deletion test/fail_compilation/ice14424.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice14424.d(12): Error: tuple has no effect in expression (tuple(__unittestL3_$n$))
fail_compilation/ice14424.d(12): Error: `tuple` has no effect in expression `tuple(__unittestL3_$n$)`
---
*/

Expand Down