809 Commits

Author SHA1 Message Date
Nikita Popov
df3a7057ab Add Name::getParts(), deprecate Name::$parts
In preparation for switching this to a plain string in
PHP-Parser 5, deprecate direct access to the property and
provide an API that will work on both versions.

(cherry picked from commit c9e5a13d68486e9fd75f9be1b4639644e54e7f4f)
2023-05-21 21:24:13 +02:00
Nikita Popov
d43edfbb31 Support CRLF newlines in pretty printer
Can be enabled using the "newlines" option.
2023-05-21 20:56:56 +02:00
Nikita Popov
ad8daa12b2 Normalize newlines in Comment::getReformattedText()
Normalize CRLF to LF in getReformattedText(). That was, if the
comment is pretty-printed, we will use proper LF newlines, rather
than inserting indentation between the CR and LF.

At the same time, this also makes it easier to emit actual CRLF
newlines with a custom pretty printer.

Fixes #599.
2023-05-21 17:38:56 +02:00
Nikita Popov
5883189d61 Fix return type of Comment::getReformattedText() 2023-05-21 15:51:27 +02:00
Nikita Popov
afe1628a72 Add support for NodeVisitor::REPLACE_WITH_NULL
Fixes #716.
2023-05-21 15:41:41 +02:00
Nikita Popov
289756d056 Gracefully handle non-contiguous arrays in Differ
Fixes #909.
2023-05-21 15:15:36 +02:00
Nikita Popov
8490c0e82d Call leaveNode() on visitors in reverse order
Node visitation is now properly nested. The call sequence will
now be

    $visitor1->enterNode($n);
    $visitor2->enterNode($n);
    $visitor2->leaveNode($n);
    $visitor1->leaveNode($n);

rather than

    $visitor1->enterNode($n);
    $visitor2->enterNode($n);
    $visitor1->leaveNode($n);
    $visitor2->leaveNode($n);

Fixes #899.
2023-05-21 12:31:15 +02:00
Nikita Popov
8bc698248d Ensure removing visitor does not leave holes 2023-05-21 12:07:21 +02:00
Nikita Popov
fb2c3ac97c Fix emulative lexer with default error handler
If no error handler is provided, explicitly create one, so we don't
end up calling handleError() on null.
2023-05-20 22:26:53 +02:00
Nikita Popov
c23976a299 Stop accepting strings as types
For types the use of a string is ambiguous -- it could be either
an Identifier or a Name. Don't guess.

