Skip to content

Commit 8489364

Browse files
committed
Update changelog and upgrading guide
1 parent 0d0accf commit 8489364

File tree

2 files changed

+143
-5
lines changed

2 files changed

+143
-5
lines changed

CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,41 @@
11
Version 3.0.0-dev
22
-----------------
33

4+
This release primarily improves our support for error recovery.
5+
46
### Added
57

68
* Added `Node::setDocComment()` method.
9+
* Added `Error::getMessageWithColumnInfo()` method.
10+
* Added support for recovery from lexer errors.
11+
* Added support for recovering from "special" errors (i.e. non-syntax parse errors).
12+
* Added precise ___location information for lexer errors.
13+
* Added `ErrorHandler` interface, and `ErrorHandler\Throwing` and `ErrorHandler\Collecting` as
14+
specific implementations. These provide a general mechanism for handling error recovery.
15+
* Added optional `ErrorHandler` argument to `Parser::parse()`, `Lexer::startLexing()` and
16+
`NameResolver::__construct()`.
17+
* The `NameResolver` now adds a `namespacedName` attribute on name nodes that cannot be statically
18+
resolved (unqualified unaliased function or constant names in namespaces).
19+
20+
### Fixed
21+
22+
* Fixed attribute assignment for `GroupUse` prefix and variables in interpolated strings.
23+
24+
### Changed
25+
26+
* The constants on `NameTraverserInterface` have been moved into the `NameTraverser` class.
27+
* Due to the error handling changes, the `Parser` interface and `Lexer` API have changed.
28+
* The emulative lexer now directly postprocesses tokens, instead of using `~__EMU__~` sequences.
29+
This changes the protected API of the lexer.
30+
31+
### Removed
32+
33+
* Removed `Error::getRawLine()` and `Error::setRawLine()`. These methods have been superseded by
34+
`Error::getStartLine()` and `Error::setStartLine()`.
35+
* Removed support for node cloning in the `NodeTraverser`.
36+
* Removed `$separator` argument from `Name::toString()`.
37+
* Removed `throw_on_error` parser option and `Parser::getErrors()` method. Use the `ErrorHandler`
38+
mechanism instead.
739

840
Version 3.0.0-beta1 (2016-09-16)
941
--------------------------------

UPGRADE-3.0.md

Lines changed: 111 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
Upgrading from PHP-Parser 2.x to 3.0
22
====================================
33

4-
This version does not include any major API changes. Only specific details of the node
5-
representation have changed in some cases.
4+
The backwards-incompatible changes in this release may be summarized as follows:
5+
6+
* The specific details of the node representation have changed in some cases, primarily to
7+
accomodate new PHP 7.1 features.
8+
* There have been significant changes to the error recovery implementation. This may affect you,
9+
if you used the error recovery mode or have a custom lexer implementation.
10+
* A number of deprecated methods were removed.
611

712
### PHP version requirements
813

@@ -31,18 +36,119 @@ The following changes are unlikely to require code changes:
3136
* `void` and `iterable` types are now stored as strings if the PHP 7 parser is used. Previously
3237
these would have been represented as `Name` instances.
3338

