Skip to content

Commit

Permalink
[8.4] Add support for __PROPERTY__ magic constant
Browse files Browse the repository at this point in the history
Part of property hooks RFC.
  • Loading branch information
nikic committed Jul 14, 2024
1 parent 5973c30 commit d8235a2
Show file tree
Hide file tree
Showing 14 changed files with 1,415 additions and 1,323 deletions.
2 changes: 2 additions & 0 deletions grammar/php.y
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@
%token T_TRAIT_C
%token T_METHOD_C
%token T_FUNC_C
%token T_PROPERTY_C
%token T_LINE
%token T_FILE
%token T_START_HEREDOC
Expand Down Expand Up @@ -1165,6 +1166,7 @@ constant:
| T_METHOD_C { $$ = Scalar\MagicConst\Method[]; }
| T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; }
| T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; }
| T_PROPERTY_C { $$ = Scalar\MagicConst\Property[]; }
;

class_constant:
Expand Down
6 changes: 2 additions & 4 deletions lib/PhpParser/Lexer/Emulative.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@
use PhpParser\Lexer;
use PhpParser\Lexer\TokenEmulator\AttributeEmulator;
use PhpParser\Lexer\TokenEmulator\EnumTokenEmulator;
use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
use PhpParser\Lexer\TokenEmulator\ExplicitOctalEmulator;
use PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator;
use PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
use PhpParser\Lexer\TokenEmulator\MatchTokenEmulator;
use PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator;
use PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
use PhpParser\Lexer\TokenEmulator\PropertyTokenEmulator;
use PhpParser\Lexer\TokenEmulator\ReadonlyFunctionTokenEmulator;
use PhpParser\Lexer\TokenEmulator\ReadonlyTokenEmulator;
use PhpParser\Lexer\TokenEmulator\ReverseEmulator;
Expand Down Expand Up @@ -47,6 +44,7 @@ public function __construct(?PhpVersion $phpVersion = null) {
new ReadonlyTokenEmulator(),
new ExplicitOctalEmulator(),
new ReadonlyFunctionTokenEmulator(),
new PropertyTokenEmulator(),
];

// Collect emulators that are relevant for the PHP version we're running
Expand Down
8 changes: 6 additions & 2 deletions lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ public function isEmulationNeeded(string $code): bool {

/** @param Token[] $tokens */
protected function isKeywordContext(array $tokens, int $pos): bool {
$previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $pos);
return $previousNonSpaceToken === null || $previousNonSpaceToken->id !== \T_OBJECT_OPERATOR;
$prevToken = $this->getPreviousNonSpaceToken($tokens, $pos);
if ($prevToken === null) {
return false;
}
return $prevToken->id !== \T_OBJECT_OPERATOR
&& $prevToken->id !== \T_NULLSAFE_OBJECT_OPERATOR;
}

