}
}
-class FunctionName {
- /** @var string|null */
+interface FunctionOrMethodName {
+ public function getDeclaration(): string;
+ public function getArgInfoName(): string;
+ public function __toString(): string;
+}
+
+class FunctionName implements FunctionOrMethodName {
+ /** @var Name */
+ private $name;
+
+ public function __construct(Name $name) {
+ $this->name = $name;
+ }
+
+ public function getNamespace(): ?string {
+ if ($this->name->isQualified()) {
+ return $this->name->slice(0, -1)->toString();
+ }
+ return null;
+ }
+
+ public function getShortName(): string {
+ return $this->name->getLast();
+ }
+
+ public function getNonNamespacedName(): string {
+ if ($this->name->isQualified()) {
+ throw new Exception("Namespaced name not supported here");
+ }
+ return $this->name->toString();
+ }
+
+ public function getDeclaration(): string {
+ return "ZEND_FUNCTION({$this->name->getLast()});\n";
+ }
+
+ public function getArgInfoName(): string {
+ $underscoreName = implode('_', $this->name->parts);
+ return "arginfo_$underscoreName";
+ }
+
+ public function __toString(): string {
+ return $this->name->toString();
+ }
+}
+
+class MethodName implements FunctionOrMethodName {
+ /** @var string */
public $className;
/** @var string */
public $name;
- public function __construct(?string $className, string $name)
- {
+ public function __construct(string $className, string $name) {
$this->className = $className;
$this->name = $name;
}
- public function getDeclaration(): string
- {
- if ($this->className) {
- return "ZEND_METHOD($this->className, $this->name);\n";
- }
+ public function getDeclaration(): string {
+ return "ZEND_METHOD($this->className, $this->name);\n";
+ }
- return "ZEND_FUNCTION($this->name);\n";
+ public function getArgInfoName(): string {
+ return "arginfo_class_{$this->className}_{$this->name}";
}
- public function __toString()
- {
- return $this->className ? "$this->className::$this->name" : $this->name;
+ public function __toString(): string {
+ return "$this->className::$this->name";
}
}
}
class FuncInfo {
- /** @var FunctionName */
+ /** @var FunctionOrMethodName */
public $name;
/** @var int */
public $flags;
public $cond;
public function __construct(
- FunctionName $name,
+ FunctionOrMethodName $name,
int $flags,
?string $aliasType,
- ?FunctionName $alias,
+ ?FunctionOrMethodName $alias,
bool $isDeprecated,
array $args,
ReturnInfo $return,
}
public function getArgInfoName(): string {
- if ($this->name->className) {
- return 'arginfo_class_' . $this->name->className . '_' . $this->name->name;
- }
- return 'arginfo_' . $this->name->name;
+ return $this->name->getArgInfoName();
}
public function getDeclarationKey(): string
}
public function getFunctionEntry(): string {
- if ($this->name->className) {
+ if ($this->name instanceof MethodName) {
if ($this->alias) {
- if ($this->alias->className) {
+ if ($this->alias instanceof MethodName) {
return sprintf(
"\tZEND_MALIAS(%s, %s, %s, %s, %s)\n",
$this->alias->className, $this->name->name, $this->alias->name, $this->getArgInfoName(), $this->getFlagsAsString()
);
- } else {
+ } else if ($this->alias instanceof FunctionName) {
return sprintf(
"\tZEND_ME_MAPPING(%s, %s, %s, %s)\n",
- $this->name->name, $this->alias->name, $this->getArgInfoName(), $this->getFlagsAsString()
+ $this->name->name, $this->alias->getNonNamespacedName(),
+ $this->getArgInfoName(), $this->getFlagsAsString()
);
+ } else {
+ throw new Error("Cannot happen");
}
} else {
if ($this->flags & Class_::MODIFIER_ABSTRACT) {
$this->name->className, $this->name->name, $this->getArgInfoName(), $this->getFlagsAsString()
);
}
- } else {
+ } else if ($this->name instanceof FunctionName) {
+ $namespace = $this->name->getNamespace();
+ $shortName = $this->name->getShortName();
+
if ($this->alias && $this->isDeprecated) {
return sprintf(
"\tZEND_DEP_FALIAS(%s, %s, %s)\n",
- $this->name, $this->alias->name, $this->getArgInfoName()
+ $shortName, $this->alias->getNonNamespacedName(), $this->getArgInfoName()
);
}
if ($this->alias) {
return sprintf(
"\tZEND_FALIAS(%s, %s, %s)\n",
- $this->name, $this->alias->name, $this->getArgInfoName()
+ $shortName, $this->alias->getNonNamespacedName(), $this->getArgInfoName()
);
}
if ($this->isDeprecated) {
- return sprintf("\tZEND_DEP_FE(%s, %s)\n", $this->name, $this->getArgInfoName());
+ return sprintf("\tZEND_DEP_FE(%s, %s)\n", $shortName, $this->getArgInfoName());
}
- return sprintf("\tZEND_FE(%s, %s)\n", $this->name, $this->getArgInfoName());
+ if ($namespace) {
+ return sprintf(
+ "\tZEND_NS_FE(\"%s\", %s, %s)\n",
+ $namespace, $shortName, $this->getArgInfoName());
+ } else {
+ return sprintf("\tZEND_FE(%s, %s)\n", $shortName, $this->getArgInfoName());
+ }
+ } else {
+ throw new Error("Cannot happen");
}
}
class FileInfo {
/** @var FuncInfo[] */
- public $funcInfos;
+ public $funcInfos = [];
/** @var ClassInfo[] */
- public $classInfos;
+ public $classInfos = [];
/** @var bool */
- public $generateFunctionEntries;
-
- public function __construct(
- array $funcInfos, array $classInfos, bool $generateFunctionEntries) {
- $this->funcInfos = $funcInfos;
- $this->classInfos = $classInfos;
- $this->generateFunctionEntries = $generateFunctionEntries;
- }
+ public $generateFunctionEntries = false;
/**
* @return iterable<FuncInfo>
function parseFunctionLike(
PrettyPrinterAbstract $prettyPrinter,
- FunctionName $name,
+ FunctionOrMethodName $name,
int $flags,
Node\FunctionLike $func,
?string $cond
$aliasType = $tag->name;
$aliasParts = explode("::", $tag->getValue());
if (count($aliasParts) === 1) {
- $alias = new FunctionName(null, $aliasParts[0]);
+ $alias = new FunctionName(new Name($aliasParts[0]));
} else {
- $alias = new FunctionName($aliasParts[0], $aliasParts[1]);
+ $alias = new MethodName($aliasParts[0], $aliasParts[1]);
}
} else if ($tag->name === 'deprecated') {
$isDeprecated = true;
return null;
}
-function parseStubFile(string $code): FileInfo {
- $lexer = new PhpParser\Lexer();
- $parser = new PhpParser\Parser\Php7($lexer);
- $nodeTraverser = new PhpParser\NodeTraverser;
- $nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
- $prettyPrinter = new class extends Standard {
- protected function pName_FullyQualified(Name\FullyQualified $node) {
- return implode('\\', $node->parts);
- }
- };
-
- $stmts = $parser->parse($code);
- $nodeTraverser->traverse($stmts);
-
- $generateFunctionEntries = false;
- $fileDocComment = getFileDocComment($stmts);
- if ($fileDocComment) {
- if (strpos($fileDocComment->getText(), '@generate-function-entries') !== false) {
- $generateFunctionEntries = true;
- }
- }
-
- $funcInfos = [];
- $classInfos = [];
+function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstract $prettyPrinter) {
$conds = [];
foreach ($stmts as $stmt) {
- $cond = handlePreprocessorConditions($conds, $stmt);
if ($stmt instanceof Stmt\Nop) {
continue;
}
+ if ($stmt instanceof Stmt\Namespace_) {
+ handleStatements($fileInfo, $stmt->stmts, $prettyPrinter);
+ continue;
+ }
+
+ $cond = handlePreprocessorConditions($conds, $stmt);
if ($stmt instanceof Stmt\Function_) {
- $funcInfos[] = parseFunctionLike(
+ $fileInfo->funcInfos[] = parseFunctionLike(
$prettyPrinter,
- new FunctionName(null, $stmt->name->toString()),
+ new FunctionName($stmt->namespacedName),
0,
$stmt,
$cond
);
-
continue;
}
$methodInfos[] = parseFunctionLike(
$prettyPrinter,
- new FunctionName($className, $classStmt->name->toString()),
+ new MethodName($className, $classStmt->name->toString()),
$flags,
$classStmt,
$cond
);
}
- $classInfos[] = new ClassInfo($className, $methodInfos);
+ $fileInfo->classInfos[] = new ClassInfo($className, $methodInfos);
continue;
}
throw new Exception("Unexpected node {$stmt->getType()}");
}
+}
+
+function parseStubFile(string $code): FileInfo {
+ $lexer = new PhpParser\Lexer();
+ $parser = new PhpParser\Parser\Php7($lexer);
+ $nodeTraverser = new PhpParser\NodeTraverser;
+ $nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
+ $prettyPrinter = new class extends Standard {
+ protected function pName_FullyQualified(Name\FullyQualified $node) {
+ return implode('\\', $node->parts);
+ }
+ };
+
+ $stmts = $parser->parse($code);
+ $nodeTraverser->traverse($stmts);
+
+ $fileInfo = new FileInfo;
+ $fileDocComment = getFileDocComment($stmts);
+ if ($fileDocComment) {
+ if (strpos($fileDocComment->getText(), '@generate-function-entries') !== false) {
+ $fileInfo->generateFunctionEntries = true;
+ }
+ }
- return new FileInfo($funcInfos, $classInfos, $generateFunctionEntries);
+ handleStatements($fileInfo, $stmts, $prettyPrinter);
+ return $fileInfo;
}
function funcInfoToCode(FuncInfo $funcInfo): string {