34-
### Removed methods
39+
### Changes to error recovery mode
40+
41+
Previously, error recovery mode was enabled by setting the `throwOnError` option to `false` when
42+
creating the parser, while collected errors were retrieved using the `getErrors()` method:
43+
44+
```php
45+
$lexer = ...;
46+
$parser = (new ParserFactory)->create(ParserFactor::ONLY_PHP7, $lexer, [
47+
'throwOnError' => true,
48+
]);
49+
50+
$stmts = $parser->parse($code);
51+
$errors = $parser->getErrors();
52+
if ($errors) {
53+
handleErrors($errors);
54+
}
55+
processAst($stmts);
56+
```
57+
58+
Both the `throwOnError` option and the `getErrors()` method have been removed in PHP-Parser 3.0.
59+
Instead an instance of `ErrorHandler\Collecting` should be passed to the `parse()` method:
60+
61+
```php
62+
$lexer = ...;
63+
$parser = (new ParserFactory)->create(ParserFactor::ONLY_PHP7, $lexer);
64+
65+
$errorHandler = new ErrorHandler\Collecting;
66+
$stmts = $parser->parse($code, $errorHandler);
67+
if ($errorHandler->hasErrors()) {
68+
handleErrors($errorHandler->getErrors());
69+
}
70+
processAst($stmts);
71+
```
72+
73+
#### Multiple parser fallback in error recovery mode
74+
75+
As a result of this change, if a `Multiple` parser is used (e.g. through the `ParserFactory` using
76+
`PREFER_PHP7` or `PREFER_PHP5`), it will now return the result of the first *non-throwing* parse. As
77+
parsing never throws in error recovery mode, the result from the first parser will always be
78+
returned.
79+
80+
The PHP 7 parser is a superset of the PHP 5 parser, with the exceptions that `=& new` and
81+
`global $$foo->bar` are not supported (other differences are in representation only). The PHP 7
82+
parser will be able to recover from the error in both cases. For this reason, this change will
83+
likely pass unnoticed if you do not specifically test for this syntax.
84+
85+
It is possible to restore the precise previous behavior with the following code:
86+
87+
```php
88+
$lexer = ...;
89+
$parser7 = new Parser\Php7($lexer);
90+
$parser5 = new Parser\Php5($lexer);
91+
92+
$errors7 = new ErrorHandler\Collecting();
93+
$stmts7 = $parser7->parse($code, $errors7);
94+
if ($errors7->hasErrors()) {
95+
$errors5 = new ErrorHandler\Collecting();
96+
$stmts5 = $parser5->parse($code, $errors5);
97+
if (!$errors5->hasErrors()) {
98+
// If PHP 7 parse has errors but PHP 5 parse has no errors, use PHP 5 result
99+
return [$stmts5, $errors5];
100+
}
101+
}
102+
// If PHP 7 succeeds or both fail use PHP 7 result
103+
return [$stmts7, $errors7];
104+
```
105+
106+
#### Error handling in the lexer
107+
108+
In order to support recovery from lexer errors, the signature of the `startLexing()` method changed
109+
to optionally accept an `ErrorHandler`:
110+
111+
```php
112+
// OLD
113+
public function startLexing($code);
114+
// NEW
115+
public function startLexing($code, ErrorHandler $errorHandler = null);
116+
```
117+
118+
If you use a custom lexer with overriden `startLexing()` method, it needs to be changed to accept
119+
the extra parameter. The value should be passed on to the parent method.
120+
121+
#### Error checks in node constructors
122+
123+
The constructors of certain nodes used to contain additional checks for semantic errors, such as
124+
creating a try block without either catch or finally. These checks have been moved from the node
125+
constructors into the parser. This allows recovery from such errors, as well as representing the
126+
resulting (invalid) AST.
127+
128+
This means that certain error conditions are no longer checked for manually constructed nodes.
129+
130+
### Removed methods, arguments, options
35131

36-
The following methods have been removed:
132+
The following methods, arguments or options have been removed:
37133

38134
* `Comment::setLine()`, `Comment::setText()`: Create new `Comment` instances instead.
39135
* `Name::set()`, `Name::setFirst()`, `Name::setLast()`: Create new `Name` instances instead. For
40136
the latter two a combination of `Name::concat()` and `Name::slice()` can be used.
137+
* `Error::getRawLine()`, `Error::setRawLine()`. Use `Error::getStartLine()` and
138+
`Error::setStartLine()` instead.
139+
* `Parser::getErrors()`. Use `ErrorHandler\Collecting` instead.
140+
* `$separator` argument of `Name::toString()`. Use `strtr()` instead, if you really need it.
141+
* `$cloneNodes` argument of `NodeTraverser::__construct()`. Explicitly clone nodes in the visitor
142+
instead.
143+
* `throwOnError` parser option. Use `ErrorHandler\Collecting` instead.
41144

42145
### Miscellaneous
43146

44147
* All methods on `PrettyPrinter\Standard` are now protected. Previoulsy most of them were public.
45148
The pretty printer should only be invoked using the `prettyPrint()`, `prettyPrintFile()` and
46149
`prettyPrintExpr()` methods.
47150
* The node dumper now prints numeric values that act as enums/flags in a string representation.
48-
If node dumper results are used in tests, updates may be needed to account for this.
151+
If node dumper results are used in tests, updates may be needed to account for this.
152+
* The constants on `NameTraverserInterface` have been moved into the `NameTraverser` class.
153+
* The emulative lexer now directly postprocesses tokens, instead of using `~__EMU__~` sequences.
154+
This changes the protected API of the emulative lexer.

0 commit comments

Comments
 (0)