diff --git a/build/gen_stub.php b/build/gen_stub.php index c30c491935298..b8ca6effe5e8d 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -191,8 +191,8 @@ class Context { } class ArrayType extends SimpleType { - public Type $keyType; - public Type $valueType; + public /* readonly */ Type $keyType; + public /* readonly */ Type $valueType; public static function createGenericArray(): self { @@ -230,8 +230,8 @@ public function equals(SimpleType $other): bool { } class SimpleType { - public string $name; - public bool $isBuiltin; + public /* readonly */ string $name; + public /* readonly */ bool $isBuiltin; public static function fromNode(Node $node): SimpleType { if ($node instanceof Node\Name) { @@ -314,17 +314,17 @@ public static function fromValue($value): SimpleType case "NULL": return SimpleType::null(); case "boolean": - return SimpleType::bool(); + return new SimpleType("bool", true); case "integer": - return SimpleType::int(); + return new SimpleType("int", true); case "double": - return SimpleType::float(); + return new SimpleType("float", true); case "string": - return SimpleType::string(); + return new SimpleType("string", true); case "array": - return SimpleType::array(); + return new SimpleType("array", true); case "object": - return SimpleType::object(); + return new SimpleType("object", true); default: throw new Exception("Type \"" . gettype($value) . "\" cannot be inferred based on value"); } @@ -335,41 +335,6 @@ public static function null(): SimpleType return new SimpleType("null", true); } - public static function bool(): SimpleType - { - return new SimpleType("bool", true); - } - - public static function int(): SimpleType - { - return new SimpleType("int", true); - } - - public static function float(): SimpleType - { - return new SimpleType("float", true); - } - - public static function string(): SimpleType - { - return new SimpleType("string", true); - } - - public static function array(): SimpleType - { - return new SimpleType("array", true); - } - - public static function object(): SimpleType - { - return new SimpleType("object", true); - } - - public static function void(): SimpleType - { - return new SimpleType("void", true); - } - protected function __construct(string $name, bool $isBuiltin) { $this->name = $name; $this->isBuiltin = $isBuiltin; @@ -567,8 +532,8 @@ public function equals(SimpleType $other): bool { class Type { /** @var SimpleType[] */ - public array $types; - public bool $isIntersection; + public /* readonly */ array $types; + public /* readonly */ bool $isIntersection; public static function fromNode(Node $node): Type { if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) { @@ -669,28 +634,19 @@ public function isNullable(): bool { return false; } - public function getWithoutNull(): Type { - return new Type( - array_values( - array_filter( - $this->types, - function(SimpleType $type) { - return !$type->isNull(); - } - ) - ), - false - ); - } - public function tryToSimpleType(): ?SimpleType { - $withoutNull = $this->getWithoutNull(); + $nonNullTypes = array_filter( + $this->types, + function(SimpleType $type) { + return !$type->isNull(); + } + ); /* type has only null */ - if (count($withoutNull->types) === 0) { + if (count($nonNullTypes) === 0) { return $this->types[0]; } - if (count($withoutNull->types) === 1) { - return $withoutNull->types[0]; + if (count($nonNullTypes) === 1) { + return reset($nonNullTypes); } return null; } @@ -778,10 +734,6 @@ public static function equals(?Type $a, ?Type $b): bool { } public function __toString() { - if ($this->types === null) { - return 'mixed'; - } - $char = $this->isIntersection ? '&' : '|'; return implode($char, array_map( function ($type) { return $type->name; }, @@ -792,9 +744,9 @@ function ($type) { return $type->name; }, class ArginfoType { /** @var SimpleType[] $classTypes */ - public array $classTypes; + public /* readonly */ array $classTypes; /** @var SimpleType[] $builtinTypes */ - private array $builtinTypes; + private /* readonly */ array $builtinTypes; /** * @param SimpleType[] $classTypes @@ -826,15 +778,15 @@ public function toTypeMask(): string { } class ArgInfo { - const SEND_BY_VAL = 0; - const SEND_BY_REF = 1; - const SEND_PREFER_REF = 2; + const SEND_BY_VAL = "0"; + const SEND_BY_REF = "1"; + const SEND_PREFER_REF = "ZEND_SEND_PREFER_REF"; - public string $name; - public int $sendBy; - public bool $isVariadic; + public /* readonly */ string $name; + public /* readonly */ string $sendBy; + public /* readonly */ bool $isVariadic; public ?Type $type; - public ?Type $phpDocType; + public /* readonly */ ?Type $phpDocType; public ?string $defaultValue; /** @var AttributeInfo[] */ public array $attributes; @@ -844,7 +796,7 @@ class ArgInfo { */ public function __construct( string $name, - int $sendBy, + string $sendBy, bool $isVariadic, ?Type $type, ?Type $phpDocType, @@ -854,7 +806,8 @@ public function __construct( $this->name = $name; $this->sendBy = $sendBy; $this->isVariadic = $isVariadic; - $this->setTypes($type, $phpDocType); + $this->type = $type; + $this->phpDocType = $phpDocType; $this->defaultValue = $defaultValue; $this->attributes = $attributes; } @@ -867,18 +820,6 @@ public function equals(ArgInfo $other): bool { && $this->defaultValue === $other->defaultValue; } - public function getSendByString(): string { - switch ($this->sendBy) { - case self::SEND_BY_VAL: - return "0"; - case self::SEND_BY_REF: - return "1"; - case self::SEND_PREFER_REF: - return "ZEND_SEND_PREFER_REF"; - } - throw new Exception("Invalid sendBy value"); - } - public function getMethodSynopsisType(): Type { if ($this->type) { return $this->type; @@ -919,12 +860,6 @@ public function getDefaultValueAsMethodSynopsisString(): ?string { return $this->defaultValue; } - - private function setTypes(?Type $type, ?Type $phpDocType): void - { - $this->type = $type; - $this->phpDocType = $phpDocType; - } } interface VariableLikeName { @@ -952,7 +887,7 @@ public function isUnknown(): bool } class ConstName extends AbstractConstName { - public string $const; + public /* readonly */ string $const; public function __construct(?Name $namespace, string $const) { @@ -988,8 +923,8 @@ public function getDeclarationName(): string } class ClassConstName extends AbstractConstName { - public Name $class; - public string $const; + public /* readonly */ Name $class; + public /* readonly */ string $const; public function __construct(Name $class, string $const) { @@ -1014,8 +949,8 @@ public function getDeclarationName(): string } class PropertyName implements VariableLikeName { - public Name $class; - public string $property; + public /* readonly */ Name $class; + public /* readonly */ string $property; public function __construct(Name $class, string $property) { @@ -1030,7 +965,7 @@ public function __toString(): string public function getDeclarationName(): string { - return $this->property; + return $this->property; } } @@ -1046,7 +981,7 @@ public function isDestructor(): bool; } class FunctionName implements FunctionOrMethodName { - private Name $name; + private /* readonly */ Name $name; public function __construct(Name $name) { $this->name = $name; @@ -1114,8 +1049,8 @@ public function isDestructor(): bool { } class MethodName implements FunctionOrMethodName { - public Name $className; - public string $methodName; + public /* readonly */ Name $className; + public /* readonly */ string $methodName; public function __construct(Name $className, string $methodName) { $this->className = $className; @@ -1173,15 +1108,18 @@ class ReturnInfo { self::REFCOUNT_N, ]; - public bool $byRef; + public /* readonly */ bool $byRef; + // NOT readonly - gets removed when discarding info for older PHP versions public ?Type $type; - public ?Type $phpDocType; - public bool $tentativeReturnType; - public string $refcount; + public /* readonly */ ?Type $phpDocType; + public /* readonly */ bool $tentativeReturnType; + public /* readonly */ string $refcount; public function __construct(bool $byRef, ?Type $type, ?Type $phpDocType, bool $tentativeReturnType, ?string $refcount) { $this->byRef = $byRef; - $this->setTypes($type, $phpDocType, $tentativeReturnType); + $this->type = $type; + $this->phpDocType = $phpDocType; + $this->tentativeReturnType = $tentativeReturnType; $this->setRefcount($refcount); } @@ -1195,13 +1133,6 @@ public function getMethodSynopsisType(): ?Type { return $this->type ?? $this->phpDocType; } - private function setTypes(?Type $type, ?Type $phpDocType, bool $tentativeReturnType): void - { - $this->type = $type; - $this->phpDocType = $phpDocType; - $this->tentativeReturnType = $tentativeReturnType; - } - private function setRefcount(?string $refcount): void { $type = $this->phpDocType ?? $this->type; @@ -1229,19 +1160,19 @@ private function setRefcount(?string $refcount): void } class FuncInfo { - public FunctionOrMethodName $name; - public int $classFlags; + public /* readonly */ FunctionOrMethodName $name; + public /* readonly */ int $classFlags; public int $flags; - public ?string $aliasType; + public /* readonly */ ?string $aliasType; public ?FunctionOrMethodName $alias; - public bool $isDeprecated; + public /* readonly */ bool $isDeprecated; public bool $supportsCompileTimeEval; - public bool $verify; + public /* readonly */ bool $verify; /** @var ArgInfo[] */ - public array $args; - public ReturnInfo $return; - public int $numRequiredArgs; - public ?string $cond; + public /* readonly */ array $args; + public /* readonly */ ReturnInfo $return; + public /* readonly */ int $numRequiredArgs; + public /* readonly */ ?string $cond; public bool $isUndocumentable; public ?int $minimumPhpVersionIdCompatibility; /** @var AttributeInfo[] */ @@ -1341,7 +1272,7 @@ public function getModifierNames(): array return $result; } - public function hasParamWithUnknownDefaultValue(): bool + private function hasParamWithUnknownDefaultValue(): bool { foreach ($this->args as $arg) { if ($arg->defaultValue && !$arg->hasProperDefaultValue()) { @@ -1421,7 +1352,7 @@ public function getFramelessDeclaration(FuncInfo $funcInfo): ?string { return $code; } - public function getFramelessFunctionInfosName(): string { + private function getFramelessFunctionInfosName(): string { return $this->name->getFramelessFunctionInfosName(); } @@ -2169,16 +2100,12 @@ public function __clone() foreach ($this->framelessFunctionInfos as $key => $framelessFunctionInfo) { $this->framelessFunctionInfos[$key] = clone $framelessFunctionInfo; } - if ($this->exposedDocComment) { - $this->exposedDocComment = clone $this->exposedDocComment; - } } } class EvaluatedValue { - /** @var mixed */ - public $value; + public /* readonly */ mixed $value; public SimpleType $type; public Expr $expr; public bool $isUnknownConstValue; @@ -2361,12 +2288,12 @@ abstract class VariableLike { public int $flags; public ?Type $type; - public ?Type $phpDocType; - public ?string $link; + public /* readonly */ ?Type $phpDocType; + public /* readonly */ ?string $link; public ?int $phpVersionIdMinimumCompatibility; /** @var AttributeInfo[] */ public array $attributes; - public ?ExposedDocComment $exposedDocComment; + public /* readonly */ ?ExposedDocComment $exposedDocComment; /** * @var AttributeInfo[] $attributes @@ -2389,8 +2316,6 @@ public function __construct( $this->exposedDocComment = $exposedDocComment; } - abstract protected function getVariableTypeCode(): string; - abstract protected function getVariableTypeName(): string; abstract protected function getFieldSynopsisDefaultLinkend(): string; @@ -2402,16 +2327,6 @@ abstract protected function getFieldSynopsisValueString(array $allConstInfos): ? abstract public function discardInfoForOldPhpVersions(?int $minimumPhpVersionIdCompatibility): void; - protected function addTypeToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void - { - $type = $this->phpDocType ?? $this->type; - - if ($type) { - $fieldsynopsisElement->appendChild(new DOMText("\n ")); - $fieldsynopsisElement->appendChild($type->getTypeForDoc($doc)); - } - } - /** * @return array */ @@ -2490,7 +2405,11 @@ public function getFieldSynopsisElement(DOMDocument $doc, array $allConstInfos): $this->addModifiersToFieldSynopsis($doc, $fieldsynopsisElement); - $this->addTypeToFieldSynopsis($doc, $fieldsynopsisElement); + $type = $this->phpDocType ?? $this->type; + if ($type) { + $fieldsynopsisElement->appendChild(new DOMText("\n ")); + $fieldsynopsisElement->appendChild($type->getTypeForDoc($doc)); + } $varnameElement = $doc->createElement("varname", $this->getFieldSynopsisName()); if ($this->link) { @@ -2549,11 +2468,11 @@ protected function addFlagForVersionsAbove(array $flags, string $flag, int $mini class ConstInfo extends VariableLike { - public ConstOrClassConstName $name; - public Expr $value; + public /* readonly */ ConstOrClassConstName $name; + public /* readonly */ Expr $value; public bool $isDeprecated; public ?string $valueString; - public ?string $cond; + public /* readonly */ ?string $cond; public ?string $cValue; public bool $isUndocumentable; public bool $isFileCacheAllowed; @@ -2605,11 +2524,6 @@ protected function getVariableTypeName(): string return "constant"; } - protected function getVariableTypeCode(): string - { - return "const"; - } - protected function getFieldSynopsisDefaultLinkend(): string { $className = str_replace(["\\", "_"], ["-", "-"], $this->name->class->toLowerString()); @@ -2658,7 +2572,7 @@ public function getPredefinedConstantTerm(DOMDocument $doc, int $indentationLeve return $termElement; } - public function getPredefinedConstantEntry(DOMDocument $doc, int $indentationLevel): DOMElement { + public function getPredefinedConstantEntry(DOMDocument $doc, int $indentationLevel): DOMElement { $indentation = str_repeat(" ", $indentationLevel); $entryElement = $doc->createElement("entry"); @@ -2914,12 +2828,12 @@ protected function addModifiersToFieldSynopsis(DOMDocument $doc, DOMElement $fie class PropertyInfo extends VariableLike { - public int $classFlags; - public PropertyName $name; - public ?Expr $defaultValue; - public ?string $defaultValueString; - public bool $isDocReadonly; - public bool $isVirtual; + public /* readonly */ int $classFlags; + public /* readonly */ PropertyName $name; + public /* readonly */ ?Expr $defaultValue; + public /* readonly */ ?string $defaultValueString; + public /* readonly */ bool $isDocReadonly; + public /* readonly */ bool $isVirtual; // Map possible variable names to the known string constant, see // ZEND_KNOWN_STRINGS @@ -3042,11 +2956,6 @@ public function __construct( parent::__construct($flags, $type, $phpDocType, $link, $phpVersionIdMinimumCompatibility, $attributes, $exposedDocComment); } - protected function getVariableTypeCode(): string - { - return "property"; - } - protected function getVariableTypeName(): string { return "property"; @@ -3234,15 +3143,12 @@ public function __clone() foreach ($this->attributes as $key => $attribute) { $this->attributes[$key] = clone $attribute; } - if ($this->exposedDocComment) { - $this->exposedDocComment = clone $this->exposedDocComment; - } } } class EnumCaseInfo { - public string $name; - public ?Expr $value; + public /* readonly */ string $name; + public /* readonly */ ?Expr $value; public function __construct(string $name, ?Expr $value) { $this->name = $name; @@ -3267,9 +3173,9 @@ public function getDeclaration(array $allConstInfos): string { } class AttributeInfo { - public string $class; + public /* readonly */ string $class; /** @var \PhpParser\Node\Arg[] */ - public array $args; + public /* readonly */ array $args; /** @param \PhpParser\Node\Arg[] $args */ public function __construct(string $class, array $args) { @@ -3320,30 +3226,30 @@ public function generateCode(string $invocation, string $nameSuffix, array $allC } class ClassInfo { - public Name $name; + public /* readonly */ Name $name; public int $flags; public string $type; - public ?string $alias; - public ?SimpleType $enumBackingType; - public bool $isDeprecated; + public /* readonly */ ?string $alias; + public /* readonly */ ?SimpleType $enumBackingType; + public /* readonly */ bool $isDeprecated; public bool $isStrictProperties; /** @var AttributeInfo[] */ public array $attributes; public ?ExposedDocComment $exposedDocComment; public bool $isNotSerializable; /** @var Name[] */ - public array $extends; + public /* readonly */ array $extends; /** @var Name[] */ - public array $implements; + public /* readonly */ array $implements; /** @var ConstInfo[] */ - public array $constInfos; + public /* readonly */ array $constInfos; /** @var PropertyInfo[] */ - public array $propertyInfos; + public /* readonly */ array $propertyInfos; /** @var FuncInfo[] */ public array $funcInfos; /** @var EnumCaseInfo[] */ - public array $enumCaseInfos; - public ?string $cond; + public /* readonly */ array $enumCaseInfos; + public /* readonly */ ?string $cond; public ?int $phpVersionIdMinimumCompatibility; public bool $isUndocumentable; @@ -3903,7 +3809,7 @@ public static function getClassSynopsisFilename(Name $name): string { return strtolower(str_replace("_", "-", implode('-', $name->getParts()))); } - public static function getClassSynopsisReference(Name $name): string { + private static function getClassSynopsisReference(Name $name): string { return "class." . self::getClassSynopsisFilename($name); } @@ -4092,10 +3998,6 @@ public function __clone() foreach ($this->attributes as $key => $attribute) { $this->attributes[$key] = clone $attribute; } - - if ($this->exposedDocComment) { - $this->exposedDocComment = clone $this->exposedDocComment; - } } /** @@ -4214,8 +4116,8 @@ public function shouldGenerateLegacyArginfo(): bool { } class DocCommentTag { - public string $name; - public ?string $value; + public /* readonly */ string $name; + public /* readonly */ ?string $value; public function __construct(string $name, ?string $value) { $this->name = $name; @@ -4271,8 +4173,10 @@ public function getVariableName(): string { } } +// Instances of ExposedDocComment are immutable and do not need to be cloned +// when held by an object that is cloned class ExposedDocComment { - private string $docComment; + private /* readonly */ string $docComment; public function __construct(string $docComment) { $this->docComment = $docComment; @@ -5107,14 +5011,14 @@ function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { if ($simpleArgType->isBuiltin) { $code .= sprintf( "\tZEND_%s_TYPE_INFO%s(%s, %s, %s, %d%s)\n", - $argKind, $argDefaultKind, $argInfo->getSendByString(), $argInfo->name, + $argKind, $argDefaultKind, $argInfo->sendBy, $argInfo->name, $simpleArgType->toTypeCode(), $argType->isNullable(), $argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" ); } else { $code .= sprintf( "\tZEND_%s_OBJ_INFO%s(%s, %s, %s, %d%s)\n", - $argKind,$argDefaultKind, $argInfo->getSendByString(), $argInfo->name, + $argKind,$argDefaultKind, $argInfo->sendBy, $argInfo->name, $simpleArgType->toEscapedName(), $argType->isNullable(), $argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" ); @@ -5124,14 +5028,14 @@ function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { if ($arginfoType->hasClassType()) { $code .= sprintf( "\tZEND_%s_OBJ_TYPE_MASK(%s, %s, %s, %s%s)\n", - $argKind, $argInfo->getSendByString(), $argInfo->name, + $argKind, $argInfo->sendBy, $argInfo->name, $arginfoType->toClassTypeString(), $arginfoType->toTypeMask(), !$argInfo->isVariadic ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" ); } else { $code .= sprintf( "\tZEND_%s_TYPE_MASK(%s, %s, %s, %s)\n", - $argKind, $argInfo->getSendByString(), $argInfo->name, + $argKind, $argInfo->sendBy, $argInfo->name, $arginfoType->toTypeMask(), $argInfo->getDefaultValueAsArginfoString() ); @@ -5140,7 +5044,7 @@ function funcInfoToCode(FileInfo $fileInfo, FuncInfo $funcInfo): string { } else { $code .= sprintf( "\tZEND_%s_INFO%s(%s, %s%s)\n", - $argKind, $argDefaultKind, $argInfo->getSendByString(), $argInfo->name, + $argKind, $argDefaultKind, $argInfo->sendBy, $argInfo->name, $argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : "" ); } @@ -5169,7 +5073,7 @@ function findEquivalentFuncInfo(array $generatedFuncInfos, FuncInfo $funcInfo): function generateCodeWithConditions( iterable $infos, string $separator, Closure $codeGenerator, ?string $parentCond = null): string { $code = ""; - + // For combining the conditional blocks of the infos with the same condition $openCondition = null; foreach ($infos as $info) {