/** @return ?Closure */
function bindTo(?object $newthis, $newscope = UNKNOWN) {}
+ /** @return mixed */
function call(object $newthis, ...$parameters) {}
/**
{
function __construct(string $message = UNKNOWN, int $code = 0, int $severity = E_ERROR, string $filename = UNKNOWN, int $lineno = 0, ?Throwable $previous = null) {}
+ /** @return int */
final function getSeverity() {}
}
function valid(): bool {}
+ /** @return mixed */
function current() {}
+ /** @return mixed */
function key() {}
function next(): void {}
+ /** @return mixed */
function send($value) {}
+ /** @return mixed */
function throw(Throwable $exception) {}
+ /** @return mixed */
function getReturn() {}
}
interface Iterator extends Traversable
{
+ /** @return mixed */
function current();
/** @return void */
function next();
+ /** @return mixed */
function key();
/** @return bool */
interface ArrayAccess
{
+ /** @return bool */
function offsetExists($offset);
/* actually this should be return by ref but atm cannot be */
+ /** @return mixed */
function offsetGet($offset);
+ /** @return void */
function offsetSet($offset, $value);
+ /** @return void */
function offsetUnset($offset);
}
/** @return string */
function serialize();
+ /** @return void */
function unserialize(string $serialized);
}
}
}
+class DocCommentTag {
+ /** @var string */
+ public $name;
+ /** @var ?string */
+ public $value;
+
+ public function __construct(string $name, ?string $value) {
+ $this->name = $name;
+ $this->value = $value;
+ }
+
+ public function getValue(): string {
+ if ($this->value === null) {
+ throw new Exception("@$this->name does not have a value");
+ }
+
+ return $this->value;
+ }
+
+ public function getVariableName(): string {
+ $value = $this->getValue();
+ if ($value === null || strlen($value) === 0 || $value[0] !== '$') {
+ throw new Exception("@$this->name not followed by variable name");
+ }
+
+ return substr($value, 1);
+ }
+}
+
+/** @return DocCommentTag[] */
+function parseDocComment(DocComment $comment): array {
+ $commentText = substr($comment->getText(), 2, -2);
+ $tags = [];
+ foreach (explode("\n", $commentText) as $commentLine) {
+ $regex = '/^\*\s*@([a-z-]+)(?:\s+(.+))$/';
+ if (preg_match($regex, trim($commentLine), $matches, PREG_UNMATCHED_AS_NULL)) {
+ $tags[] = new DocCommentTag($matches[1], $matches[2]);
+ }
+ }
+
+ return $tags;
+}
+
function parseFunctionLike(
string $name, ?string $className, Node\FunctionLike $func, ?string $cond
): FuncInfo {
$comment = $func->getDocComment();
$paramMeta = [];
$alias = null;
+ $haveDocReturnType = false;
if ($comment) {
- $commentText = substr($comment->getText(), 2, -2);
-
- foreach (explode("\n", $commentText) as $commentLine) {
- if (preg_match('/^\*\s*@prefer-ref\s+\$(.+)$/', trim($commentLine), $matches)) {
- $varName = $matches[1];
+ $tags = parseDocComment($comment);
+ foreach ($tags as $tag) {
+ if ($tag->name === 'prefer-ref') {
+ $varName = $tag->getVariableName();
if (!isset($paramMeta[$varName])) {
$paramMeta[$varName] = [];
}
$paramMeta[$varName]['preferRef'] = true;
- } else if (preg_match('/^\*\s*@alias\s+(.+)$/', trim($commentLine), $matches)) {
- $alias = $matches[1];
+ } else if ($tag->name === 'alias') {
+ $alias = $tag->getValue();
+ } else if ($tag->name === 'return') {
+ $haveDocReturnType = true;
}
}
}
}
$returnType = $func->getReturnType();
+ if ($returnType === null && !$haveDocReturnType && substr($name, 0, 2) !== '__') {
+ throw new Exception("Missing return type for function $name()");
+ }
+
$return = new ReturnInfo(
$func->returnsByRef(),
$returnType ? Type::fromNode($returnType) : null);
function variant_round($left, int $decimals): ?variant {}
-function variant_cmp($left, $right, int $lcid = UNKNOWN, int $flags = 0) {}
+function variant_cmp($left, $right, int $lcid = UNKNOWN, int $flags = 0): int {}
function variant_date_to_timestamp(variant $variant): ?int {}
function com_message_pump(int $timeoutms = 0): bool {}
-function com_load_typelib(string $typelib_name, bool $case_insensitive = true) {}
+function com_load_typelib(string $typelib_name, bool $case_insensitive = true): bool {}
ZEND_ARG_TYPE_INFO(0, decimals, IS_LONG, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_variant_cmp, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_variant_cmp, 0, 2, IS_LONG, 0)
ZEND_ARG_INFO(0, left)
ZEND_ARG_INFO(0, right)
ZEND_ARG_TYPE_INFO(0, lcid, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, timeoutms, IS_LONG, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_com_load_typelib, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_com_load_typelib, 0, 1, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, typelib_name, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, case_insensitive, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
class DOMImplementation
{
+ /** @return void */
public function getFeature(string $feature, string $version) {}
/** @return bool */
/** @return bool */
public function registerNamespace(string $prefix, string $namespaceURI) {}
- /** @param string|array $restrict */
+ /**
+ * @param string|array $restrict
+ * @return bool|null
+ */
public function registerPhpFunctions($restrict = null) {}
}
#endif
function imagettfbbox(float $size, float $angle, string $font_file, string $text): array|false {}
-function imagettftext(GdImage $im, float $size, float $angle, int $x, int $y, int $col, string $font_file, string $text) {}
+function imagettftext(GdImage $im, float $size, float $angle, int $x, int $y, int $col, string $font_file, string $text): array|false {}
#endif
function imagefilter(GdImage $im, int $filtertype, $arg1 = UNKNOWN, $arg2 = UNKNOWN, $arg3 = UNKNOWN, $arg4 = UNKNOWN): bool {}
#endif
#if defined(HAVE_GD_FREETYPE)
-ZEND_BEGIN_ARG_INFO_EX(arginfo_imagettftext, 0, 0, 8)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imagettftext, 0, 8, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_OBJ_INFO(0, im, GdImage, 0)
ZEND_ARG_TYPE_INFO(0, size, IS_DOUBLE, 0)
ZEND_ARG_TYPE_INFO(0, angle, IS_DOUBLE, 0)
class IntlIterator implements Iterator
{
+ /** @return mixed */
public function current() {}
+ /** @return mixed */
public function key() {}
+ /** @return void */
public function next() {}
+ /** @return void */
public function rewind() {}
+ /** @return bool */
public function valid() {}
}
interface JsonSerializable
{
+ /** @return mixed */
public function jsonSerialize();
}
/** @return string */
public function getContent() {}
+ /** @return mixed */
public function getMetadata() {}
/** @return int */
/** @return bool */
public function isDisabled() {}
+ /** @return mixed */
public function invoke(...$args) {}
+ /** @return mixed */
public function invokeArgs(array $args) {}
/** @return Closure */
/** @return int */
public function getModifiers() {}
+ /** @return mixed */
public function invoke(?object $object = null, ...$args) {}
+ /** @return mixed */
public function invokeArgs(?object $object, array $args) {}
/** @return ReflectionClass */
/** @return ReflectionClassConstant[] */
public function getReflectionConstants() {}
+ /** @return mixed */
public function getConstant(string $name) {}
/** @return ReflectionClassConstant|false */
/** @return ?array */
public function getStaticProperties() {}
+ /** @return mixed */
public function getStaticPropertyValue(string $name, $default = UNKNOWN) {}
/** @return void */
/** @return string|false */
public function getName() {}
+ /** @return mixed */
public function getValue(?object $object = null) {}
/** @return void */
/** @return string|false */
public function getName() {}
+ /** @return mixed */
public function getValue() {}
/** @return bool */
/** @return bool */
public function isDefaultValueAvailable() {}
+ /** @return mixed */
public function getDefaultValue() {}
/** @return bool */
*/
function socket_import_stream($stream) {}
-/** @param resource $socket */
+/**
+ * @param resource $socket
+ * @return resource|false
+ */
function socket_export_stream($socket) {}
/** @param resource $socket */
public function __toString(): string {}
+ /** @return void */
final public function _bad_state_ex() {}
}
function array_product(array $arg): int|float {}
+/** @return mixed */
function array_reduce(array $arg, callable $callback, $initial = null) {}
function array_filter(array $arg, callable $callback = UNKNOWN, int $use_keys = 0): array {}
function is_scalar($value): bool {}
/** @param mixed $value */
-function is_callable($value, bool $syntax_only = false, &$callable_name = null) {}
+function is_callable($value, bool $syntax_only = false, &$callable_name = null): bool {}
/** @param mixed $value */
function is_iterable($value): bool {}
* @param int|string $in_codepage
* @param int|string $out_codepage
*/
-function sapi_windows_cp_conv($in_codepage, $out_codepage, string $subject) {}
+function sapi_windows_cp_conv($in_codepage, $out_codepage, string $subject): ?string {}
function sapi_windows_cp_is_utf8(): bool {}
#define arginfo_is_scalar arginfo_boolval
-ZEND_BEGIN_ARG_INFO_EX(arginfo_is_callable, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_is_callable, 0, 1, _IS_BOOL, 0)
ZEND_ARG_INFO(0, value)
ZEND_ARG_TYPE_INFO(0, syntax_only, _IS_BOOL, 0)
ZEND_ARG_INFO(1, callable_name)
#endif
#if defined(PHP_WIN32)
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sapi_windows_cp_conv, 0, 0, 3)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sapi_windows_cp_conv, 0, 3, IS_STRING, 1)
ZEND_ARG_INFO(0, in_codepage)
ZEND_ARG_INFO(0, out_codepage)
ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0)
class php_user_filter
{
+ /** @return int */
public function filter($in, $out, &$consumed, $closing) {}
/** @return void */
function xml_parser_set_option(XmlParser $parser, int $option, $value): bool {}
-function xml_parser_get_option(XmlParser $parser, int $option) {}
+function xml_parser_get_option(XmlParser $parser, int $option): string|int|false {}
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_xml_parser_get_option, 0, 0, 2)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_xml_parser_get_option, 0, 2, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_OBJ_INFO(0, parser, XmlParser, 0)
ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0)
ZEND_END_ARG_INFO()
function xmlrpc_encode($value): ?string {}
+/** @return mixed */
function xmlrpc_decode(string $xml, string $encoding = "iso-8859-1") {}
+/** @return mixed */
function xmlrpc_decode_request(string $xml, &$method, string $encoding = "iso-8859-1") {}
function xmlrpc_encode_request(?string $method, $params, array $output_options = UNKNOWN): ?string {}
/** @param resource $server */
function xmlrpc_server_register_method($server, string $method_name, $function): bool {}
-/** @param resource $server */
+/**
+ * @param resource $server
+ * @return mixed
+ */
function xmlrpc_server_call_method($server, string $xml, $user_data, array $output_options = UNKNOWN) {}
+/** @return mixed */
function xmlrpc_parse_method_descriptions(string $xml) {}
/** @param resource $server */
function xmlwriter_write_raw(XMLWriter $xmlwriter, string $content): bool {}
-function xmlwriter_start_document(XMLWriter $xmlwriter, ?string $version = '1.0', ?string $encoding = null, ?string $standalone = null) {}
+function xmlwriter_start_document(XMLWriter $xmlwriter, ?string $version = '1.0', ?string $encoding = null, ?string $standalone = null): bool {}
function xmlwriter_end_document(XMLWriter $xmlwriter): bool {}
#define arginfo_xmlwriter_write_raw arginfo_xmlwriter_write_cdata
-ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlwriter_start_document, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xmlwriter_start_document, 0, 1, _IS_BOOL, 0)
ZEND_ARG_OBJ_INFO(0, xmlwriter, XMLWriter, 0)
ZEND_ARG_TYPE_INFO(0, version, IS_STRING, 1)
ZEND_ARG_TYPE_INFO(0, encoding, IS_STRING, 1)
function zend_create_unterminated_string(string $str): string {}
-function zend_terminate_string(string &$str) {}
+function zend_terminate_string(string &$str): string {}
/** @param mixed $variable */
function zend_leak_variable($variable): void {}
ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO_EX(arginfo_zend_terminate_string, 0, 0, 1)
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_terminate_string, 0, 1, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(1, str, IS_STRING, 0)
ZEND_END_ARG_INFO()