in src/_Private/CLIOutputHandler.hack [118:213]
final protected function getPrettyContext(
\Throwable $ex,
string $file,
): ?string {
if (!\file_exists($file)) {
// Possibly running in repo-authoritative mode
return null;
}
$frame = $ex->getTrace()
|> Vec\filter(
$$,
$row ==>
(($row as KeyedContainer<_, _>)['file'] ?? null) as ?string === $file,
)
|> C\last($$);
if (!$frame is KeyedContainer<_, _>) {
return null;
}
$colors = $this->terminal->supportsColors();
$c_light = $colors ? "\e[2m" : '';
$c_bold = $colors ? "\e[1m" : '';
$c_red = $colors ? "\e[31m" : '';
$c_reset = $colors ? "\e[0m" : '';
$line = $frame['line'] as int;
$line_number_width = Str\length((string)$line) + 2;
$first_line = Math\maxva(1, $line - self::CONTEXT_LINES);
$all_lines = \file_get_contents($file)
|> Str\split($$, "\n");
$context_lines = Vec\slice(
$all_lines,
$first_line - 1,
($line - $first_line),
)
|> Vec\map_with_key(
$$,
($n, $content) ==> Str\format(
'%s| %s%s%s',
Str\pad_left((string)($n + $first_line), $line_number_width, ' '),
$c_light,
$content,
$c_reset,
),
);
$blame_line = $all_lines[$line - 1];
$fun = $frame['function'] as string;
$fun_offset = Str\search($blame_line, $fun.'(');
if ($fun_offset is null && Str\contains($fun, '\\')) {
$fun = Str\split($fun, '\\') |> C\lastx($$);
$fun_offset = Str\search($blame_line, $fun.'(');
}
if (
$fun_offset is null && $frame['function'] === 'HH\\invariant_violation'
) {
$fun = 'invariant';
$fun_offset = Str\search($blame_line, 'invariant(');
}
if ($fun_offset is null) {
$context_lines[] = Str\format(
'%s%s>%s %s%s',
Str\pad_left((string)$line, $line_number_width),
$c_red,
$c_reset.$c_bold,
$blame_line,
$c_reset,
);
} else {
$context_lines[] = Str\format(
'%s%s>%s %s%s%s%s%s%s',
Str\pad_left((string)$line, $line_number_width),
$c_red,
$c_reset.$c_bold,
Str\slice($blame_line, 0, $fun_offset),
$c_red,
$fun,
$c_reset.$c_bold,
Str\slice($blame_line, $fun_offset + Str\length($fun)),
$c_reset,
);
$context_lines[] = Str\format(
'%s%s%s%s',
Str\repeat(' ', $line_number_width + $fun_offset + 2),
$c_red,
Str\repeat('^', Str\length($fun)),
$c_reset,
);
}
return $file.':'.$line."\n".Str\join($context_lines, "\n");
}