public function emulate(string $code, array $tokens): array {
Expand Down
19 changes: 19 additions & 0 deletions lib/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php declare(strict_types=1);

namespace PhpParser\Lexer\TokenEmulator;

use PhpParser\PhpVersion;

final class PropertyTokenEmulator extends KeywordEmulator {
public function getPhpVersion(): PhpVersion {
return PhpVersion::fromComponents(8, 4);
}

public function getKeywordString(): string {
return '__property__';
}

public function getKeywordToken(): int {
return \T_PROPERTY_C;
}
}
15 changes: 15 additions & 0 deletions lib/PhpParser/Node/Scalar/MagicConst/Property.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php declare(strict_types=1);

namespace PhpParser\Node\Scalar\MagicConst;

use PhpParser\Node\Scalar\MagicConst;

class Property extends MagicConst {
public function getName(): string {
return '__PROPERTY__';
}

public function getType(): string {
return 'Scalar_MagicConst_Property';
}
}
1,325 changes: 667 additions & 658 deletions lib/PhpParser/Parser/Php7.php

Large diffs are not rendered by default.

1,327 changes: 668 additions & 659 deletions lib/PhpParser/Parser/Php8.php

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions lib/PhpParser/ParserAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,7 @@ protected function createTokenMap(): array {
$tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = static::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG;
$tokenMap[\T_ENUM] = static::T_ENUM;
$tokenMap[\T_READONLY] = static::T_READONLY;
$tokenMap[\T_PROPERTY_C] = static::T_PROPERTY_C;

// We have create a map from PHP token IDs to external symbol IDs.
// Now map them to the internal symbol ID.
Expand Down
4 changes: 4 additions & 0 deletions lib/PhpParser/PrettyPrinter/Standard.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node): string {
return '__TRAIT__';
}

protected function pScalar_MagicConst_Property(MagicConst\Property $node): string {
return '__PROPERTY__';
}

// Scalars

private function indentString(string $str): string {
Expand Down
2 changes: 2 additions & 0 deletions lib/PhpParser/compatibility_tokens.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ function defineCompatibilityTokens(): void {
'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG',
'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG',
'T_READONLY',
// PHP 8.4
'T_PROPERTY_C',
];

// PHP-Parser might be used together with another library that also emulates some or all
Expand Down
15 changes: 15 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ parameters:
count: 1
path: lib/PhpParser/Lexer/Emulative.php

-
message: "#^Constant T_PROPERTY_C not found\\.$#"
count: 1
path: lib/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php

-
message: "#^Method PhpParser\\\\NodeDumper\\:\\:__construct\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
count: 1
Expand Down Expand Up @@ -220,11 +225,21 @@ parameters:
count: 1
path: lib/PhpParser/ParserAbstract.php

-
message: "#^Access to undefined constant static\\(PhpParser\\\\ParserAbstract\\)\\:\\:T_PROPERTY_C\\.$#"
count: 1
path: lib/PhpParser/ParserAbstract.php

-
message: "#^Access to undefined constant static\\(PhpParser\\\\ParserAbstract\\)\\:\\:T_READONLY\\.$#"
count: 1
path: lib/PhpParser/ParserAbstract.php

-
message: "#^Constant T_PROPERTY_C not found\\.$#"
count: 1
path: lib/PhpParser/ParserAbstract.php

-
message: "#^Unary operation \"\\+\" on string results in an error\\.$#"
count: 1
Expand Down
7 changes: 7 additions & 0 deletions test/PhpParser/Lexer/EmulativeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public function testNoReplaceKeywordsAfterNullsafeObjectOperator(string $keyword

public static function provideTestReplaceKeywords() {
return [
// PHP 8.4
['__PROPERTY__', \T_PROPERTY_C],

// PHP 8.0
['match', \T_MATCH],

Expand Down Expand Up @@ -424,6 +427,10 @@ public static function provideTestTargetVersion() {
[\T_ENCAPSED_AND_WHITESPACE, ' baz'],
[ord('"'), '"'],
]],
['8.4', '__PROPERTY__', [[\T_PROPERTY_C, '__PROPERTY__']]],
['8.3', '__PROPERTY__', [[\T_STRING, '__PROPERTY__']]],
['8.4', '__property__', [[\T_PROPERTY_C, '__property__']]],
['8.3', '__property__', [[\T_STRING, '__property__']]],
];
}
}
5 changes: 5 additions & 0 deletions test/code/parser/scalar/magicConst.test
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ __LINE__;
__METHOD__;
__NAMESPACE__;
__TRAIT__;
__PROPERTY__;
-----
array(
0: Stmt_Expression(
Expand Down Expand Up @@ -44,4 +45,8 @@ array(
expr: Scalar_MagicConst_Trait(
)
)
8: Stmt_Expression(
expr: Scalar_MagicConst_Property(
)
)
)
2 changes: 2 additions & 0 deletions test/code/prettyPrinter/expr/literals.test
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ __CLASS__;
__TRAIT__;
__METHOD__;
__NAMESPACE__;
__PROPERTY__;

// not actually literals, but close
null;
Expand Down Expand Up @@ -94,6 +95,7 @@ __CLASS__;
__TRAIT__;
__METHOD__;
__NAMESPACE__;
__PROPERTY__;
// not actually literals, but close
null;
true;
Expand Down

0 comments on commit d8235a2

Please sign in to comment.