Add isSpecialClassName() method to Identifier and Name

This commit is contained in:
Nikita Popov 2017-08-15 22:56:53 +02:00
parent d97cc3d96e
commit 7b36ca3b6c
5 changed files with 39 additions and 23 deletions

View File

@ -100,8 +100,7 @@ class NameContext {
*/
public function getResolvedName(Name $name, int $type) {
// don't resolve special class names
if ($type === Stmt\Use_::TYPE_NORMAL
&& in_array($name->toLowerString(), ['self', 'parent', 'static'])) {
if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) {
if (!$name->isUnqualified()) {
$this->errorHandler->handleError(new Error(
sprintf("'\\%s' is an invalid class name", $name->toString()),

View File

@ -12,6 +12,12 @@ class Identifier extends NodeAbstract
/** @var string Identifier as string */
public $name;
private static $specialClassNames = [
'self' => true,
'parent' => true,
'static' => true,
];
/**
* Constructs an identifier node.
*
@ -36,6 +42,15 @@ class Identifier extends NodeAbstract
return strtolower($this->name);
}
/**
* Checks whether the identifier is a special class name (self, parent or static).
*
* @return bool Whether identifier is a special class name
*/
public function isSpecialClassName() : bool {
return isset(self::$specialClassNames[strtolower($this->name)]);
}
/**
* Get identifier as string.
*

View File

@ -11,6 +11,12 @@ class Name extends NodeAbstract
*/
public $parts;
private static $specialClassNames = [
'self' => true,
'parent' => true,
'static' => true,
];
/**
* Constructs a name node.
*
@ -110,6 +116,16 @@ class Name extends NodeAbstract
return strtolower(implode('\\', $this->parts));
}
/**
* Checks whether the identifier is a special class name (self, parent or static).
*
* @return bool Whether identifier is a special class name
*/
public function isSpecialClassName() : bool {
return count($this->parts) === 1
&& isset(self::$specialClassNames[strtolower($this->parts[0])]);
}
/**
* Returns a string representation of the name by imploding the namespace parts with the
* namespace separator.

View File

@ -23,12 +23,6 @@ class Class_ extends ClassLike
/** @var Node\Name[] Names of implemented interfaces */
public $implements;
protected static $specialNames = [
'self' => true,
'parent' => true,
'static' => true,
];
/**
* Constructs a class node.
*

View File

@ -654,12 +654,6 @@ abstract class ParserAbstract implements Parser
return new Node\Identifier($lowerName, $name->getAttributes());
}
protected static $specialNames = [
'self' => true,
'parent' => true,
'static' => true,
];
/**
* Get combined start and end attributes at a stack location
*
@ -730,7 +724,7 @@ abstract class ParserAbstract implements Parser
}
protected function checkNamespace(Namespace_ $node) {
if ($node->name && isset(self::$specialNames[$node->name->toLowerString()])) {
if ($node->name && $node->name->isSpecialClassName()) {
$this->emitError(new Error(
sprintf('Cannot use \'%s\' as namespace name', $node->name),
$node->name->getAttributes()
@ -749,14 +743,14 @@ abstract class ParserAbstract implements Parser
}
protected function checkClass(Class_ $node, $namePos) {
if (null !== $node->name && isset(self::$specialNames[$node->name->toLowerString()])) {
if (null !== $node->name && $node->name->isSpecialClassName()) {
$this->emitError(new Error(
sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name),
$this->getAttributesAt($namePos)
));
}
if ($node->extends && isset(self::$specialNames[$node->extends->toLowerString()])) {
if ($node->extends && $node->extends->isSpecialClassName()) {
$this->emitError(new Error(
sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends),
$node->extends->getAttributes()
@ -764,7 +758,7 @@ abstract class ParserAbstract implements Parser
}
foreach ($node->implements as $interface) {
if (isset(self::$specialNames[$interface->toLowerString()])) {
if ($interface->isSpecialClassName()) {
$this->emitError(new Error(
sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface),
$interface->getAttributes()
@ -774,7 +768,7 @@ abstract class ParserAbstract implements Parser
}
protected function checkInterface(Interface_ $node, $namePos) {
if (null !== $node->name && isset(self::$specialNames[$node->name->toLowerString()])) {
if (null !== $node->name && $node->name->isSpecialClassName()) {
$this->emitError(new Error(
sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name),
$this->getAttributesAt($namePos)
@ -782,7 +776,7 @@ abstract class ParserAbstract implements Parser
}
foreach ($node->extends as $interface) {
if (isset(self::$specialNames[$interface->toLowerString()])) {
if ($interface->isSpecialClassName()) {
$this->emitError(new Error(
sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface),
$interface->getAttributes()
@ -844,9 +838,7 @@ abstract class ParserAbstract implements Parser
}
protected function checkUseUse(UseUse $node, $namePos) {
if ($node->alias &&
('self' === $node->alias->toLowerString() || 'parent' === $node->alias->toLowerString())
) {
if ($node->alias && $node->alias->isSpecialClassName()) {
$this->emitError(new Error(
sprintf(
'Cannot use %s as %s because \'%2$s\' is a special class name',