From 96429b867586afe45ff05629d4ac7b7093dd419f Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 10:03:56 -0800 Subject: [PATCH 1/9] gen_stub: merge `ConstOrClassConstName` interface into `AbstractConstName` Interface is only directly implemented by the abstract class, no need to have a separate interface. --- build/gen_stub.php | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index aef737b37e526..8567e8de0331e 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -859,19 +859,15 @@ public function __toString(): string; public function getDeclarationName(): string; } -interface ConstOrClassConstName extends VariableLikeName { - public function equals(ConstOrClassConstName $const): bool; - public function isClassConst(): bool; - public function isUnknown(): bool; -} - -abstract class AbstractConstName implements ConstOrClassConstName +abstract class AbstractConstName implements VariableLikeName { - public function equals(ConstOrClassConstName $const): bool + public function equals(AbstractConstName $const): bool { return $this->__toString() === $const->__toString(); } + abstract public function isClassConst(): bool; + public function isUnknown(): bool { return strtolower($this->__toString()) === "unknown"; @@ -2464,7 +2460,7 @@ protected function addFlagForVersionsAbove(array $flags, string $flag, int $mini class ConstInfo extends VariableLike { - public /* readonly */ ConstOrClassConstName $name; + public /* readonly */ AbstractConstName $name; public /* readonly */ Expr $value; public bool $isDeprecated; public ?string $valueString; @@ -2477,7 +2473,7 @@ class ConstInfo extends VariableLike * @var AttributeInfo[] $attributes */ public function __construct( - ConstOrClassConstName $name, + AbstractConstName $name, int $flags, Expr $value, ?string $valueString, @@ -4439,7 +4435,7 @@ function parseFunctionLike( */ function parseConstLike( PrettyPrinterAbstract $prettyPrinter, - ConstOrClassConstName $name, + AbstractConstName $name, Node\Const_ $const, int $flags, ?Node $type, From c416682f61ee31cd2d4b1f48455afdde6aaf8800 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 10:43:16 -0800 Subject: [PATCH 2/9] gen_stub: combine identical condition blocks --- build/gen_stub.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 8567e8de0331e..df939de2c9eb4 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -1424,9 +1424,7 @@ public function getFunctionEntry(): string { if (!$php84MinimumCompatibility) { $code .= "#else\n"; - } - if (!$php84MinimumCompatibility) { $flags = array_slice($flagsByPhpVersions, 0, 4, true); $template = "\tZEND_RAW_FENTRY($zendName, $name, $argInfoName, %s)\n"; $flagsCode = generateVersionDependentFlagCode( @@ -1435,9 +1433,7 @@ public function getFunctionEntry(): string { $this->minimumPhpVersionIdCompatibility ); $code .= implode("", $flagsCode); - } - if (!$php84MinimumCompatibility) { $code .= "#endif\n"; } } From cc1f119729b5914f152542275ed64e61b5039f65 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 10:56:42 -0800 Subject: [PATCH 3/9] gen_stub: document more readonly class properties --- build/gen_stub.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index df939de2c9eb4..98d3b112288f2 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2459,11 +2459,11 @@ class ConstInfo extends VariableLike public /* readonly */ AbstractConstName $name; public /* readonly */ Expr $value; public bool $isDeprecated; - public ?string $valueString; + public /* readonly */ ?string $valueString; public /* readonly */ ?string $cond; - public ?string $cValue; - public bool $isUndocumentable; - public bool $isFileCacheAllowed; + public /* readonly */ ?string $cValue; + public /* readonly */ bool $isUndocumentable; + public /* readonly */ bool $isFileCacheAllowed; /** * @var AttributeInfo[] $attributes @@ -3248,7 +3248,7 @@ class ClassInfo { public /* readonly */ array $enumCaseInfos; public /* readonly */ ?string $cond; public ?int $phpVersionIdMinimumCompatibility; - public bool $isUndocumentable; + public /* readonly */ bool $isUndocumentable; /** * @param AttributeInfo[] $attributes From dae63fb5b9bef367402c07a0a06657c05119dd9c Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 10:58:29 -0800 Subject: [PATCH 4/9] gen_stub: add visibility to class constants Make everything public for now --- build/gen_stub.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 98d3b112288f2..95d3628cfb5d5 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -770,9 +770,9 @@ public function toTypeMask(): string { } class ArgInfo { - const SEND_BY_VAL = "0"; - const SEND_BY_REF = "1"; - const SEND_PREFER_REF = "ZEND_SEND_PREFER_REF"; + public const SEND_BY_VAL = "0"; + public const SEND_BY_REF = "1"; + public const SEND_PREFER_REF = "ZEND_SEND_PREFER_REF"; public /* readonly */ string $name; public /* readonly */ string $sendBy; @@ -1086,11 +1086,11 @@ public function isDestructor(): bool { } class ReturnInfo { - const REFCOUNT_0 = "0"; - const REFCOUNT_1 = "1"; - const REFCOUNT_N = "N"; + public const REFCOUNT_0 = "0"; + public const REFCOUNT_1 = "1"; + public const REFCOUNT_N = "N"; - const REFCOUNTS_NONSCALAR = [ + public const REFCOUNTS_NONSCALAR = [ self::REFCOUNT_1, self::REFCOUNT_N, ]; From aed092db1fdfbbf17b6296edfc9ecc6e5d7cba8f Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 11:02:31 -0800 Subject: [PATCH 5/9] gen_stub: convert `parseFramelessFunctionInfo()` to a constructor Also mark `FramelessFunctionInfo::$arity` readonly --- build/gen_stub.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index 95d3628cfb5d5..a849f2c49076a 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4222,15 +4222,14 @@ function parseDocComment(DocComment $comment): array { } class FramelessFunctionInfo { - public int $arity; -} + public /* readonly */ int $arity; + + public function __construct(string $json) { + // FIXME: Should have some validation + $json = json_decode($json, true); -function parseFramelessFunctionInfo(string $json): FramelessFunctionInfo { - // FIXME: Should have some validation - $json = json_decode($json, true); - $framelessFunctionInfo = new FramelessFunctionInfo(); - $framelessFunctionInfo->arity = $json["arity"]; - return $framelessFunctionInfo; + $this->arity = $json["arity"]; + } } function parseFunctionLike( @@ -4314,7 +4313,7 @@ function parseFunctionLike( break; case 'frameless-function': - $framelessFunctionInfos[] = parseFramelessFunctionInfo($tag->getValue()); + $framelessFunctionInfos[] = new FramelessFunctionInfo($tag->getValue()); break; } } From 6714a974a4ed405324915f89fd735b6c17820a65 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 11:20:04 -0800 Subject: [PATCH 6/9] gen_stub: clean up some variable declarations Inline single-use variables, remove unneeded forward declarations --- build/gen_stub.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index a849f2c49076a..aba25ba767073 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4583,14 +4583,12 @@ function parseClass( ?int $minimumPhpVersionIdCompatibility, bool $isUndocumentable ): ClassInfo { - $flags = $class instanceof Class_ ? $class->flags : 0; $comments = $class->getComments(); $alias = null; $isDeprecated = false; $isStrictProperties = false; $isNotSerializable = false; $allowsDynamicProperties = false; - $attributes = []; if ($comments) { $tags = parseDocComments($comments); @@ -4651,7 +4649,7 @@ function parseClass( return new ClassInfo( $name, - $flags, + $class instanceof Class_ ? $class->flags : 0, $classKind, $alias, $class instanceof Enum_ && $class->scalarType !== null @@ -4895,8 +4893,7 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac } function parseStubFile(string $code): FileInfo { - $lexer = new PhpParser\Lexer\Emulative(); - $parser = new PhpParser\Parser\Php7($lexer); + $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer\Emulative()); $nodeTraverser = new PhpParser\NodeTraverser; $nodeTraverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); $prettyPrinter = new class extends Standard { @@ -5162,8 +5159,7 @@ static function (FuncInfo $funcInfo) use (&$generatedFuncInfos, $fileInfo) { $framelessFunctionCode = generateCodeWithConditions( $fileInfo->getAllFuncInfos(), "\n", static function (FuncInfo $funcInfo) { - $code = $funcInfo->getFramelessDeclaration($funcInfo); - return $code; + return $funcInfo->getFramelessDeclaration($funcInfo); } ); From 9b6f5757eab5f41bcc5fe391219179108840349d Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 11:26:04 -0800 Subject: [PATCH 7/9] gen_stub: whitespace and readability improvements Remove blank lines at the start of functions, ensure there are spaces between parameters, split a long function call across multiple lines --- build/gen_stub.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index aba25ba767073..db1403c4845fe 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -3073,7 +3073,7 @@ private function getString(string $propName): array { $include = array_merge($include, self::PHP_81_KNOWN); break; } - if (array_key_exists($propName,$include)) { + if (array_key_exists($propName, $include)) { $knownStr = $include[$propName]; return [ '', @@ -3568,7 +3568,6 @@ public function discardInfoForOldPhpVersions(?int $phpVersionIdMinimumCompatibil * @param iterable $allConstInfo */ public function getClassSynopsisDocument(array $classMap, array $allConstInfos): ?string { - $doc = new DOMDocument(); $doc->formatOutput = true; $classSynopsis = $this->getClassSynopsisElement($doc, $classMap, $allConstInfos); @@ -3586,7 +3585,6 @@ public function getClassSynopsisDocument(array $classMap, array $allConstInfos): * @param array $allConstInfos */ public function getClassSynopsisElement(DOMDocument $doc, array $classMap, array $allConstInfos): ?DOMElement { - $classSynopsis = $doc->createElement("classsynopsis"); $classSynopsis->setAttribute("class", $this->type === "interface" ? "interface" : "class"); @@ -4872,7 +4870,15 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac } $fileInfo->classInfos[] = parseClass( - $className, $stmt, $constInfos, $propertyInfos, $methodInfos, $enumCaseInfos, $cond, $fileInfo->getMinimumPhpVersionIdCompatibility(), $fileInfo->isUndocumentable + $className, + $stmt, + $constInfos, + $propertyInfos, + $methodInfos, + $enumCaseInfos, + $cond, + $fileInfo->getMinimumPhpVersionIdCompatibility(), + $fileInfo->isUndocumentable ); continue; } @@ -5018,7 +5024,7 @@ function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { } else { $code .= sprintf( "\tZEND_%s_OBJ_INFO%s(%s, %s, %s, %d%s)\n", - $argKind,$argDefaultKind, $argInfo->sendBy, $argInfo->name, + $argKind, $argDefaultKind, $argInfo->sendBy, $argInfo->name, $simpleArgType->toEscapedName(), $argType->isNullable(), $argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" ); @@ -5360,7 +5366,6 @@ function generatePropertyAttributeInitialization( /** @param array $funcMap */ function generateOptimizerInfo(array $funcMap): string { - $code = "/* This is a generated file, edit the .stub.php files instead. */\n\n"; $code .= "static const func_info_t func_infos[] = {\n"; From 6a9e63fc1515105ddfd971c2193dfd6cf53f2904 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 11:30:03 -0800 Subject: [PATCH 8/9] gen_stub: stop cloning `AttributeInfo` objects They are immutable --- build/gen_stub.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index db1403c4845fe..a3ad9328bb85e 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2082,9 +2082,6 @@ public function __clone() $this->args[$key] = clone $argInfo; } $this->return = clone $this->return; - foreach ($this->attributes as $key => $attribute) { - $this->attributes[$key] = clone $attribute; - } foreach ($this->framelessFunctionInfos as $key => $framelessFunctionInfo) { $this->framelessFunctionInfos[$key] = clone $framelessFunctionInfo; } @@ -3137,9 +3134,6 @@ public function __clone() if ($this->type) { $this->type = clone $this->type; } - foreach ($this->attributes as $key => $attribute) { - $this->attributes[$key] = clone $attribute; - } } } @@ -3169,6 +3163,8 @@ public function getDeclaration(array $allConstInfos): string { } } +// Instances of AttributeInfo are immutable and do not need to be cloned +// when held by an object that is cloned class AttributeInfo { public /* readonly */ string $class; /** @var \PhpParser\Node\Arg[] */ @@ -3996,10 +3992,6 @@ public function __clone() foreach ($this->funcInfos as $key => $funcInfo) { $this->funcInfos[$key] = clone $funcInfo; } - - foreach ($this->attributes as $key => $attribute) { - $this->attributes[$key] = clone $attribute; - } } /** From 4caa5504b8bd46340d8b1742b90ba3c951897a51 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Tue, 4 Feb 2025 11:32:15 -0800 Subject: [PATCH 9/9] gen_stub: stop cloning `FramelessFunctionInfo` objects They are immutable --- build/gen_stub.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build/gen_stub.php b/build/gen_stub.php index a3ad9328bb85e..2289c46e222df 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -2082,9 +2082,6 @@ public function __clone() $this->args[$key] = clone $argInfo; } $this->return = clone $this->return; - foreach ($this->framelessFunctionInfos as $key => $framelessFunctionInfo) { - $this->framelessFunctionInfos[$key] = clone $framelessFunctionInfo; - } } } @@ -4211,6 +4208,8 @@ function parseDocComment(DocComment $comment): array { return $tags; } +// Instances of FramelessFunctionInfo are immutable and do not need to be cloned +// when held by an object that is cloned class FramelessFunctionInfo { public /* readonly */ int $arity;