Skip to content

Commit

Permalink
[PHP 8.3] Support dynamic class const fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic committed Jul 30, 2023
1 parent 05e84f7 commit cfc54e3
Show file tree
Hide file tree
Showing 8 changed files with 480 additions and 417 deletions.
2 changes: 2 additions & 0 deletions grammar/php7.y
Expand Up @@ -1046,6 +1046,8 @@ constant:
class_constant:
class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier_maybe_reserved
{ $$ = Expr\ClassConstFetch[$1, $3]; }
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}'
{ $$ = Expr\ClassConstFetch[$1, $4]; }
/* We interpret an isolated FOO:: as an unfinished class constant fetch. It could also be
an unfinished static property fetch or unfinished scoped call. */
| class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error
Expand Down
6 changes: 3 additions & 3 deletions lib/PhpParser/BuilderFactory.php
Expand Up @@ -349,15 +349,15 @@ public function propertyFetch(Expr $var, $name) : Expr\PropertyFetch {
/**
* Creates a class constant fetch node.
*
* @param string|Name|Expr $class Class name
* @param string|Identifier $name Constant name
* @param string|Name|Expr $class Class name
* @param string|Identifier|Expr $name Constant name
*
* @return Expr\ClassConstFetch
*/
public function classConstFetch($class, $name): Expr\ClassConstFetch {
return new Expr\ClassConstFetch(
BuilderHelpers::normalizeNameOrExpr($class),
BuilderHelpers::normalizeIdentifier($name)
BuilderHelpers::normalizeIdentifierOrExpr($name)
);
}

Expand Down
10 changes: 5 additions & 5 deletions lib/PhpParser/Node/Expr/ClassConstFetch.php
Expand Up @@ -10,15 +10,15 @@ class ClassConstFetch extends Expr
{
/** @var Name|Expr Class name */
public $class;
/** @var Identifier|Error Constant name */
/** @var Identifier|Expr|Error Constant name */
public $name;

/**
* Constructs a class const fetch node.
*
* @param Name|Expr $class Class name
* @param string|Identifier|Error $name Constant name
* @param array $attributes Additional attributes
* @param Name|Expr $class Class name
* @param string|Identifier|Expr|Error $name Constant name
* @param array $attributes Additional attributes
*/
public function __construct($class, $name, array $attributes = []) {
$this->attributes = $attributes;
Expand All @@ -29,7 +29,7 @@ public function __construct($class, $name, array $attributes = []) {
public function getSubNodeNames() : array {
return ['class', 'name'];
}

public function getType() : string {
return 'Expr_ClassConstFetch';
}
Expand Down
819 changes: 412 additions & 407 deletions lib/PhpParser/Parser/Php7.php

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/PhpParser/PrettyPrinter/Standard.php
Expand Up @@ -606,7 +606,7 @@ protected function pExpr_ConstFetch(Expr\ConstFetch $node) {
}

protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) {
return $this->pDereferenceLhs($node->class) . '::' . $this->p($node->name);
return $this->pDereferenceLhs($node->class) . '::' . $this->pObjectProperty($node->name);
}

protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) {
Expand Down
6 changes: 5 additions & 1 deletion test/PhpParser/BuilderFactoryTest.php
Expand Up @@ -210,6 +210,10 @@ public function testConstFetches() {
new Expr\ClassConstFetch(new Expr\Variable('foo'), new Identifier('BAR')),
$factory->classConstFetch(new Expr\Variable('foo'), 'BAR')
);
$this->assertEquals(
new Expr\ClassConstFetch(new Name('Foo'), new Expr\Variable('foo')),
$factory->classConstFetch('Foo', $factory->var('foo'))
);
}

public function testVar() {
Expand Down Expand Up @@ -243,7 +247,7 @@ public function testPropertyFetch() {
public function testInvalidIdentifier() {
$this->expectException(\LogicException::class);
$this->expectExceptionMessage('Expected string or instance of Node\Identifier');
(new BuilderFactory())->classConstFetch('Foo', new Expr\Variable('foo'));
(new BuilderFactory())->classConstFetch('Foo', new Name('foo'));
}

public function testInvalidIdentifierOrExpr() {
Expand Down
43 changes: 43 additions & 0 deletions test/code/parser/expr/dynamicClassConst.test
@@ -0,0 +1,43 @@
Dynamic class constant fetch
-----
<?php
Foo::{bar()};
$foo::{bar()};
-----
!!php7
array(
0: Stmt_Expression(
expr: Expr_ClassConstFetch(
class: Name(
parts: array(
0: Foo
)
)
name: Expr_FuncCall(
name: Name(
parts: array(
0: bar
)
)
args: array(
)
)
)
)
1: Stmt_Expression(
expr: Expr_ClassConstFetch(
class: Expr_Variable(
name: foo
)
name: Expr_FuncCall(
name: Name(
parts: array(
0: bar
)
)
args: array(
)
)
)
)
)
9 changes: 9 additions & 0 deletions test/code/prettyPrinter/expr/dynamicClassConstFetch.test
@@ -0,0 +1,9 @@
Dynamic class constant fetch
-----
<?php
Foo::{bar()};
$foo::{bar()};
-----
!!php7
Foo::{bar()};
$foo::{bar()};

0 comments on commit cfc54e3

Please sign in to comment.