Skip to content

Commit

Permalink
BlueScreen::highlightLine() is more robust
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Sep 25, 2023
1 parent 34837fd commit f83d399
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 40 deletions.
62 changes: 30 additions & 32 deletions src/Tracy/BlueScreen/CodeHighlighter.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,34 @@ final class CodeHighlighter
*/
public static function highlightLine(string $html, int $line, int $column = 0): string
{
$source = explode("\n", "\n" . str_replace("\r\n", "\n", $html));
$html = str_replace("\r\n", "\n", $html);
$lines = explode("\n", "\n" . $html);
$startLine = max(1, min($line, count($lines) - 1) - (int) floor(self::DisplayLines * 2 / 3));
$endLine = min($startLine + self::DisplayLines - 1, count($lines) - 1);
$numWidth = strlen((string) $endLine);
$openTags = $closeTags = [];
$out = '';
$spans = 1;
$start = $i = max(1, min($line, count($source) - 1) - (int) floor(self::DisplayLines * 2 / 3));
while (--$i >= 1) { // find last highlighted block
if (preg_match('#.*(</?span[^>]*>)#', $source[$i], $m)) {
if ($m[1] !== '</span>') {
$spans++;
$out .= $m[1];
}

break;
for ($n = 1; $n <= $endLine; $n++) {
if ($n === $startLine) {
$out = implode('', $openTags);
}
if ($n === $line) {
$out .= implode('', $closeTags);
}
}

$source = array_slice($source, $start, self::DisplayLines, true);
end($source);
$numWidth = strlen((string) key($source));
preg_replace_callback('#</?(\w+)[^>]*>#', function ($m) use (&$openTags, &$closeTags) {
if ($m[0][1] === '/') {
array_pop($openTags);
array_shift($closeTags);
} else {
$openTags[] = $m[0];
array_unshift($closeTags, "</$m[1]>");
}
}, $lines[$n]);

foreach ($source as $n => $s) {
$spans += substr_count($s, '<span') - substr_count($s, '</span');
$s = str_replace(["\r", "\n"], ['', ''], $s);
preg_match_all('#<[^>]+>#', $s, $tags);
if ($n == $line) {
$s = strip_tags($s);
if ($n === $line) {
$s = strip_tags($lines[$n]);
if ($column) {
$s = preg_replace(
'#((?:&.*?;|[^&]){' . ($column - 1) . '})(&.*?;|.)#u',
Expand All @@ -53,18 +56,13 @@ public static function highlightLine(string $html, int $line, int $column = 0):
1,
);
}
$out .= sprintf(
"<span class='tracy-line-highlight'>%{$numWidth}s: %s\n</span>%s",
$n,
$s,
implode('', $tags[0]),
);
$out .= sprintf("<span class='tracy-line-highlight'>%{$numWidth}s: %s\n</span>%s", $n, $s, implode('', $openTags));
} else {
$out .= sprintf("<span class='tracy-line'>%{$numWidth}s:</span> %s\n", $n, $s);
$out .= sprintf("<span class='tracy-line'>%{$numWidth}s:</span> %s\n", $n, $lines[$n]);
}
}

$out .= str_repeat('</span>', $spans) . '</code>';
$out .= implode('', $closeTags);
return $out;
}

Expand All @@ -87,9 +85,9 @@ public static function highlightPhp(string $source, int $line, int $column = 0):
$source = preg_replace('#/\*sensitive\{\*/.*?/\*\}\*/#s', Dumper\Describer::HiddenValue, $source);
$source = explode("\n", highlight_string($source, true));
$out = $source[0]; // <code><span color=highlight.html>
$source = str_replace('<br />', "\n", $source[1]);
$out .= self::highlightLine($source, $line, $column);
$out = str_replace('&nbsp;', ' ', $out);
$tmp = str_replace('<br />', "\n", $source[1]);
$out .= self::highlightLine($tmp, $line, $column);
$out = str_replace('&nbsp;', ' ', $out) . $source[2] . @$source[3];
return "<pre class='tracy-code'><div>$out</div></pre>";
}

Expand All @@ -109,7 +107,7 @@ public static function highlightPhpCli(string $code, int $line, int $column = 0)
'tracy-line-highlight' => "1;37m\e[41",
];
$stack = ['0'];

$html = preg_replace_callback(
'#<\w+(?: (class|style)=["\'](.*?)["\'])?[^>]*>|</\w+>#',
function ($m) use ($colors, &$stack): string {
Expand Down
16 changes: 8 additions & 8 deletions tests/Tracy/expected/Debugger.exception.html.expect
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span> function </span><span style="color: #000">third</span><span style="color: #D24; font-weight: bold">(</span><span style="color: #000">$arg1</span><span style="color: #D24; font-weight: bold">)
<span class='tracy-line'>%d%:</span> {
<span class='tracy-line-highlight'>%d%: throw new Exception('The my exception', 123);
</span></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #080"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"><span class='tracy-line'>%d%:</span> }
</span><span class='tracy-line-highlight'>%d%: throw new Exception('The my exception', 123);
</span><span style="color: #D24; font-weight: bold"><span class='tracy-line'>%d%:</span> }
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span> </span><span style="color: #000">define</span><span style="color: #D24; font-weight: bold">(</span><span style="color: #080">'MY_CONST'</span><span style="color: #D24; font-weight: bold">, </span><span style="color: #000">123</span><span style="color: #D24; font-weight: bold">);
Expand Down Expand Up @@ -77,8 +77,8 @@
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span> function </span><span style="color: #000">second</span><span style="color: #D24; font-weight: bold">(</span><span style="color: #000">$arg1</span><span style="color: #D24; font-weight: bold">, </span><span style="color: #000">$arg2</span><span style="color: #D24; font-weight: bold">)
<span class='tracy-line'>%d%:</span> {
<span class='tracy-line-highlight'>%d%: third([1, 2, 3]);
</span></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"><span class='tracy-line'>%d%:</span> }
</span><span class='tracy-line-highlight'>%d%: third([1, 2, 3]);
</span><span style="color: #D24; font-weight: bold"><span class='tracy-line'>%d%:</span> }
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span> function </span><span style="color: #000">third</span><span style="color: #D24; font-weight: bold">(</span><span style="color: #000">$arg1</span><span style="color: #D24; font-weight: bold">)
Expand Down Expand Up @@ -109,8 +109,8 @@
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span> function </span><span style="color: #000">first</span><span style="color: #D24; font-weight: bold">(</span><span style="color: #000">$arg1</span><span style="color: #D24; font-weight: bold">, </span><span style="color: #000">$arg2</span><span style="color: #D24; font-weight: bold">)
<span class='tracy-line'>%d%:</span> {
<span class='tracy-line-highlight'>%d%: second(true, false);
</span></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"><span class='tracy-line'>%d%:</span> }
</span><span class='tracy-line-highlight'>%d%: second(true, false);
</span><span style="color: #D24; font-weight: bold"><span class='tracy-line'>%d%:</span> }
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span> function </span><span style="color: #000">second</span><span style="color: #D24; font-weight: bold">(</span><span style="color: #000">$arg1</span><span style="color: #D24; font-weight: bold">, </span><span style="color: #000">$arg2</span><span style="color: #D24; font-weight: bold">)
Expand Down Expand Up @@ -143,8 +143,8 @@
<span class='tracy-line'>%d%:</span>
<span class='tracy-line'>%d%:</span> </span><span style="color: #000">define</span><span style="color: #D24; font-weight: bold">(</span><span style="color: #080">'MY_CONST'</span><span style="color: #D24; font-weight: bold">, </span><span style="color: #000">123</span><span style="color: #D24; font-weight: bold">);
<span class='tracy-line'>%d%:</span> @</span><span style="color: #000">hex2bin</span><span style="color: #D24; font-weight: bold">(</span><span style="color: #080">'a'</span><span style="color: #D24; font-weight: bold">); </span><span style="color: #998; font-style: italic">// E_WARNING
<span class='tracy-line-highlight'>%d%: first(10, 'any string');
</span></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #000"></span><span style="color: #D24; font-weight: bold"></span><span style="color: #080"></span><span style="color: #D24; font-weight: bold"><span class='tracy-line'>%d%:</span> </span>
</span><span class='tracy-line-highlight'>%d%: first(10, 'any string');
</span><span style="color: #D24; font-weight: bold"><span class='tracy-line'>%d%:</span> </span>
</span></code></div></pre>

<table class="tracy-callstack-args">
Expand Down

0 comments on commit f83d399

Please sign in to comment.