Skip to content
4 changes: 4 additions & 0 deletions doc/component/Pretty_printing.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ The pretty printer respects a number of attributes used by some nodes:
* `kind` on `Scalar\String_` to use single quotes (default), double quotes, heredoc or nowdoc.
In the latter two cases, the heredoc/nowdoc label from the `docLabel` attribute is used.
* `kind` on `Scalar\Int_` to use decimal (default), binary, octal or hexadecimal representation.
* `shouldPrintRawValue` and `rawValue` on `Scalar\Int_` to preserve the original formatting of
integer literals (e.g., numeric separators like `1_000`). When `shouldPrintRawValue` is set to
`true`, the value from `rawValue` is used instead of the computed representation. This works for
all integer formats (decimal, binary, octal, hexadecimal).
* `kind` on `Cast\Double` to use `(double)` (default), `(float)` or `(real)`.
* `kind` on `Expr\List_` to use `[]` or `list()` (default depends on `phpVersion` option).
* `kind` on `Expr\Array_` to use `[]` or `array()` (default depends on `shortArraySyntax` option).
Expand Down
5 changes: 5 additions & 0 deletions lib/PhpParser/PrettyPrinter/Standard.php
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,18 @@ protected function pScalar_InterpolatedString(Scalar\InterpolatedString $node):
}

protected function pScalar_Int(Scalar\Int_ $node): string {
if ($node->getAttribute('shouldPrintRawValue') === true) {
return $node->getAttribute('rawValue');
}

if ($node->value === -\PHP_INT_MAX - 1) {
// PHP_INT_MIN cannot be represented as a literal,
// because the sign is not part of the literal
return '(-' . \PHP_INT_MAX . '-1)';
}

$kind = $node->getAttribute('kind', Scalar\Int_::KIND_DEC);

if (Scalar\Int_::KIND_DEC === $kind) {
return (string) $node->value;
}
Expand Down
22 changes: 22 additions & 0 deletions test/PhpParser/PrettyPrinterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,28 @@ public static function provideTestUnnaturalLiterals() {
];
}

/** @dataProvider provideTestCustomRawValue */
public function printCustomRawValue($node, $expected): void {
$prettyPrinter = new PrettyPrinter\Standard();
$result = $prettyPrinter->prettyPrintExpr($node);
$this->assertSame($expected, $result);
}

public static function provideTestCustomRawValue() {
return [
// Decimal with separator
[new Int_(1000, ['rawValue' => '10_00', 'shouldPrintRawValue' => true]), '10_00'],
// Hexadecimal with separator
[new Int_(0xDEADBEEF, ['kind' => Int_::KIND_HEX, 'rawValue' => '0xDEAD_BEEF', 'shouldPrintRawValue' => true]), '0xDEAD_BEEF'],
// Binary with separator
[new Int_(0b11110000, ['kind' => Int_::KIND_BIN, 'rawValue' => '0b1111_0000', 'shouldPrintRawValue' => true]), '0b1111_0000'],
// Octal with separator
[new Int_(0755, ['kind' => Int_::KIND_OCT, 'rawValue' => '0755_000', 'shouldPrintRawValue' => true]), '0755_000'],
// Without flag set, should use default formatting
[new Int_(1000, ['rawValue' => '10_00', 'shouldPrintRawValue' => false]), '1000'],
];
}

public function testPrettyPrintWithError(): void {
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Cannot pretty-print AST with Error nodes');
Expand Down