|
| 1 | +# Tolerant Parser Update TODO |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +This branch tracks work needed to bring the tolerant PHP parser up to date for PHP 8.3, 8.4, and 8.5 so that downstream consumers (notably Phan) can rely on it when the native `ext-ast` extension is unavailable. The fork currently matches upstream commit `457738cbe` (September 2024) and is missing several recent language features. |
| 6 | + |
| 7 | +## Current Status |
| 8 | + |
| 9 | +- PHPUnit suites `invariants` and `api` pass locally when run with `zend.assertions=1` and `assert.exception=1`. |
| 10 | +- Grammar fixtures (`tests/cases/parser*.tree/.diag`) were generated before the latest language changes; they will need regeneration once parser updates land. |
| 11 | +- Validation tests that depend on large submodules (`validation/frameworks/*`) remain skipped/not vendored. |
| 12 | + |
| 13 | +## Gaps / Work Items |
| 14 | + |
| 15 | +### PHP 8.3 |
| 16 | + |
| 17 | +Double-check tolerant against the language changes that shipped with 8.3: |
| 18 | + |
| 19 | +- **Dynamic class constant fetch** (`Foo::{expr}`): ensure tokenizer/grammar accept brace-wrapped expressions after `::`, add fixtures, and mirror php-ast node structure. **(verified via `tests/samples/dynamic_class_const.php`)** |
| 20 | +- **Typed class constants / readonly amendments**: confirm class-constant declarations propagate their type information and `readonly` constraints into tolerant AST output. |
| 21 | +- **`#[\Override]` attribute**: attributes already parse, but we should add fixtures to verify tolerant preserves them on methods. |
| 22 | +- **Arbitrary static variable initialisers**: while this is largely semantic, tolerant should accept the new grammar in function-level `static` declarations and update diagnostics if necessary. |
| 23 | + |
| 24 | +### PHP 8.4 |
| 25 | + |
| 26 | +- **Property access hooks** (`public int $count { get => ...; set { ... } }`): **(implemented)** |
| 27 | + - Tokenizer must recognise `get`/`set` (and hook modifiers) in this context. |
| 28 | + - Introduce AST nodes for hook lists/bodies that align with php-ast’s `AST_PROP_ELEM` `hooks` child. |
| 29 | + - Update diagnostics to catch invalid hook combinations. |
| 30 | + - Conversion now produces `AST_PROPERTY_HOOK`/`AST_PROPERTY_HOOK_SHORT_BODY` nodes; add regression coverage to guard against regressions. |
| 31 | +- **Asymmetric visibility v2** (`public(set) private(get) $prop;`): extend the modifier grammar, update `TokenKind`, and cover tolerant AST flag handling. |
| 32 | +- **`new Foo()->bar()` without wrapping parentheses**: confirm parser handles the reduced precedence and add regression tests. |
| 33 | +- **Property hook improvements** (hook attributes, multiple hooks per property, etc.): ensure attribute placement and hook ordering are represented correctly. |
| 34 | +- Audit additional 8.4 deprecations that change parsing (e.g. implicit nullable parameters) to ensure tolerant still emits matching diagnostics. |
| 35 | + |
| 36 | +### PHP 8.5 (in progress) |
| 37 | + |
| 38 | +Monitor RFCs merged into php-src and mirror the token/grammar changes, for example: |
| 39 | + |
| 40 | +- **Pipe operator** (`expr |> func(...)`): add new tokens, precedence rules, AST nodes, and fixtures. |
| 41 | +- **`clone with`** expressions: model the new syntax (`clone $obj with { prop: value }`) and ensure node mapping covers the initializer list. |
| 42 | +- **Final property promotion** (`final public function __construct(private final string $x) {}`): allow `final` in promoted parameters and carry flags into tolerant AST. |
| 43 | +- **Attributes on constants / extended attribute targets**: verify attributes on constants and traits are preserved. |
| 44 | +- **Extend `#[\Override]` to properties / `#[\NoDiscard]` / `#[\DelayedTargetValidation]`**: attributes already parse, but add regression coverage to ensure tolerant does not misclassify their targets. |
| 45 | +- Track any additional keywords (`with`, operator tokens, etc.) and update `TokenKind.php` / `TokenStringMaps.php` accordingly. |
| 46 | + |
| 47 | +### Diagnostics & Node Mapping |
| 48 | + |
| 49 | +- Review `TokenKind`/`TokenStringMaps` for completeness after adding new tokens. |
| 50 | +- Ensure node classes record line/column spans needed by language-server features when hooks and new constructs are present. |
| 51 | +- Verify edits still map correctly (`TextEdit`, node mapping) for newly supported syntax. |
| 52 | + |
| 53 | +### Tests & Tooling |
| 54 | + |
| 55 | +- Add focused fixtures for property hooks and any new constructs under `tests/cases/parser` (and regenerate `.tree/.diag`). |
| 56 | +- Re-enable / update tolerant PHPUnit suites once fixtures are refreshed. |
| 57 | +- Consider syncing targeted tests from Phan’s fallback suite to catch divergences early. |
| 58 | + |
| 59 | +### Integration with Phan |
| 60 | + |
| 61 | +- After implementing features, run Phan’s fallback parser tests (`./tests/run_test __FakeSelfFallbackTest`) to ensure parity. |
| 62 | +- Publish updated tags / commit references so Phan can subtree merge the changes into `third_party/phan-tolerant`. |
| 63 | + |
| 64 | +### Verification Strategy |
| 65 | + |
| 66 | +- **AST comparison**: use Phan’s `tools/dump_ast.php` (php-ast) to capture the expected AST for new syntax. For the tolerant side, run `php tools/PrintTolerantAst.php` (raw tolerant tree) in combination with Phan’s `internal/dump_fallback_ast.php` (uses the converter) to ensure both the parse tree and converted php-ast structures match expectations. |
| 67 | +- **PHP runtime selection**: on this dev machine we can run `sudo newphp 83`, `sudo newphp 84`, etc. to switch CLI versions; other environments may require Docker images, phpenv, asdf, etc. Record the PHP version used when regenerating fixtures. |
| 68 | +- **Leverage Phan fixtures**: pull feature-specific testcases (e.g. property hooks, asymmetric visibility) from `phan/tests/files/src` into tolerant’s parser tests to validate new constructs. |
| 69 | +- **Run tolerant PHPUnit suites**: keep `vendor/bin/phpunit --testsuite invariants,api` (with `zend.assertions=1`) as a fast regression check while iterating. |
| 70 | + |
| 71 | +Recommended sample inputs for AST diffs (update as new fixtures are added): |
| 72 | + |
| 73 | +| Feature | Sample file(s) | Min PHP | Native AST dump | Tolerant dump | |
| 74 | +| --- | --- | --- | --- | --- | |
| 75 | +| Dynamic class const fetch | `tests/samples/dynamic_class_const.php` | 8.3 | `php ~/phan/tools/dump_ast.php --json …` | `php tools/PrintTolerantAst.php …` + `php ~/phan/internal/dump_fallback_ast.php --php-ast …` | |
| 76 | +| Property hooks | `tests/samples/property_hooks.php` | 8.4 | (run after `sudo newphp 84`) | same as above | |
| 77 | +| Asymmetric visibility props | (add fixture) | 8.4 | … | … | |
| 78 | +| Pipe operator | `tests/samples/pipe_operator.php` | 8.5 | `php ~/phan/tools/dump_ast.php --json …` | `php tools/PrintTolerantAst.php …`, `php ~/phan/internal/dump_fallback_ast.php --php-ast …` | |
| 79 | +| `clone with` expressions | (add fixture) | 8.5 | … | … | |
| 80 | + |
| 81 | +## Next Steps |
| 82 | + |
| 83 | +1. Audit existing fixtures vs php-src 8.3/8.4 syntax to catalogue precise failures. |
| 84 | +2. Prototype grammar/tokenizer changes for property hooks and regenerate associated AST nodes. |
| 85 | +3. Update diagnostics and tolerant AST converter expectations in tandem with Phan. |
| 86 | +4. Refresh fixtures and CI to cover the new syntax. |
| 87 | +5. Coordinate subtree sync back into Phan once tests pass. |
0 commit comments