Skip to content

Commit 4e8c4c1

Browse files
Support and test AST version 50
1 parent 5c65130 commit 4e8c4c1

File tree

9 files changed

+333
-208
lines changed

9 files changed

+333
-208
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ PHP-Parser to php-ast
33

44
[![Build Status](https://travis-ci.org/TysonAndre/php-parser-to-php-ast.svg?branch=master)](https://travis-ci.org/TysonAndre/php-parser-to-php-ast)
55

6+
This converts ASTs(Abstract Syntax Trees) from [PHP-Parser](https://github.com/nikic/PHP-Parser) to [php-ast](https://github.com/nikic/php-ast/).
7+
It can be used as a PHP-only implementation of php-ast.
8+
9+
Supported [php-ast AST versions](https://github.com/nikic/php-ast#version-changelog): 40, 50
10+
11+
Current Status
12+
--------------
13+
614
No tests are failing
715

816
- This is 90% done

composer.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
2-
"name": "tysonandre/php-parser",
3-
"description": "A php-parser to php-ast converter written in php",
2+
"name": "tysonandre/php-parser-to-php-ast",
3+
"description": "A php-parser to php-ast converter written in php. Can be used to test out projects using php-ast without compiling php-ast.",
44
"require": {
55
"php": ">=7.1",
6-
"nikic/PHP-Parser": "3.0.5"
6+
"nikic/PHP-Parser": "~3.1.0"
77
},
88
"require-dev": {
99
"phpunit/phpunit": "^5.7"
1010
},
1111
"suggest": {
12-
"ext-ast": "~0.1.4"
12+
"ext-ast": "~0.1.5"
1313
},
1414
"autoload": {
1515
"psr-4": {"ASTConverter\\": "src/ASTConverter"}

composer.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ASTConverter/ASTConverter.php

Lines changed: 250 additions & 185 deletions
Large diffs are not rendered by default.

src/util.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php declare(strict_types=1);
2+
// TODO: update for version 50 and 40
23

34
use ast\flags;
45

@@ -164,7 +165,10 @@ function format_flags(int $kind, int $flags) : string {
164165
return (string) $flags;
165166
}
166167

167-
/** Dumps abstract syntax tree */
168+
/**
169+
* Dumps abstract syntax tree
170+
* @suppress PhanUndeclaredProperty fixme
171+
*/
168172
function ast_dump($ast, int $options = 0) : string {
169173
if ($ast instanceof ast\Node) {
170174
$result = ast\get_kind_name($ast->kind);
@@ -179,13 +183,20 @@ function ast_dump($ast, int $options = 0) : string {
179183
if (ast\kind_uses_flags($ast->kind)) {
180184
$result .= "\n flags: " . format_flags($ast->kind, $ast->flags);
181185
}
182-
if (isset($ast->name)) {
183-
$result .= "\n name: $ast->name";
186+
$name = $ast->name ?? $ast->children['name'] ?? null;
187+
if (is_string($name)) {
188+
$result .= "\n name: $name";
184189
}
185-
if (isset($ast->docComment)) {
186-
$result .= "\n docComment: $ast->docComment";
190+
$docComment = $ast->docComment ?? $ast->children['docComment'] ?? null;
191+
if ($docComment !== null) {
192+
$result .= "\n docComment: $docComment";
187193
}
188194
foreach ($ast->children as $i => $child) {
195+
if ($i === 'name' && $child === $name) {
196+
continue;
197+
} else if ($i === 'docComment' && $child === $docComment) {
198+
continue;
199+
}
189200
$result .= "\n $i: " . str_replace("\n", "\n ", ast_dump($child, $options));
190201
}
191202
return $result;

test_files/src/stmt_list.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
while ($a) { $b; }
55

66
declare(ticks=1);
7+
/** Doc comment on decl */
78
declare(ticks=1) {}

test_files/src/type_hints.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
<?php
2-
function test(A $a, array $b, callable $c, INT $d, Float $e, string $f, bool $g, iterable $h) : void { }
2+
function test(A $a, array $b, callable $c, INT $d, Float $e, string $f, bool $g, iterable $h, object $j) : void { }

tests/ASTConverter/ConversionTest.php

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,38 @@ function($filename) {
2222
return array_values($files);
2323
}
2424

25+
/**
26+
* @return bool
27+
*/
28+
public static function hasNativeASTSupport(int $astVersion) {
29+
try {
30+
$x = \ast\parse_code('', $astVersion);
31+
return true;
32+
} catch (\LogicException $e) {
33+
return false;
34+
}
35+
}
36+
37+
/**
38+
* @return string[]|int[] [string $filePath, int $astVersion]
39+
*/
2540
public function astValidFileExampleProvider() {
2641
$tests = [];
2742
$sourceDir = dirname(dirname(realpath(__DIR__))) . '/test_files/src';
2843
$files = $this->_scanSourceDirForPHP($sourceDir);
44+
$supports40 = self::hasNativeASTSupport(40);
45+
$supports50 = self::hasNativeASTSupport(50);
46+
if (!($supports40 || $supports50)) {
47+
throw new RuntimeException("Neither AST version 40 nor 50 are natively supported");
48+
}
2949
foreach ($files as $file) {
30-
$tests[] = [$sourceDir . '/' . $file];
50+
$path = $sourceDir . '/' . $file;
51+
if ($supports40) {
52+
$tests[] = [$path, 40];
53+
}
54+
if ($supports50) {
55+
$tests[] = [$path, 50];
56+
}
3157
}
3258
return $tests;
3359
}
@@ -52,15 +78,15 @@ private static function normalizeOriginalAST($node) {
5278
}
5379

5480
/** @dataProvider astValidFileExampleProvider */
55-
public function testFallbackFromParser(string $fileName) {
81+
public function testFallbackFromParser(string $fileName, int $astVersion) {
5682
$contents = file_get_contents($fileName);
5783
if ($contents === false) {
5884
$this->fail("Failed to read $fileName");
5985
}
60-
$ast = \ast\parse_code($contents, ASTConverter::AST_VERSION);
86+
$ast = \ast\parse_code($contents, $astVersion);
6187
self::normalizeOriginalAST($ast);
6288
$this->assertInstanceOf('\ast\Node', $ast, 'Examples must be syntactically valid PHP parseable by php-ast');
63-
$fallback_ast = \ASTConverter\ASTConverter::ast_parse_code_fallback($contents, ASTConverter::AST_VERSION);
89+
$fallback_ast = \ASTConverter\ASTConverter::ast_parse_code_fallback($contents, $astVersion);
6490
$this->assertInstanceOf('\ast\Node', $fallback_ast, 'The fallback must also return a tree of php-ast nodes');
6591
$fallbackASTRepr = var_export($fallback_ast, true);
6692
$originalASTRepr = var_export($ast, true);

tests/ASTConverter/ErrorTolerantConversionTest.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,25 @@ function foo() {
177177
}
178178

179179
private function _testFallbackFromParser(string $incompleteContents, string $validContents) {
180-
$ast = \ast\parse_code($validContents, ASTConverter::AST_VERSION);
180+
$supports40 = ConversionTest::hasNativeASTSupport(40);
181+
$supports50 = ConversionTest::hasNativeASTSupport(50);
182+
if (!($supports40 || $supports50)) {
183+
$this->fail('No supported AST versions to test');
184+
}
185+
if ($supports40) {
186+
$this->_testFallbackFromParserForASTVersion($incompleteContents, $validContents, 40);
187+
}
188+
if ($supports50) {
189+
$this->_testFallbackFromParserForASTVersion($incompleteContents, $validContents, 50);
190+
}
191+
}
192+
193+
private function _testFallbackFromParserForASTVersion(string $incompleteContents, string $validContents, int $astVersion) {
194+
$ast = \ast\parse_code($validContents, $astVersion);
181195
$this->assertInstanceOf('\ast\Node', $ast, 'Examples(for validContents) must be syntactically valid PHP parseable by php-ast');
182196
$errors = [];
183197
$phpParserNode = ASTConverter::phpparser_parse($incompleteContents, true, $errors);
184-
$fallback_ast = ASTConverter::phpparser_to_phpast($phpParserNode, ASTConverter::AST_VERSION);
198+
$fallback_ast = ASTConverter::phpparser_to_phpast($phpParserNode, $astVersion);
185199
$this->assertInstanceOf('\ast\Node', $fallback_ast, 'The fallback must also return a tree of php-ast nodes');
186200
$fallbackASTRepr = var_export($fallback_ast, true);
187201
$originalASTRepr = var_export($ast, true);
@@ -197,7 +211,7 @@ private function _testFallbackFromParser(string $incompleteContents, string $val
197211
} catch (\PhpParser\Error $e) {
198212
}
199213
$original_ast_dump = \ast_dump($ast);
200-
$parser_export = var_export($phpParserNode, true);
214+
// $parser_export = var_export($phpParserNode, true);
201215
$this->assertSame($originalASTRepr, $fallbackASTRepr, <<<EOT
202216
The fallback must return the same tree of php-ast nodes
203217
Code:

0 commit comments

Comments
 (0)