@ -76,24 +76,15 @@ trait DeclarationSymbolTrait
foreach ($v2->uses as $use) {
foreach ($v2->uses as $use) {
$id = $this->parseIdentifier($use->name);
$id = $this->parseIdentifier($use->name);
$type = $use->type !== Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $v2->type;
$type = $use->type !== Node\Stmt\Use_::TYPE_UNKNOWN ? $use->type : $v2->type;
$alias = $this->registerUseImportAlias($use, $type, $id);
if ($type === Node\Stmt\Use_::TYPE_FUNCTION) {
if ($type === Node\Stmt\Use_::TYPE_FUNCTION) {
$lastIndex = strrpos($id, '\\');
$this->useFunctions[$alias] = $id;
$fn = substr($id, $lastIndex + 1);
if ($use->alias) {
$this->useFunctions[$use->alias->toString()] = $id;
} else {
$this->useFunctions[$fn] = $id;
}
} elseif ($type === Node\Stmt\Use_::TYPE_CONSTANT) {
} elseif ($type === Node\Stmt\Use_::TYPE_CONSTANT) {
$lastIndex = strrpos($id, '\\');
$lastIndex = strrpos($id, '\\');
$cn = substr($id, $lastIndex + 1);
$cn = substr($id, $lastIndex + 1);
$ns = substr($id, 0, $lastIndex);
$ns = substr($id, 0, $lastIndex);
$fullName = $ns . '\\' . $cn;
$fullName = $ns . '\\' . $cn;
if ($use->alias) {
$this->useConstants[$alias] = $fullName;
$this->useConstants[$use->alias->toString()] = $fullName;
} else {
$this->useConstants[$cn] = $fullName;
}
} else {
} else {
$idLower = strtolower($id);
$idLower = strtolower($id);
if ($idLower === 'native_types') {
if ($idLower === 'native_types') {
@ -107,7 +98,7 @@ trait DeclarationSymbolTrait
// Class and namespace import aliases are case-insensitive.
// Class and namespace import aliases are case-insensitive.
// An explicit alias replaces the implicit short name; it
// An explicit alias replaces the implicit short name; it
// must not also make the target's final segment available.
// must not also make the target's final segment available.
$this->useAliases[strtolower($use-> alias->toString() )] = $id;
$this->useAliases[strtolower($alias)] = $id;
} else {
} else {
$this->useNamespaces[] = $id;
$this->useNamespaces[] = $id;
}
}
@ -116,15 +107,38 @@ trait DeclarationSymbolTrait
}
}
}
}
private function registerUseImportAlias(Node\UseItem $use, int $type, string $id): string
{
$alias = $use->getAlias()->toString();
// PHP class and function names are case-insensitive, while constant
// aliases are case-sensitive. The three import kinds have independent
// symbol tables, so the same alias may be used once in each domain.
$key = $type === Node\Stmt\Use_::TYPE_CONSTANT ? $alias : strtolower($alias);
if (isset($this->useImportAliases[$type][$key])) {
$kind = match ($type) {
Node\Stmt\Use_::TYPE_FUNCTION => 'function ',
Node\Stmt\Use_::TYPE_CONSTANT => 'const ',
default => '',
};
$this->fatalError(
$use,
"Cannot use {$kind}{$id} as {$alias} because the name is already in use",
);
}
$this->useImportAliases[$type][$key] = $id;
return $alias;
}
protected function parseGroupUse(Node\Stmt\GroupUse $node): void
protected function parseGroupUse(Node\Stmt\GroupUse $node): void
{
{
$prefix = $node->prefix;
$prefix = $node->prefix;
$uses = [];
$uses = [];
foreach ($node->uses as $use) {
foreach ($node->uses as $use) {
$fullName = Node\Name::concat($prefix, $use->name);
$fullName = Node\Name::concat($prefix, $use->name);
$uses[] = new Node\UseItem($fullName, $use->alias, $use->type);
$uses[] = new Node\UseItem($fullName, $use->alias, $use->type, $use->getAttributes() );
}
}
$syntheticUse = new Node\Stmt\Use_($uses, $node->type);
$syntheticUse = new Node\Stmt\Use_($uses, $node->type, $node->getAttributes() );
$this->parseUse($syntheticUse);
$this->parseUse($syntheticUse);
}
}