Skip to content

Commit

Permalink
Escape backticks in error messages (#20893)
Browse files Browse the repository at this point in the history
  • Loading branch information
dkorpel authored Feb 18, 2025
1 parent e082ce2 commit 0e5c41f
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 6 deletions.
3 changes: 1 addition & 2 deletions compiler/src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -1896,8 +1896,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
const sident = se.toStringz();
if (!sident.length || !Identifier.isValidIdentifier(sident))
{
error(ns.exp.loc, "expected valid identifier for C++ namespace but got `%.*s`",
cast(int)sident.length, sident.ptr);
error(ns.exp.loc, "expected valid identifier for C++ namespace but got `%s`", se.toErrMsg());
return null;
}
else
Expand Down
32 changes: 32 additions & 0 deletions compiler/src/dmd/errors.d
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,10 @@ private void verrorPrint(const(char)* format, va_list ap, ref ErrorInfo info)
writeHighlights(con, tmp);
}
else
{
unescapeBackticks(tmp);
fputs(tmp.peekChars(), stderr);
}
fputc('\n', stderr);

__gshared SourceLoc old_loc;
Expand Down Expand Up @@ -828,6 +831,7 @@ extern (C++) void halt() @safe
* is D source code, and color syntax highlight it.
* Modify contents of `buf` with highlighted result.
* Many parallels to ddoc.highlightText().
* Double backticks are replaced by a single backtick without coloring.
* Params:
* buf = text containing `...` code to highlight
*/
Expand All @@ -843,6 +847,13 @@ private void colorSyntaxHighlight(ref OutBuffer buf)
switch (c)
{
case '`':
// A double backtick means it's part of the content, don't color
if (i + 1 < buf.length && buf[i + 1] == '`')
{
buf.remove(i, 1);
continue;
}

if (inBacktick)
{
inBacktick = false;
Expand All @@ -867,6 +878,27 @@ private void colorSyntaxHighlight(ref OutBuffer buf)
}
}

/// Replace double backticks in `buf` with a single backtick
void unescapeBackticks(ref OutBuffer buf)
{
for (size_t i = 0; i + 1 < buf.length; ++i)
{
if (buf[i] == '`' && buf[i + 1] == '`')
buf.remove(i, 1);
}
}

unittest
{
OutBuffer buf;
buf.writestring("x````");
unescapeBackticks(buf);
assert(buf.extractSlice() == "x``");

buf.writestring("x````");
colorSyntaxHighlight(buf);
assert(buf.extractSlice() == "x``");
}

/**
* Embed these highlighting commands in the text stream.
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dmd/hdrgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,15 @@ const(char)* toErrMsg(const Dsymbol d)
*/
private void truncateForError(ref OutBuffer buf, size_t maxLength)
{
// Remove newlines
// Remove newlines, escape backticks ` by doubling them
for (size_t i = 0; i < buf.length; i++)
{
if (buf[i] == '\r')
buf.remove(i, 1);
if (buf[i] == '\n')
buf.peekSlice[i] = ' ';
if (buf[i] == '`')
i = buf.insert(i, "`");
}

// Strip trailing whitespace
Expand Down
6 changes: 3 additions & 3 deletions compiler/test/fail_compilation/cppmangle.d
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/*
TEST_OUTPUT:
---
fail_compilation/cppmangle.d(11): Error: expected valid identifier for C++ namespace but got ``
fail_compilation/cppmangle.d(15): Error: expected valid identifier for C++ namespace but got `0num`
fail_compilation/cppmangle.d(11): Error: expected valid identifier for C++ namespace but got `""`
fail_compilation/cppmangle.d(15): Error: expected valid identifier for C++ namespace but got `"0num"`
fail_compilation/cppmangle.d(19): Error: compile time string constant (or sequence) expected, not `2`
fail_compilation/cppmangle.d(23): Error: expected valid identifier for C++ namespace but got `invalid@namespace`
fail_compilation/cppmangle.d(23): Error: expected valid identifier for C++ namespace but got `"invalid@namespace"`
---
*/

Expand Down

0 comments on commit 0e5c41f

Please sign in to comment.