Retain the implicit promotion to Identifier in places where only
Identifier is legal, e.g. various symbol names.
2023-05-20 22:13:04 +02:00
Nikita Popov
a9dad5c54e Fix type of ClassConst::$type 2023-05-20 22:01:01 +02:00
Nikita Popov
74caed6446 Fix labelCharMap for DEL character
This map is supposed to have string keys, not integer keys.
2023-05-20 21:55:53 +02:00
Nikita Popov
a5d4c1005c Remove some unused symbols 2023-05-20 21:40:55 +02:00
Nikita Popov
93731c5cfa Move constants from NodeTraverser to NodeVisitor
These are really part of the NodeVisitor API. Retain aliases for
compatibility.
2023-05-20 21:37:34 +02:00
Nikita Popov
91da19147b Support readonly anonymous classes 2023-05-20 21:17:44 +02:00
Nikita Popov
5c267f55c9 Add support for typed constants
RFC: https://wiki.php.net/rfc/typed_class_constants
2023-05-20 21:02:03 +02:00
Nikita Popov
779b6950c3 Fix coding style 2023-05-20 18:55:12 +02:00
Nikita Popov
b68fb76f14 Add makeReadonly() to param builder
(cherry picked from commit 11e2dcd96c830ee934fa7b0243f4d67d8a8821ab)
2023-05-19 22:17:50 +02:00
Cees-Jan Kiewiet
36a6dcd04e [5.x] Add constructor property promotion
By making flags on the Param builder configurable by providing make(Public|Protected|Private) methods we can promote parameters to properties from the constructor
2023-03-06 23:12:51 +01:00
Nikita Popov
bb4263ea1a Treat del as label character depending on PHP version
In formatting-preserving pretty printing, treat DEL as a label
character based on the target PHP version (the default of 7.1
implying it isn't one).

This avoids failure to round-trip an unchanged input.
2023-03-05 17:03:00 +01:00
Nikita Popov
4ce0de2d12 Use PHP 7.1 as default pretty printer target 2023-03-05 16:56:50 +01:00
Nikita Popov
a3bc900a41 Don't ltrim when preserving formatting
We shouldn't ltrim when printing a whole file, that way we will
not just fail to preserve formatting, but actually change semantics
by dropping meaningful whitespace.
2023-03-05 16:42:30 +01:00
Nikita Popov
aa721520f9 Don't generate braces for "else if"
Mentioned in #915.
2023-03-05 11:30:39 +01:00
Anthony Ferrara
64484a4979 Add PrettyPrinter interface
Closes #423.
2023-03-04 21:56:58 +01:00
Nikita Popov
a0ed229b31 Revert "Rename PrettyPrinterAbstract to PrettyPrinter"
This reverts commit 2217f14d6e039f1c0572329e6fcc99f6c17178a3.
2023-03-04 21:54:56 +01:00
Nikita Popov
698ff1ca46 Don't always omit parentheses for argument-less yield
We may need parentheses around an argument-less yield to distinguish
(yield) - $a from yield -$a and similar.

Treat argument-less yield like a prefix operator. This will print
parentheses a bit more often than is really required, because the
arity ambiguity only exists for certain operators. This seems like
a reasonably good approximation through, as it only affects
argument-less yield on the LHS of infix operators.
2023-03-04 12:06:35 +01:00
Nikita Popov
b3158e0b53 Respect namespace style for enum scalar type printing
Doesn't matter in any practical sense because such types are always
invalid, but makes sure pretty printing round-trips.
2023-03-04 11:56:59 +01:00
Nikita Popov
bbec9db626 Handle overflowing \u escape sequence 2023-03-01 22:39:15 +01:00
Nikita Popov
6649012e6c Produce error if <?= used as identifier
Due to a peculiarity of how <?= is handled, it can get treated as
an echo identifier. Make sure it isn't, to match PHP behavior.
2023-03-01 21:35:27 +01:00
Nikita Popov
2217f14d6e Rename PrettyPrinterAbstract to PrettyPrinter 2023-03-01 21:25:02 +01:00
Nikita Popov
c62dda9507 Strip trailing doc string newline before parsing escape sequences
If the doc string ends on an escaped \r, it should not get eaten
as the "last newline".
2023-03-01 21:05:55 +01:00
Nikita Popov
57d4a02659 Handle isolated \r in doc string
Doc strings have a trailing \n and these will get interpreted as
\r\n and removed from the string contents.

For nowdoc, fall back to single quote if there's a trailing \r.
For heredoc, escape all isolated \r -- unlike \n and \r\n this is
really a special character, because this is no longer relevant as
an actual newline character.
2023-02-27 22:00:49 +01:00
Nikita Popov
8e100f1e69 Handle another yield edge case
match also uses =>, so we need to make sure that a trailing yield
is wrapped in parentheses.
2023-02-27 21:36:36 +01:00
Nikita Popov
fcd5934dae Prevent merging of consecutive -/+ more thoroughly
The unary -/+ or --/++ might not be the direct child. Instead
determine this by actually printing the operand and checking
whether it starts with -/+.
2023-02-27 19:07:44 +01:00
Nikita Popov
cc34c2450c Fix logic for new operand parentheses requirement
We need to perform this check recursively.
2023-02-27 19:00:33 +01:00
Nikita Popov
cb60eda774 Support yield precedence
Since PHP 7.0 yield is a proper expression, so print it with
proper precedence. If the pretty printer is configured for
older version (non-default), then always print parentheses.

There is an interesting interaction here, in that => is resolved
in favor of yield if the yield occurs as part of an array (or
outer yield). This kind of bypasses the entire precedence hierarchy
and *only* affects yield expressions. For the sake of simplicity
this is modeled via normal LHS precedence, because this will only
add unnecessary parentheses to a handful of low precedence unary
operators. If desired, a special marker for this purpose could be
added though.
2023-02-26 22:58:53 +01:00
Nikita Popov
1cb460ae38 Handle throw precedence
Now that this is an expression, we also need to handle precedence.
2023-02-26 18:33:24 +01:00
Nikita Popov
3bd38c5b2c Properly support prefix operator precedence printing
The pretty printer is supposed to produce a minimal-parentheses
printing for expressions. However, for prefix operators, we were
failing to do so in ways that are practically meaningful, e.g.
$a = yield from $b produced redundant parentheses around the
yield from.

For prefix operators, the precedence of the direct parent operator
is not actually relevant: What matters is the precedence of any
infix operator whose LHS it appears on. For example, $a . include $b
does not require parentheses, but (include $a) . $b does.

To handle this, keep separate track of the parent operator
precedence, and a special LHS precedence which is used for unary
operator printing only. Because the LHS precedence may not come
from the direct parent, we have to pass it down the call stack.
And if we do that, we may as well do the same for the parent
precedence.

This also fixes an integration test failure with php-src, because
arrow function precedence was previously not respected (and would
be ugly to respect without this change).
2023-02-26 18:26:20 +01:00
Nikita Popov
e9416a0eae Support fixup for dynamic class const name
This is new in PHP 8.3.
2023-02-26 16:00:35 +01:00
Nikita Popov
7b4a8c1ebd Properly handle static deref LHS
The rules for static and array/object deref are slightly different:
The former does not allow constants.
2023-02-26 15:57:37 +01:00
Nikita Popov
9476cff37d Doc string end label may have leading whitespace
When detecting whether the string contains the end label, allow
leading whitespace in front of it. This is legal since the
introduction of flexible doc strings.
2023-02-26 15:21:33 +01:00
Nikita Popov
6a88bdb05a Support new variables in fixup 2023-02-26 15:17:07 +01:00
Nikita Popov
1eb6b5653e Properly handle new/instanceof operand restrictions
Fixes #912.
2023-02-26 15:11:36 +01:00
Nikita Popov
d24745ddbc Respect precedence during clone pretty printing
Clone is the prefix operator with the highest operator precedence,
but was not treated as an operator at all.
2023-02-26 14:58:17 +01:00
Nikita Popov
cd3c0c11e4 Remove __halt_compiler from semi reserved keyword list
Apparently PHP does not allow use of __halt_compiler as a
semi-reserved keyword.
2023-02-26 12:32:22 +01:00
Nikita Popov
f6ddde6428 Perform end label check on escaped string
Escaping might convert a label character into an escape sequence
if it is not valid UTF-8.
2023-02-26 12:27:05 +01:00
Nikita Popov
47626c74ec Handle interpolated variable after end label
Interpolated variables start with non-label characters, and as
such also count as end label terminators since PHP 7.3.
2023-02-26 12:20:32 +01:00
Nikita Popov
ce3337b0c2 Update allowed characters after doc string label
With the introduction of flexible doc strings, the ending label
is no longer required to be followed by a semicolon or newline.
We need to prevent doc string printing if the label is followed
by any non-label character.
2023-02-26 12:14:04 +01:00
Nikita Popov
d83562e6fe Print INF as 1.0E+1000
This makes pretty printing round trip to another Float literal,
rather than a constant lookup. The 1e1000 form in particular is
chosen because that seems to be the typical form used in various
tests.
2023-02-26 09:47:19 +01:00
Nikita Popov
2df8878f5d [PHP 8.3] Support dynamic class const fetch
RFC: https://wiki.php.net/rfc/dynamic_class_constant_fetch
2023-01-29 20:49:00 +01:00