From f46ad45b3bf06859cb74bc78bc5fa17852ffd035 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 2 Jan 2025 17:14:33 +0100 Subject: [PATCH] Update to PHP-Parser 5 --- README.md | 2 +- composer.json | 2 +- demo.php | 2 +- lib/PHPCfg/AstVisitor/NameResolver.php | 4 +- lib/PHPCfg/Parser.php | 10 ++- test/PHPCfg/AttributesTest.php | 112 +++++++++---------------- test/PHPCfg/NameResolverTest.php | 2 +- test/PHPCfg/ParserTest.php | 2 +- 8 files changed, 54 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 3d6ba04..48b74cb 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The constructed SSA form is minimal and pure (or is supposed to be). To bootstrap the parser, you need to give it a `PhpParser` instance: ```php $parser = new PHPCfg\Parser( - (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7) + (new PhpParser\ParserFactory)->createForNewestSupportedVersion() ); ``` Then, just call parse on a block of code, giving it a filename: diff --git a/composer.json b/composer.json index 2ce992d..5c63165 100755 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ ], "require": { "php": ">=7.4", - "nikic/php-parser": "^4.0", + "nikic/php-parser": "^5.0", "phpdocumentor/graphviz": "^1.0.4" }, "require-dev": { diff --git a/demo.php b/demo.php index efe9f4b..a87aead 100755 --- a/demo.php +++ b/demo.php @@ -16,7 +16,7 @@ $graphviz = false; list($fileName, $code) = getCode($argc, $argv); -$parser = new PHPCfg\Parser((new ParserFactory())->create(ParserFactory::PREFER_PHP7)); +$parser = new PHPCfg\Parser((new ParserFactory())->createForNewestSupportedVersion()); $declarations = new PHPCfg\Visitor\DeclarationFinder(); $calls = new PHPCfg\Visitor\CallFinder(); diff --git a/lib/PHPCfg/AstVisitor/NameResolver.php b/lib/PHPCfg/AstVisitor/NameResolver.php index 1dbbeab..91c7e81 100644 --- a/lib/PHPCfg/AstVisitor/NameResolver.php +++ b/lib/PHPCfg/AstVisitor/NameResolver.php @@ -69,8 +69,8 @@ function ($match) { }, $comment->getText() ), - $comment->getLine(), - $comment->getFilePos() + $comment->getStartLine(), + $comment->getStartFilePos() ); $node->setDocComment($comment); diff --git a/lib/PHPCfg/Parser.php b/lib/PHPCfg/Parser.php index 518ca5c..237082d 100755 --- a/lib/PHPCfg/Parser.php +++ b/lib/PHPCfg/Parser.php @@ -825,6 +825,9 @@ protected function parseExprNode($expr) if ($expr instanceof Node\Scalar) { return $this->parseScalarNode($expr); } + if ($expr instanceof Node\InterpolatedStringPart) { + return new Literal($expr->value); + } if ($expr instanceof Node\Expr\AssignOp) { $var = $this->parseExprNode($expr->var); $read = $this->readVariable($var); @@ -1524,15 +1527,14 @@ private function compileJumptableSwitch(Stmt\Switch_ $node) private function parseScalarNode(Node\Scalar $scalar) { switch ($scalar->getType()) { - case 'Scalar_Encapsed': + case 'Scalar_InterpolatedString': $op = new Op\Expr\ConcatList($this->parseExprList($scalar->parts, self::MODE_READ), $this->mapAttributes($scalar)); $this->block->children[] = $op; return $op->result; - case 'Scalar_DNumber': - case 'Scalar_LNumber': + case 'Scalar_Float': + case 'Scalar_Int': case 'Scalar_String': - case 'Scalar_EncapsedStringPart': return new Literal($scalar->value); case 'Scalar_MagicConst_Class': // TODO diff --git a/test/PHPCfg/AttributesTest.php b/test/PHPCfg/AttributesTest.php index 25b5d69..2b43a84 100755 --- a/test/PHPCfg/AttributesTest.php +++ b/test/PHPCfg/AttributesTest.php @@ -11,7 +11,6 @@ namespace PHPCfg; -use PhpParser; use PhpParser\ParserFactory; use PHPUnit\Framework\TestCase; @@ -41,7 +40,7 @@ function foo(\$a) { expr: Var#1<\$a> EOF; - $parser = new Parser((new ParserFactory())->create(ParserFactory::PREFER_PHP7), null); + $parser = new Parser((new ParserFactory())->createForNewestSupportedVersion(), null); $traverser = new Traverser(); $traverser->addVisitor(new Visitor\Simplifier()); $printer = new Printer\Text(); @@ -71,120 +70,91 @@ function foowithattribute(\$a) { } EOF; - $expected = <<< EOF + $expected = <<<'EOF' Block#1 Stmt_Function<'foo'> attribute['filename']: foo.php attribute['startLine']: 2 + attribute['startTokenPos']: 1 + attribute['startFilePos']: 6 attribute['endLine']: 4 + attribute['endTokenPos']: 15 + attribute['endFilePos']: 40 Stmt_Function<'foowithattribute'> attribute['filename']: foo.php attribute['startLine']: 6 + attribute['startTokenPos']: 17 + attribute['startFilePos']: 43 attribute['endLine']: 9 + attribute['endTokenPos']: 35 + attribute['endFilePos']: 98 attrGroup[0]: attribute['filename']: foo.php attribute['startLine']: 6 + attribute['startTokenPos']: 17 + attribute['startFilePos']: 43 attribute['endLine']: 6 + attribute['endTokenPos']: 19 + attribute['endFilePos']: 49 attr[0]: attribute['filename']: foo.php attribute['startLine']: 6 + attribute['startTokenPos']: 18 + attribute['startFilePos']: 45 attribute['endLine']: 6 + attribute['endTokenPos']: 18 + attribute['endFilePos']: 48 name: LITERAL('Attr') Terminal_Return - + Function 'foo': mixed Block#1 Expr_Param attribute['filename']: foo.php attribute['startLine']: 2 + attribute['startTokenPos']: 5 + attribute['startFilePos']: 19 attribute['endLine']: 2 + attribute['endTokenPos']: 5 + attribute['endFilePos']: 20 declaredType: mixed name: LITERAL('a') - result: Var#1<\$a> + result: Var#1<$a> Terminal_Return attribute['filename']: foo.php attribute['startLine']: 3 + attribute['startTokenPos']: 10 + attribute['startFilePos']: 29 attribute['endLine']: 3 - expr: Var#1<\$a> - + attribute['endTokenPos']: 13 + attribute['endFilePos']: 38 + expr: Var#1<$a> + Function 'foowithattribute': mixed Block#1 Expr_Param attribute['filename']: foo.php attribute['startLine']: 7 + attribute['startTokenPos']: 25 + attribute['startFilePos']: 77 attribute['endLine']: 7 + attribute['endTokenPos']: 25 + attribute['endFilePos']: 78 declaredType: mixed name: LITERAL('a') - result: Var#1<\$a> + result: Var#1<$a> Terminal_Return attribute['filename']: foo.php attribute['startLine']: 8 + attribute['startTokenPos']: 30 + attribute['startFilePos']: 87 attribute['endLine']: 8 - expr: Var#1<\$a> + attribute['endTokenPos']: 33 + attribute['endFilePos']: 96 + expr: Var#1<$a> EOF; - $parser = new Parser((new ParserFactory())->create(ParserFactory::PREFER_PHP7), null); - $traverser = new Traverser(); - $traverser->addVisitor(new Visitor\Simplifier()); - $printer = new Printer\Text(true); - - try { - $script = $parser->parse($code, 'foo.php'); - $traverser->traverse($script); - $result = $printer->printScript($script); - } catch (\RuntimeException $e) { - $result = $e->getMessage(); - } - - $this->assertEquals($this->canonicalize($expected), $this->canonicalize($result)); - } - - public function testAdditionalAttributes() - { - $code = <<< EOF - - attribute['filename']: foo.php - attribute['startLine']: 2 - attribute['startFilePos']: 6 - attribute['endLine']: 4 - attribute['endFilePos']: 40 - Terminal_Return - -Function 'foo': mixed -Block#1 - Expr_Param - attribute['filename']: foo.php - attribute['startLine']: 2 - attribute['startFilePos']: 19 - attribute['endLine']: 2 - attribute['endFilePos']: 20 - declaredType: mixed - name: LITERAL('a') - result: Var#1<\$a> - Terminal_Return - attribute['filename']: foo.php - attribute['startLine']: 3 - attribute['startFilePos']: 29 - attribute['endLine']: 3 - attribute['endFilePos']: 38 - expr: Var#1<\$a> -EOF; - - $lexer = new \PhpParser\Lexer(array( - 'usedAttributes' => array( - 'comments', 'startLine', 'endLine', 'startFilePos', 'endFilePos' - ) - )); - - $parser = new Parser((new ParserFactory())->create(ParserFactory::PREFER_PHP7, $lexer), null); + $parser = new Parser((new ParserFactory())->createForNewestSupportedVersion(), null); $traverser = new Traverser(); $traverser->addVisitor(new Visitor\Simplifier()); $printer = new Printer\Text(true); diff --git a/test/PHPCfg/NameResolverTest.php b/test/PHPCfg/NameResolverTest.php index 1895665..40a4a85 100644 --- a/test/PHPCfg/NameResolverTest.php +++ b/test/PHPCfg/NameResolverTest.php @@ -24,7 +24,7 @@ class NameResolverTest extends TestCase protected function setUp(): void { - $this->astParser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7); + $this->astParser = (new ParserFactory())->createForNewestSupportedVersion(); } /** @dataProvider getIgnoresInvalidParamTypeInDocCommentCases */ diff --git a/test/PHPCfg/ParserTest.php b/test/PHPCfg/ParserTest.php index 07f3dd6..19ddc1f 100755 --- a/test/PHPCfg/ParserTest.php +++ b/test/PHPCfg/ParserTest.php @@ -22,7 +22,7 @@ public function testParseAndDump($code, $expectedDump) { $astTraverser = new PhpParser\NodeTraverser(); $astTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver()); - $parser = new Parser((new ParserFactory())->create(ParserFactory::PREFER_PHP7), $astTraverser); + $parser = new Parser((new ParserFactory())->createForNewestSupportedVersion(), $astTraverser); $traverser = new Traverser(); $traverser->addVisitor(new Visitor\Simplifier()); $printer = new Printer\Text();