Skip to content

Commit

Permalink
add checkClassModifier() to separate from validation of class members
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed May 15, 2022
1 parent da55227 commit 05018b8
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 3 deletions.
2 changes: 1 addition & 1 deletion grammar/php7.y
Expand Up @@ -387,7 +387,7 @@ class_entry_type:

class_modifiers:
class_modifier { $$ = $1; }
| class_modifiers class_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; }
| class_modifiers class_modifier { $this->checkClassModifier($1, $2, #2); $$ = $1 | $2; }
;

class_modifier:
Expand Down
21 changes: 21 additions & 0 deletions lib/PhpParser/Node/Stmt/Class_.php
Expand Up @@ -81,6 +81,27 @@ public function isAnonymous() : bool {
return null === $this->name;
}

/**
* @internal
*/
public static function verifyClassModifier($a, $b) {
if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) {
throw new Error('Multiple abstract modifiers are not allowed');
}

if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) {
throw new Error('Multiple final modifiers are not allowed');
}

if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) {
throw new Error('Multiple readonly modifiers are not allowed');
}

if ($a & 48 && $b & 48) {
throw new Error('Cannot use the final modifier on an abstract class');
}
}

/**
* @internal
*/
Expand Down
2 changes: 1 addition & 1 deletion lib/PhpParser/Parser/Php7.php
Expand Up @@ -1653,7 +1653,7 @@ protected function initReduceCallbacks() {
$this->semValue = $this->semStack[$stackPos-(1-1)];
},
215 => function ($stackPos) {
$this->checkModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)];
$this->checkClassModifier($this->semStack[$stackPos-(2-1)], $this->semStack[$stackPos-(2-2)], $stackPos-(2-2)); $this->semValue = $this->semStack[$stackPos-(2-1)] | $this->semStack[$stackPos-(2-2)];
},
216 => function ($stackPos) {
$this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
Expand Down
9 changes: 9 additions & 0 deletions lib/PhpParser/ParserAbstract.php
Expand Up @@ -875,6 +875,15 @@ protected function createCommentNopAttributes(array $comments) {
return $attributes;
}

protected function checkClassModifier($a, $b, $modifierPos) {
try {
Class_::verifyClassModifier($a, $b);
} catch (Error $error) {
$error->setAttributes($this->getAttributesAt($modifierPos));
$this->emitError($error);
}
}

protected function checkModifier($a, $b, $modifierPos) {
// Jumping through some hoops here because verifyModifier() is also used elsewhere
try {
Expand Down
2 changes: 1 addition & 1 deletion test/code/parser/stmt/class/modifier.test
Expand Up @@ -233,7 +233,7 @@ array(
<?php abstract final class A { }
-----
!!php7
Cannot use the final modifier on an abstract class member from 1:16 to 1:20
Cannot use the final modifier on an abstract class from 1:16 to 1:20
array(
0: Stmt_Class(
attrGroups: array(
Expand Down

0 comments on commit 05018b8

Please sign in to comment.