From ac879a1b675e381326d3f2a440b81af3c1a7a374 Mon Sep 17 00:00:00 2001
From: Vincent Langlet
* The constant name. *
- * @return mixed the value of the constant, or null if the constant is not - * defined. + * @return mixed the value of the constant. * @throws Error If the constant is not defined */ #[Pure(true)] From 57e00c6ffbe2d80c6a7d98aa52b9afb3362d3004 Mon Sep 17 00:00:00 2001 From: Artemy Pestretsov* The prefix of the namespace. *
- * @return string The namespace URI of the node. + * @return string|null The namespace URI of the node. */ #[PhpStormStubsElementAvailable(from: '8.0')] #[TentativeType] @@ -307,10 +307,10 @@ public function lookupNamespaceURI(?string $prefix): ?string {} /** * Gets the namespace URI of the node based on the prefix * @link https://php.net/manual/en/domnode.lookupnamespaceuri.php - * @param string $prefix+ * @param string|null $prefix
* The prefix of the namespace. *
- * @return string The namespace URI of the node. + * @return string|null The namespace URI of the node. */ #[PhpStormStubsElementAvailable(from: '5.3', to: '7.4')] public function lookupNamespaceUri($prefix) {} From 71588c847f5aba549289b48ba8619027cc268540 Mon Sep 17 00:00:00 2001 From: Thomas Schulz* As idate always returns an integer and @@ -400,7 +401,8 @@ function idate(string $format, ?int $timestamp): int|false {} * The format of the outputted date string. See the formatting * options for the date function. *
- * @param int|null $timestamp [optional] + * @param int|null $timestamp [optional] Default value: time(). The optional timestamp parameter is an integer Unix timestamp + * that defaults to the current local time if a timestamp is not given. * @return string|false a formatted date string. If a non-numeric value is used for * timestamp, false is returned and an * E_WARNING level error is emitted. From 4f769af59f2ba8137965c1784192dbd4c9ac44b6 Mon Sep 17 00:00:00 2001 From: Tim Bond+ * Can be 1, 2, 3, 4, 5 for built-in fonts in latin2 encoding (where higher numbers corresponding to larger fonts) or (since 8.1) GdFont instance + *
* @param int $x* x-coordinate of the upper left corner. *
From df7d6e1ea32ec849b0b35eeb47fad13dcbe6047b Mon Sep 17 00:00:00 2001 From: Muqsit* The value to insert. *
- * @return void + * @return true */ public function insert($value) {} From 6d1accb78b0e67e4d4196a48d5c79535f555d84e Mon Sep 17 00:00:00 2001 From: Valentin Udaltsov* When set to TRUE, outputs raw binary data. FALSE outputs lowercase hexits. *
+ * @param array $options [optional]+ * Additional options. This parameter was added for PHP 8.1 only. + *
* @return string a string containing the derived key as lowercase hexits unless * raw_output is set to TRUE in which case the raw * binary representation of the derived key is returned. * @since 5.5 */ #[Pure] -function hash_pbkdf2(string $algo, string $password, string $salt, int $iterations, int $length = 0, bool $binary = false): string {} +function hash_pbkdf2( + string $algo, + string $password, + string $salt, + int $iterations, + int $length = 0, + bool $binary = false, + #[PhpStormStubsElementAvailable('8.1')] array $options = [] +): string {} /** * Generates a key diff --git a/pgsql/pgsql.php b/pgsql/pgsql.php index 91f899c0a..c28309a13 100644 --- a/pgsql/pgsql.php +++ b/pgsql/pgsql.php @@ -2066,8 +2066,8 @@ function pg_consume_input(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'] */ function pg_flush(#[LanguageLevelTypeAware(['8.1' => 'PgSql\Connection'], default: 'resource')] $connection): int|bool {} -define('PGSQL_LIBPQ_VERSION', "15.3"); -define('PGSQL_LIBPQ_VERSION_STR', "15.3"); +define('PGSQL_LIBPQ_VERSION', "15.4"); +define('PGSQL_LIBPQ_VERSION_STR', "15.4"); /** * Passed to pg_connect to force the creation of a new connection, From 07ab12d8b1d953ad45c70fc1279b4f57308fef62 Mon Sep 17 00:00:00 2001 From: LolGleb
* The input string.
@@ -559,7 +559,6 @@ function money_format(string $format, float $number): ?string {}
* $rest = substr("abcdef", -3, -1); // returns "de"
* ?>
*
- * @return string|false the extracted part of string or false on failure.
*/
#[Pure]
#[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")]
From ef2dad0e42afd479a5079e5a8532ba5accfba716 Mon Sep 17 00:00:00 2001
From: szutoutou
* The compare function used for the sort. *
- * @return void */ #[TentativeType] - public function uasort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback): bool {} + #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] + public function uasort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback) {} /** * User defined sort @@ -1987,26 +1983,26 @@ public function uasort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: * @param callable $callback* The compare function used for the sort. *
- * @return void */ #[TentativeType] - public function uksort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback): bool {} + #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] + public function uksort(#[LanguageLevelTypeAware(['8.0' => 'callable'], default: '')] $callback) {} /** * Sort an array naturally * @link https://php.net/manual/en/arrayiterator.natsort.php - * @return bool */ #[TentativeType] - public function natsort(): bool {} + #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] + public function natsort() {} /** * Sort an array naturally, case insensitive * @link https://php.net/manual/en/arrayiterator.natcasesort.php - * @return bool */ #[TentativeType] - public function natcasesort(): bool {} + #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] + public function natcasesort() {} /** * Unserialize diff --git a/curl/curl_d.php b/curl/curl_d.php index 22ed96f49..52b15e8cf 100644 --- a/curl/curl_d.php +++ b/curl/curl_d.php @@ -1120,6 +1120,17 @@ * @since 5.2.4 */ define('CURLINFO_PRIVATE', 1048597); + +/** + * @since 8.3 + */ +define('CURLINFO_CAPATH', 1048638); + +/** + * @since 8.3 + */ +define('CURLINFO_CAINFO', 1048637); + /** * Supports IPv6 * @link https://php.net/manual/en/curl.constants.php @@ -1151,6 +1162,37 @@ * @link https://curl.haxx.se/libcurl/c/libcurl-errors.html */ define('CURLE_OK', 0); + +/** + * @since 8.3 + */ +define('CURLKHMATCH_OK', 0); + +/** + * @since 8.3 + */ +define('CURLKHMATCH_MISMATCH', 1); + +/** + * @since 8.3 + */ +define('CURLKHMATCH_MISSING', 2); + +/** + * @since 8.3 + */ +define('CURLKHMATCH_LAST', 3); + +/** + * @since 8.3 + */ +define('CURLOPT_MIME_OPTIONS', 315); + +/** + * @since 8.3 + */ +define('CURLMIMEOPT_FORMESCAPE', 1); + /** * The URL you passed to libcurl used a protocol that this libcurl does not support. * The support might be a compile-time option that you didn't use, @@ -2061,6 +2103,41 @@ */ define('CURLOPT_SERVICE_NAME', 10236); +/** + * @since 8.3 + */ +define('CURLOPT_SSH_HOSTKEYFUNCTION', 20316); + +/** + * @since 8.3 + */ +define('CURLOPT_PROTOCOLS_STR', 10318); + +/** + * @since 8.3 + */ +define('CURLOPT_REDIR_PROTOCOLS_STR', 10319); + +/** + * @since 8.3 + */ +define('CURLOPT_WS_OPTIONS', 320); + +/** + * @since 8.3 + */ +define('CURLWS_RAW_MODE', 1); + +/** + * @since 8.3 + */ +define('CURLOPT_CA_CACHE_TIMEOUT', 321); + +/** + * @since 8.3 + */ +define('CURLOPT_QUICK_EXIT', 322); + /** * Value for the CURLOPT_SSH_AUTH_TYPES option. * libcurl attempts to connect to ssh-agent or pageant and let the agent attempt the authentication. diff --git a/date/date_c.php b/date/date_c.php index d6db7e837..c297e6ca0 100644 --- a/date/date_c.php +++ b/date/date_c.php @@ -1100,4 +1100,54 @@ public function __serialize(): array {} #[PhpStormStubsElementAvailable(from: '8.2')] public function __unserialize(array $data): void {} + + /** + * @since 8.3 + */ + public static function createFromISO8601String(string $specification, int $options = 0): static {} } + +/** + * @since 8.3 + */ +class DateError extends Error {} + +/** + * @since 8.3 + */ +class DateObjectError extends DateError {} + +/** + * @since 8.3 + */ +class DateRangeError extends DateError {} + +/** + * @since 8.3 + */ +class DateException extends Exception {} + +/** + * @since 8.3 + */ +class DateInvalidTimeZoneException extends DateException {} + +/** + * @since 8.3 + */ +class DateInvalidOperationException extends DateException {} + +/** + * @since 8.3 + */ +class DateMalformedStringException extends DateException {} + +/** + * @since 8.3 + */ +class DateMalformedIntervalStringException extends DateException {} + +/** + * @since 8.3 + */ +class DateMalformedPeriodStringException extends DateException {} diff --git a/dom/dom_c.php b/dom/dom_c.php index 4bf64209f..099399e40 100644 --- a/dom/dom_c.php +++ b/dom/dom_c.php @@ -142,6 +142,8 @@ class DOMNode */ #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $textContent; + public bool $isConnected; + public ?DOMElement $parentElement; /** * Adds a new child before a reference node @@ -318,9 +320,15 @@ public function lookupNamespaceUri($prefix) {} /** * @param DOMNode $arg * @return bool + * @removed 8.0 */ public function isEqualNode(DOMNode $arg) {} + /** + * @since 8.3 + */ + public function isEqualNode(?DOMNode $otherNode): bool {} + /** * @param $feature * @param $version @@ -391,6 +399,16 @@ public function C14NFile( #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: 'array')] $xpath = null, #[LanguageLevelTypeAware(['8.0' => 'array|null'], default: 'array')] $nsPrefixes = null ): int|false {} + + /** + * @since 8.3 + */ + public function contains(DOMNode|DOMNameSpaceNode|null $other): bool {} + + /** + * @since 8.3 + */ + public function getRootNode(?array $options = []): DOMNode {} } /** @@ -577,6 +595,8 @@ class DOMNameSpaceNode #[LanguageLevelTypeAware(['8.1' => 'string'], default: '')] public $nodeName; + public ?DOMElement $parentElement; + public bool $isConnected; } /** @@ -616,6 +636,12 @@ public function append(...$nodes): void {} * {@inheritDoc} */ public function prepend(...$nodes): void {} + + /** + * @since 8.3 + * {@inheritDoc} + */ + public function replaceChildren(...$nodes): void {} } /** @@ -1001,9 +1027,8 @@ public function getElementsByTagNameNS( #[TentativeType] public function getElementById(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $elementId): ?DOMElement {} - /** - * @param DOMNode $node - */ + #[TentativeType] + #[LanguageLevelTypeAware(['8.3' => 'DOMNode|false'], default: '')] public function adoptNode(DOMNode $node) {} /** @@ -1016,6 +1041,12 @@ public function append(...$nodes): void {} */ public function prepend(...$nodes): void {} + /** + * @since 8.3 + * {@inheritDoc} + */ + public function replaceChildren(...$nodes): void {} + /** * Normalizes the document * @link https://php.net/manual/en/domdocument.normalizedocument.php @@ -1041,10 +1072,12 @@ public function renameNode(DOMNode $node, $namespace, $qualifiedName) {} * Bitwise OR * of the libxml option constants. * - * @return DOMDocument|bool true on success or false on failure. If called statically, returns a + * @return DOMDocument|bool true on success or false on failure. Prior to PHP 8.3 if called statically, returns a * DOMDocument and issues E_STRICT * warning. */ + #[TentativeType] + #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'DOMDocument|bool')] public function load( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = null @@ -1073,10 +1106,12 @@ public function save($filename, $options = null) {} * Bitwise OR * of the libxml option constants. * - * @return DOMDocument|bool true on success or false on failure. If called statically, returns a + * @return DOMDocument|bool true on success or false on failure. Prior to PHP 8.3 if called statically, returns a * DOMDocument and issues E_STRICT * warning. */ + #[TentativeType] + #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'DOMDocument|bool')] public function loadXML( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $source, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = null @@ -1142,10 +1177,12 @@ public function xinclude(#[LanguageLevelTypeAware(['8.0' => 'int'], default: '') * Since PHP 5.4.0 and Libxml 2.6.0, you may also * use the options parameter to specify additional Libxml parameters. * - * @return DOMDocument|bool true on success or false on failure. If called statically, returns a + * @return DOMDocument|bool true on success or false on failure. Prior to PHP 8.3 if called statically, returns a * DOMDocument and issues E_STRICT * warning. */ + #[TentativeType] + #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'DOMDocument|bool')] public function loadHTML( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $source, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0 @@ -1161,10 +1198,12 @@ public function loadHTML( * Since PHP 5.4.0 and Libxml 2.6.0, you may also * use the options parameter to specify additional Libxml parameters. * - * @return DOMDocument|bool true on success or false on failure. If called statically, returns a + * @return DOMDocument|bool true on success or false on failure. Prior to PHP 8.3 if called statically, returns a * DOMDocument and issues E_STRICT * warning. */ + #[TentativeType] + #[LanguageLevelTypeAware(['8.3' => 'bool'], default: 'DOMDocument|bool')] public function loadHTMLFile( #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $filename, #[LanguageLevelTypeAware(['8.0' => 'int'], default: '')] $options = 0 @@ -1443,10 +1482,10 @@ public function substringData( * @param string $data* The string to append. *
- * @return void */ #[TentativeType] - public function appendData(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data): bool {} + #[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] + public function appendData(#[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $data) {} /** * Insert a string at the specified 16-bit unit offset @@ -1679,6 +1718,8 @@ class DOMElement extends DOMNode implements DOMParentNode, DOMChildNode #[LanguageLevelTypeAware(['8.1' => 'DOMElement|null'], default: '')] public $nextElementSibling; + public string $id; + public string $className; /** * Returns value of attribute @@ -1976,6 +2017,12 @@ public function append(...$nodes): void {} */ public function prepend(...$nodes): void {} + /** + * @since 8.3 + * {@inheritDoc} + */ + public function replaceChildren(...$nodes): void {} + /** * Creates a new DOMElement object * @link https://php.net/manual/en/domelement.construct.php @@ -1989,6 +2036,26 @@ public function __construct( #[LanguageLevelTypeAware(['8.0' => 'string|null'], default: '')] $value = null, #[LanguageLevelTypeAware(['8.0' => 'string'], default: '')] $namespace = null ) {} + + /** + * @since 8.3 + */ + public function getAttributeNames(): array {} + + /** + * @since 8.3 + */ + public function toggleAttribute(string $qualifiedName, ?bool $force = false): bool {} + + /** + * @since 8.3 + */ + public function insertAdjacentElement(string $where, DOMElement $element): ?DOMElement {} + + /** + * @since 8.3 + */ + public function insertAdjacentText(string $where, string $data): void {} } /** @@ -2455,6 +2522,11 @@ public function append(...$nodes): void; * @since 8.0 */ public function prepend(...$nodes): void; + + /** + * @since 8.3 + */ + public function replaceChildren(...$nodes): void; } /** diff --git a/gd/gd.php b/gd/gd.php index 3e9ee1114..a35700fdb 100644 --- a/gd/gd.php +++ b/gd/gd.php @@ -818,11 +818,16 @@ function imagecopyresampled(GdImage $dst_image, GdImage $src_image, int $dst_x, * Specifies the color of the uncovered zone after the rotation * * @param bool $ignore_transparent [optional]- * If set and non-zero, transparent colors are ignored (otherwise kept). + * Prior to PHP 8.3 if set and non-zero, transparent colors are ignored (otherwise kept). *
* @return resource|GdImage|false the rotated image or FALSE on failure */ -function imagerotate(GdImage $image, float $angle, int $background_color, bool $ignore_transparent = false): GdImage|false {} +function imagerotate( + GdImage $image, + float $angle, + int $background_color, + #[PhpStormStubsElementAvailable(to: '8.2')] bool $ignore_transparent = false +): GdImage|false {} /** * Should antialias functions be used or not.* An optional seed value *
* @param int $mode [optional]@@ -23,7 +24,7 @@ function lcg_value(): float {} * @return void */ function mt_srand( - int $seed = null, + #[LanguageLevelTypeAware(['8.3' => 'int|null'], default: 'int')] $seed = null, #[PhpStormStubsElementAvailable(from: '7.1')] int $mode = MT_RAND_MT19937 ): void {} @@ -33,7 +34,7 @@ function mt_srand( * an alias of {@see mt_srand()}. *
* @link https://php.net/manual/en/function.srand.php - * @param int $seed+ * @param int|null $seed
* Optional seed value *
* @param int $mode [optional]@@ -42,7 +43,7 @@ function mt_srand( * @return void */ function srand( - int $seed = null, + #[LanguageLevelTypeAware(['8.3' => 'int|null'], default: 'int')] $seed = null, #[PhpStormStubsElementAvailable(from: '7.1')] int $mode = MT_RAND_MT19937 ): void {} @@ -214,6 +215,21 @@ public function pickArrayKeys(array $array, int $num): array {} public function __serialize(): array {} public function __unserialize(array $data): void {} + + /** + * @since 8.3 + */ + public function nextFloat(): float {} + + /** + * @since 8.3 + */ + public function getFloat(float $min, float $max, IntervalBoundary $boundary = IntervalBoundary::ClosedOpen): float {} + + /** + * @since 8.3 + */ + public function getBytesFromString(string $string, int $length): string {} } /** @@ -230,4 +246,19 @@ class BrokenRandomEngineError extends RandomError {} * @since 8.2 */ class RandomException extends Exception {} + + /** + * @since 8.3 + */ + enum IntervalBoundary + { + public string $name; + + case ClosedOpen; + case ClosedClosed; + case OpenClosed; + case OpenOpen; + + public static function cases(): array {} + } } diff --git a/sockets/sockets.php b/sockets/sockets.php index 7fa20c9f4..b119c19ad 100644 --- a/sockets/sockets.php +++ b/sockets/sockets.php @@ -1400,6 +1400,11 @@ function socket_wsaprotocol_info_import($info_id) {} */ function socket_wsaprotocol_info_release($info_id) {} +/** + * @since 8.3 + */ +function socket_atmark(Socket $socket): bool {} + define('AF_UNIX', 1); define('AF_INET', 2); @@ -1462,7 +1467,12 @@ function socket_wsaprotocol_info_release($info_id) {} define('SO_TYPE', 3); define('SO_ERROR', 4); define('SO_BINDTODEVICE', 25); +define('SO_ATTACH_REUSEPORT_CBPF', 51); +define('SO_DETACH_FILTER', 27); +define('SO_DETACH_BPF', 27); + define('SOL_SOCKET', 1); +define('SOL_UDPLITE', 136); define('SOMAXCONN', 128); /** * @since 8.1 @@ -1560,6 +1570,14 @@ function socket_wsaprotocol_info_release($info_id) {} */ define('IPV6_MULTICAST_LOOP', 19); define('IPV6_V6ONLY', 26); +define('IP_BIND_ADDRESS_NO_PORT', 24); +define('IP_MTU_DISCOVER', 10); +define('IP_PMTUDISC_DO', 2); +define('IP_PMTUDISC_DONT', 0); +define('IP_PMTUDISC_WANT', 1); +define('IP_PMTUDISC_PROBE', 3); +define('IP_PMTUDISC_INTERFACE', 4); +define('IP_PMTUDISC_OMIT', 5); /** * Operation not permitted. @@ -2326,6 +2344,16 @@ function socket_wsaprotocol_info_release($info_id) {} */ define('TCP_KEEPCNT', 6); +/** + * @since 8.3 + */ +define('TCP_QUICKACK', 12); + +/** + * @since 8.3 + */ +define('TCP_REPAIR', 19); + /** * Socket_set_option for the socket_send* functions. * It avoids copy b/w userland and kernel for both TCP and UDP protocols. diff --git a/sqlite3/sqlite3.php b/sqlite3/sqlite3.php index b26210e46..f4d942d61 100644 --- a/sqlite3/sqlite3.php +++ b/sqlite3/sqlite3.php @@ -6,6 +6,11 @@ use JetBrains\PhpStorm\Internal\PhpStormStubsElementAvailable; use JetBrains\PhpStorm\Internal\TentativeType; +/** + * @since 8.3 + */ +class SQLite3Exception extends \Exception {} + /** * A class that interfaces SQLite 3 databases. * @link https://php.net/manual/en/class.sqlite3.php diff --git a/standard/standard_4.php b/standard/standard_4.php index 0c5e43fe2..ba361c1f1 100644 --- a/standard/standard_4.php +++ b/standard/standard_4.php @@ -244,12 +244,12 @@ function debug_zval_dump( * to true, print_r will return its output, instead of * printing it (which it does by default). *
- * @return string|true If given a string, integer or float, + * @return string|bool If given a string, integer or float, * the value itself will be printed. If given an array, values * will be presented in a format that shows keys and elements. Similar * notation is used for objects. */ -function print_r(mixed $value, bool $return = false): string|true {} +function print_r(mixed $value, bool $return = false): string|bool {} /** * Returns the amount of memory allocated to PHP diff --git a/standard/standard_6.php b/standard/standard_6.php index 92835dd96..c72bdf2d8 100644 --- a/standard/standard_6.php +++ b/standard/standard_6.php @@ -589,6 +589,11 @@ function stream_get_contents($stream, ?int $length = null, int $offset = -1): st */ function stream_supports_lock($stream): bool {} +/** + * @since 8.3 + */ +function stream_context_set_options($context, array $options): bool {} + /** * Gets line from file pointer and parse for CSV fields * @link https://php.net/manual/en/function.fgetcsv.php diff --git a/standard/standard_8.php b/standard/standard_8.php index 9b316e7ba..643f60961 100644 --- a/standard/standard_8.php +++ b/standard/standard_8.php @@ -59,7 +59,6 @@ * (strerror) corresponding to the present value of * errno. * - * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function syslog(int $priority, string $message): bool {} @@ -67,7 +66,6 @@ function syslog(int $priority, string $message): bool {} /** * Close connection to system logger * @link https://php.net/manual/en/function.closelog.php - * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function closelog(): bool {} @@ -140,7 +138,7 @@ function define_syslog_variables() {} */ #[Pure] #[LanguageLevelTypeAware(["8.0" => "string"], default: "string|false")] -function metaphone(string $string, int $max_phonemes = 0): false|string {} +function metaphone(string $string, int $max_phonemes = 0) {} /** * Turn on output buffering @@ -395,7 +393,6 @@ function ob_list_handlers(): array {} * parameter sort_flags, for details * see sort. * - * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function ksort(array &$array, int $flags = SORT_REGULAR): bool {} @@ -411,7 +408,6 @@ function ksort(array &$array, int $flags = SORT_REGULAR): bool {} * sort_flags, for details see * sort. * - * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function krsort(array &$array, int $flags = SORT_REGULAR): bool {} @@ -422,9 +418,9 @@ function krsort(array &$array, int $flags = SORT_REGULAR): bool {} * @param array &$array* The input array. *
- * @return bool true on success or false on failure. */ -function natsort(array &$array): bool {} +#[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] +function natsort(array &$array) {} /** * Sort an array using a case insensitive "natural order" algorithm @@ -432,9 +428,9 @@ function natsort(array &$array): bool {} * @param array &$array* The input array. *
- * @return bool true on success or false on failure. */ -function natcasesort(array &$array): bool {} +#[LanguageLevelTypeAware(['8.3' => 'true'], default: 'bool')] +function natcasesort(array &$array) {} /** * Sort an array and maintain index association @@ -447,10 +443,9 @@ function natcasesort(array &$array): bool {} * parameter sort_flags, for details * see sort. * - * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] -function asort(array &$array, int $flags = SORT_REGULAR): bool {} +function asort(array &$array, int $flags = SORT_REGULAR) {} /** * Sort an array in reverse order and maintain index association @@ -463,7 +458,6 @@ function asort(array &$array, int $flags = SORT_REGULAR): bool {} * sort_flags, for details see * sort. * - * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function arsort(array &$array, int $flags = SORT_REGULAR): bool {} @@ -482,7 +476,6 @@ function arsort(array &$array, int $flags = SORT_REGULAR): bool {} * Sorting type flags:* The array. *
- * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function shuffle(array &$array): bool {} @@ -596,7 +585,6 @@ function shuffle(array &$array): bool {} * it will be passed as the third parameter to the callback * funcname. * - * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function array_walk(object|array &$array, callable $callback, mixed $arg): bool {} @@ -625,7 +613,6 @@ function array_walk(object|array &$array, callable $callback, mixed $arg): bool * it will be passed as the third parameter to the callback * funcname. * - * @return bool true on success or false on failure. */ #[LanguageLevelTypeAware(['8.2' => 'true'], default: 'bool')] function array_walk_recursive(object|array &$array, callable $callback, mixed $arg): bool {} @@ -937,7 +924,11 @@ function array_fill_keys(array $keys, mixed $value): array {} * end, inclusive. */ #[Pure] -function range($start, $end, int|float $step = 1): array {} +function range( + #[LanguageLevelTypeAware(['8.3' => 'string|int|float'], default: '')] $start, + #[LanguageLevelTypeAware(['8.3' => 'string|int|float'], default: '')] $end, + int|float $step = 1 +): array {} /** * Sort multiple or multi-dimensional arrays diff --git a/standard/standard_9.php b/standard/standard_9.php index 4a2e1acab..e500a6ffc 100644 --- a/standard/standard_9.php +++ b/standard/standard_9.php @@ -948,6 +948,7 @@ class AssertionError extends Error {} * An optional new value for the option. * * @return mixed The original setting of any option. + * @deprecated */ function assert_options(int $option, mixed $value): mixed {} diff --git a/tests/AbstractBaseStubsTestCase.php b/tests/AbstractBaseStubsTestCase.php index a62e5b8f3..6c4483b52 100644 --- a/tests/AbstractBaseStubsTestCase.php +++ b/tests/AbstractBaseStubsTestCase.php @@ -16,6 +16,7 @@ use RuntimeException; use StubTests\Model\PHPClass; use StubTests\Model\PHPConst; +use StubTests\Model\PHPEnum; use StubTests\Model\PHPFunction; use StubTests\Model\PHPInterface; use StubTests\Parsers\ParserUtils; @@ -75,12 +76,15 @@ public static function getStringRepresentationOfDefaultParameterValue(mixed $def if ($class === 'self' && $contextClass !== null) { $class = $contextClass->name; } - $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getClass($class) ?? + $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($class) ?? + PhpStormStubsSingleton::getPhpStormStubs()->getClass($class) ?? PhpStormStubsSingleton::getPhpStormStubs()->getInterface($class); if ($parentClass === null) { throw new Exception("Class $class not found in stubs"); } - if ((string)$defaultValue->name === 'class') { + if ($parentClass instanceof PHPEnum) { + $value = $parentClass->name . "::" . $defaultValue->name; + } elseif ((string)$defaultValue->name === 'class') { $value = (string)$defaultValue->class; } else { $constant = $parentClass->getConstant((string)$defaultValue->name);; @@ -90,6 +94,8 @@ public static function getStringRepresentationOfDefaultParameterValue(mixed $def $value = "null"; } elseif (is_array($defaultValue) || $defaultValue instanceof Array_) { $value = '[]'; + } elseif ($defaultValue instanceof \UnitEnum){ + $value = get_class($defaultValue) . "::" . $defaultValue->name; } else { $value = strval($defaultValue); } diff --git a/tests/BaseClassesTest.php b/tests/BaseClassesTest.php index b72046f49..d61290a78 100644 --- a/tests/BaseClassesTest.php +++ b/tests/BaseClassesTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\Exception; use RuntimeException; use StubTests\Model\PHPClass; +use StubTests\Model\PHPEnum; use StubTests\Model\PHPInterface; use StubTests\Model\PHPMethod; use StubTests\Model\PHPProperty; @@ -45,10 +46,12 @@ public function testClassesParent(PHPClass|PHPInterface $class) * @dataProvider \StubTests\TestData\Providers\Reflection\ReflectionMethodsProvider::classMethodsProvider * @throws Exception|RuntimeException */ - public function testClassesMethodsExist(PHPClass|PHPInterface $class, PHPMethod $method) + public function testClassesMethodsExist(PHPClass|PHPInterface|PHPEnum $class, PHPMethod $method) { $className = $class->name; - if ($class instanceof PHPClass) { + if ($class instanceof PHPEnum) { + $stubClass = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($className); + } elseif ($class instanceof PHPClass) { $stubClass = PhpStormStubsSingleton::getPhpStormStubs()->getClass($className); } else { $stubClass = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($className); @@ -63,7 +66,9 @@ public function testClassesMethodsExist(PHPClass|PHPInterface $class, PHPMethod public function testClassesFinalMethods(PHPClass|PHPInterface $class, PHPMethod $method) { $className = $class->name; - if ($class instanceof PHPClass) { + if ($class instanceof PHPEnum) { + $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($className)->getMethod($method->name); + } elseif ($class instanceof PHPClass) { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getClass($className)->getMethod($method->name); } else { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($className)->getMethod($method->name); @@ -82,7 +87,9 @@ public function testClassesFinalMethods(PHPClass|PHPInterface $class, PHPMethod public function testClassesStaticMethods(PHPClass|PHPInterface $class, PHPMethod $method) { $className = $class->name; - if ($class instanceof PHPClass) { + if ($class instanceof PHPEnum) { + $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($className)->getMethod($method->name); + } elseif ($class instanceof PHPClass) { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getClass($className)->getMethod($method->name); } else { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($className)->getMethod($method->name); @@ -101,7 +108,9 @@ public function testClassesStaticMethods(PHPClass|PHPInterface $class, PHPMethod public function testClassesMethodsVisibility(PHPClass|PHPInterface $class, PHPMethod $method) { $className = $class->name; - if ($class instanceof PHPClass) { + if ($class instanceof PHPEnum) { + $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($className)->getMethod($method->name); + } elseif ($class instanceof PHPClass) { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getClass($className)->getMethod($method->name); } else { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($className)->getMethod($method->name); @@ -120,7 +129,9 @@ public function testClassesMethodsVisibility(PHPClass|PHPInterface $class, PHPMe public function testClassMethodsParametersCount(PHPClass|PHPInterface $class, PHPMethod $method) { $className = $class->name; - if ($class instanceof PHPClass) { + if ($class instanceof PHPEnum) { + $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($className)->getMethod($method->name); + } elseif ($class instanceof PHPClass) { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getClass($className)->getMethod($method->name); } else { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($className)->getMethod($method->name); diff --git a/tests/DockerImages/8.3/Dockerfile b/tests/DockerImages/8.3/Dockerfile new file mode 100644 index 000000000..766eb15a0 --- /dev/null +++ b/tests/DockerImages/8.3/Dockerfile @@ -0,0 +1,14 @@ +FROM php:8.3.0beta3-alpine + +RUN set -eux; \ + apk add --repository http://dl-cdn.alpinelinux.org/alpine/edge/community --no-cache --virtual .build-deps \ + bash gcc g++ make autoconf pkgconfig git \ + libmcrypt-dev imap-dev php-imap enchant2 php-enchant bzip2-dev gettext-dev libxml2-dev php82-dev php-gd icu-dev \ + php-zip php-tidy php-intl libffi-dev openssl-dev php82-pear rabbitmq-c rabbitmq-c-dev librrd \ + libzip-dev rrdtool-dev gmp-dev yaml yaml-dev fann fann-dev openldap-dev librdkafka librdkafka-dev libcurl curl-dev \ + libpng-dev gpgme gpgme-dev libpq-dev aspell-dev + +RUN docker-php-ext-install imap gmp sockets intl gd ldap bz2 mysqli bcmath calendar dba exif gettext opcache pcntl \ + pdo_mysql shmop sysvmsg sysvsem sysvshm xml soap pgsql pspell + +WORKDIR /opt/project/phpstorm-stubs diff --git a/tests/DockerImages/testRunner/Dockerfile b/tests/DockerImages/testRunner/Dockerfile index fc6b6ed8c..244e1897c 100644 --- a/tests/DockerImages/testRunner/Dockerfile +++ b/tests/DockerImages/testRunner/Dockerfile @@ -1,8 +1,26 @@ -FROM php:8.1-apache +FROM php:8.3.0beta3-apache RUN echo 'memory_limit = 1024M' >> /usr/local/etc/php/conf.d/docker-php-memlimit.ini COPY --from=composer /usr/bin/composer /usr/bin/composer RUN apt-get update && apt-get -y install git zip unzip - +RUN apt-get update -y && \ + apt-get install git -y && \ + git clone https://github.com/xdebug/xdebug +WORKDIR xdebug +RUN phpize && \ + chmod +x configure && \ + ./configure --enable-xdebug && \ + make && \ + make install +# Enable xdebug extension +RUN echo "zend_extension=$(php-config --extension-dir)/xdebug.so" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +#RUN pecl install xdebug +#RUN docker-php-ext-enable xdebug +RUN echo "xdebug.mode=develop,debug,coverage" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +#RUN echo "xdebug.remote_host=192.168.178.178" >> /usr/local/etc/php/php.ini +RUN echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/php.ini +RUN echo "xdebug.start_with_request=yes" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN echo "xdebug.output_dir=/opt/project/xdebug_snapshots" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini +RUN echo "xdebug.log=/opt/project/xdebug_logs/xdebug33php82.log" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini WORKDIR /opt/project/phpstorm-stubs diff --git a/tests/Model/BasePHPClass.php b/tests/Model/BasePHPClass.php index fc5a593d2..300ec83c3 100644 --- a/tests/Model/BasePHPClass.php +++ b/tests/Model/BasePHPClass.php @@ -36,6 +36,23 @@ function (PHPConst $nextConstant) use ($parsedConstant) { } } + public function addEnumCase(PHPEnumCase $parsedConstant) + { + if (isset($parsedConstant->name)) { + if (array_key_exists($parsedConstant->name, $this->constants)) { + $amount = count(array_filter( + $this->constants, + function (PHPConst $nextConstant) use ($parsedConstant) { + return $nextConstant->name === $parsedConstant->name; + } + )); + $this->constants[$parsedConstant->name . '_duplicated_' . $amount] = $parsedConstant; + } else { + $this->constants[$parsedConstant->name] = $parsedConstant; + } + } + } + /** * @return PHPConst|null * @throws RuntimeException diff --git a/tests/Model/PHPConst.php b/tests/Model/PHPConst.php index 15cc90679..e1f7247e2 100644 --- a/tests/Model/PHPConst.php +++ b/tests/Model/PHPConst.php @@ -8,6 +8,7 @@ use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Expr\UnaryMinus; use PhpParser\Node\Stmt\ClassConst; +use PhpParser\Node\Stmt\Enum_; use PhpParser\Node\Stmt\Namespace_; use PhpParser\NodeAbstract; use ReflectionClassConstant; @@ -107,9 +108,14 @@ protected function getConstValue($node) protected function getConstantFQN(NodeAbstract $node, $nodeName) { $namespace = ''; - $parentParentNode = $node->getAttribute('parent')->getAttribute('parent'); - if ($parentParentNode instanceof Namespace_ && !empty($parentParentNode->name)) { - $namespace = '\\' . implode('\\', $parentParentNode->name->parts) . '\\'; + $parentNode = $node->getAttribute('parent'); + if ($parentNode instanceof Enum_) { + return $nodeName; + } else { + $parentParentNode = $parentNode->getAttribute('parent'); + if ($parentParentNode instanceof Namespace_ && !empty($parentParentNode->name)) { + $namespace = '\\' . implode('\\', $parentParentNode->name->parts) . '\\'; + } } return $namespace . $nodeName; diff --git a/tests/Model/PHPEnum.php b/tests/Model/PHPEnum.php new file mode 100644 index 000000000..0b3096720 --- /dev/null +++ b/tests/Model/PHPEnum.php @@ -0,0 +1,111 @@ +name = $reflectionObject->getName(); + $this->interfaces = $reflectionObject->getInterfaceNames(); + $this->isFinal = $reflectionObject->isFinal(); + if (method_exists($reflectionObject, 'isReadOnly')) { + $this->isReadonly = $reflectionObject->isReadOnly(); + } + foreach ($reflectionObject->getMethods() as $method) { + if ($method->getDeclaringClass()->getName() !== $this->name) { + continue; + } + $parsedMethod = (new PHPMethod())->readObjectFromReflection($method); + $this->addMethod($parsedMethod); + } + + if (method_exists($reflectionObject, 'getReflectionConstants')) { + foreach ($reflectionObject->getReflectionConstants() as $constant) { + if ($constant->getDeclaringClass()->getName() !== $this->name) { + continue; + } + if ($constant->isEnumCase()) { + $enumCase = (new PHPEnumCase())->readObjectFromReflection($constant); + $this->addEnumCase($enumCase); + } else { + $parsedConstant = (new PHPConst())->readObjectFromReflection($constant); + $this->addConstant($parsedConstant); + } + } + } + + foreach ($reflectionObject->getProperties() as $property) { + if ($property->getDeclaringClass()->getName() !== $this->name) { + continue; + } + $parsedProperty = (new PHPProperty())->readObjectFromReflection($property); + $this->addProperty($parsedProperty); + } + + return $this; + } + + /** + * @param Enum_ $node + * @return static + */ + public function readObjectFromStubNode($node) + { + $this->name = self::getFQN($node); + $this->availableVersionsRangeFromAttribute = self::findAvailableVersionsRangeFromAttribute($node->attrGroups); + $this->collectTags($node); + if (!empty($node->extends)) { + $this->parentClass = ''; + foreach ($node->extends->parts as $part) { + $this->parentClass .= "\\$part"; + } + $this->parentClass = ltrim($this->parentClass, "\\"); + } + if (!empty($node->implements)) { + foreach ($node->implements as $interfaceObject) { + $interfaceFQN = ''; + foreach ($interfaceObject->parts as $interface) { + $interfaceFQN .= "\\$interface"; + } + $this->interfaces[] = ltrim($interfaceFQN, "\\"); + } + } + if ($node->getDocComment() !== null) { + $docBlock = DocBlockFactory::createInstance()->create($node->getDocComment()->getText()); + /** @var PropertyRead[] $properties */ + $properties = array_merge( + $docBlock->getTagsByName('property-read'), + $docBlock->getTagsByName('property') + ); + foreach ($properties as $property) { + $propertyName = $property->getVariableName(); + assert($propertyName !== '', "@property name is empty in class $this->name"); + $newProperty = new PHPProperty($this->name); + $newProperty->is_static = false; + $newProperty->access = 'public'; + $newProperty->name = $propertyName; + $newProperty->parentName = $this->name; + $newProperty->typesFromSignature = self::convertParsedTypeToArray($property->getType()); + assert( + !array_key_exists($propertyName, $this->properties), + "Property '$propertyName' is already declared in class '$this->name'" + ); + $this->properties[$propertyName] = $newProperty; + } + } + + return $this; + } + + public function readMutedProblems($jsonData) {} +} diff --git a/tests/Model/PHPEnumCase.php b/tests/Model/PHPEnumCase.php new file mode 100644 index 000000000..ea5bc4e5c --- /dev/null +++ b/tests/Model/PHPEnumCase.php @@ -0,0 +1,45 @@ +name = $reflectionObject->name; + $this->value = $reflectionObject->getValue(); + if ($reflectionObject->isPrivate()) { + $this->visibility = 'private'; + } elseif ($reflectionObject->isProtected()) { + $this->visibility = 'protected'; + } else { + $this->visibility = 'public'; + } + return $this; + } + + /** + * @param EnumCase $node + * @return $this|PHPEnumCase + */ + public function readObjectFromStubNode($node) + { + $this->name = $this->getConstantFQN($node, $node->name->name); + //$this->value = $this->getConstValue($node); + //$this->collectTags($node); + $parentNode = $node->getAttribute('parent'); + if (property_exists($parentNode, 'attrGroups')) { + $this->availableVersionsRangeFromAttribute = self::findAvailableVersionsRangeFromAttribute($parentNode->attrGroups); + } + $this->parentName = self::getFQN($parentNode->namespacedName); + return $this; + } + + public function readMutedProblems($jsonData) {} +} diff --git a/tests/Model/PhpVersions.php b/tests/Model/PhpVersions.php index f5cafc53b..784dc2903 100644 --- a/tests/Model/PhpVersions.php +++ b/tests/Model/PhpVersions.php @@ -10,7 +10,7 @@ class PhpVersions implements ArrayAccess, IteratorAggregate { - private static $versions = [5.3, 5.4, 5.5, 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2]; + private static $versions = [5.3, 5.4, 5.5, 5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3]; public static function getLatest() { diff --git a/tests/Model/StubsContainer.php b/tests/Model/StubsContainer.php index aa93c096c..44d60ef4f 100644 --- a/tests/Model/StubsContainer.php +++ b/tests/Model/StubsContainer.php @@ -28,6 +28,11 @@ class StubsContainer */ private $interfaces = []; + /** + * @var PHPEnum[] + */ + private $enums = []; + /** * @return PHPConst[] */ @@ -188,6 +193,38 @@ public function getClass($name, $sourceFilePath = null, $shouldSuitCurrentPhpVer return null; } + /** + * @param string $name + * @param string|null $sourceFilePath + * @param bool $shouldSuitCurrentPhpVersion + * @return PHPEnum|null + * @throws RuntimeException + */ + public function getEnum($name, $sourceFilePath = null, $shouldSuitCurrentPhpVersion = true) + { + $enums = array_filter($this->enums, function (PHPEnum $enum) use ($shouldSuitCurrentPhpVersion, $name) { + return $enum->name === $name && + (!$shouldSuitCurrentPhpVersion || BasePHPElement::entitySuitsCurrentPhpVersion($enum)); + }); + if (count($enums) === 1) { + return array_pop($enums); + } + + if ($sourceFilePath !== null) { + $enums = array_filter($enums, function (PHPEnum $enum) use ($shouldSuitCurrentPhpVersion, $sourceFilePath) { + return $enum->sourceFilePath === $sourceFilePath && + (!$shouldSuitCurrentPhpVersion || BasePHPElement::entitySuitsCurrentPhpVersion($enum)); + }); + } + if (count($enums) > 1) { + throw new RuntimeException("Multiple enums with name $name found"); + } + if (!empty($enums)) { + return array_pop($enums); + } + return null; + } + /** * @return PHPClass[] */ @@ -255,6 +292,14 @@ public function getInterfaces() return $this->interfaces; } + /** + * @return PHPEnum[] + */ + public function getEnums() + { + return $this->enums; + } + /** * @return PHPInterface[] */ @@ -281,4 +326,21 @@ function (PHPInterface $nextInterface) use ($interface) { } } } + + public function addEnum(PHPEnum $enum) + { + if (isset($enum->name)) { + if (array_key_exists($enum->name, $this->enums)) { + $amount = count(array_filter( + $this->enums, + function (PHPEnum $nextEnum) use ($enum) { + return $nextEnum->name === $enum->name; + } + )); + $this->enums[$enum->name . '_duplicated_' . $amount] = $enum; + } else { + $this->enums[$enum->name] = $enum; + } + } + } } diff --git a/tests/Parsers/PHPReflectionParser.php b/tests/Parsers/PHPReflectionParser.php index dc443b53c..4a6bb9159 100644 --- a/tests/Parsers/PHPReflectionParser.php +++ b/tests/Parsers/PHPReflectionParser.php @@ -7,6 +7,7 @@ use StubTests\Model\CommonUtils; use StubTests\Model\PHPClass; use StubTests\Model\PHPDefineConstant; +use StubTests\Model\PHPEnum; use StubTests\Model\PHPFunction; use StubTests\Model\PHPInterface; use StubTests\Model\StubsContainer; @@ -44,9 +45,15 @@ public static function getStubs() foreach (get_declared_classes() as $clazz) { $reflectionClass = new ReflectionClass($clazz); if ($reflectionClass->isInternal()) { - $class = (new PHPClass())->readObjectFromReflection($reflectionClass); - $class->readMutedProblems($jsonData->classes); - $stubs->addClass($class); + if (method_exists($reflectionClass, 'isEnum') && $reflectionClass->isEnum()) { + $enum = (new PHPEnum())->readObjectFromReflection($reflectionClass); + $enum->readMutedProblems($jsonData->enums); + $stubs->addEnum($enum); + } else { + $class = (new PHPClass())->readObjectFromReflection($reflectionClass); + $class->readMutedProblems($jsonData->classes); + $stubs->addClass($class); + } } } diff --git a/tests/Parsers/ParserUtils.php b/tests/Parsers/ParserUtils.php index c29b1db8c..a2b3b66d3 100644 --- a/tests/Parsers/ParserUtils.php +++ b/tests/Parsers/ParserUtils.php @@ -122,7 +122,10 @@ private static function getLatestAvailableVersionFromPhpDoc(BasePHPElement $elem */ private static function getSinceVersionsFromParentClass(PHPMethod|PHPConst $element): array { - $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getClass($element->parentName, shouldSuitCurrentPhpVersion: false); + $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($element->parentName, shouldSuitCurrentPhpVersion: false); + if ($parentClass === null) { + $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getClass($element->parentName, shouldSuitCurrentPhpVersion: false); + } if ($parentClass === null) { $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($element->parentName, shouldSuitCurrentPhpVersion: false); } @@ -137,7 +140,10 @@ private static function getSinceVersionsFromParentClass(PHPMethod|PHPConst $elem */ public static function getLatestAvailableVersionsFromParentClass(PHPMethod|PHPConst $element): array { - $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getClass($element->parentName, shouldSuitCurrentPhpVersion: false); + $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($element->parentName, shouldSuitCurrentPhpVersion: false); + if ($parentClass === null) { + $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getClass($element->parentName, shouldSuitCurrentPhpVersion: false); + } if ($parentClass === null) { $parentClass = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($element->parentName, shouldSuitCurrentPhpVersion: false); } diff --git a/tests/Parsers/Visitors/ASTVisitor.php b/tests/Parsers/Visitors/ASTVisitor.php index 95ea11494..4a83ef45d 100644 --- a/tests/Parsers/Visitors/ASTVisitor.php +++ b/tests/Parsers/Visitors/ASTVisitor.php @@ -8,6 +8,7 @@ use PhpParser\Node\Const_; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Stmt\Class_; +use PhpParser\Node\Stmt\Enum_; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; use PhpParser\Node\Stmt\Interface_; @@ -17,6 +18,8 @@ use StubTests\Model\PHPClass; use StubTests\Model\PHPConst; use StubTests\Model\PHPDefineConstant; +use StubTests\Model\PHPEnum; +use StubTests\Model\PHPEnumCase; use StubTests\Model\PHPFunction; use StubTests\Model\PHPInterface; use StubTests\Model\PHPMethod; @@ -43,6 +46,15 @@ public function enterNode(Node $node): void $function->stubBelongsToCore = true; } $this->stubs->addFunction($function); + } elseif ($node instanceof Node\Stmt\EnumCase) { + $constant = (new PHPEnumCase())->readObjectFromStubNode($node); + $constant->sourceFilePath = $this->sourceFilePath; + if ($this->isStubCore) { + $constant->stubBelongsToCore = true; + } + if ($this->stubs->getEnum($constant->parentName, $this->sourceFilePath, false) !== null) { + $this->stubs->getEnum($constant->parentName, $this->sourceFilePath, false)->addEnumCase($constant); + } } elseif ($node instanceof Const_) { $constant = (new PHPConst())->readObjectFromStubNode($node); $constant->sourceFilePath = $this->sourceFilePath; @@ -51,6 +63,8 @@ public function enterNode(Node $node): void } if ($constant->parentName === null) { $this->stubs->addConstant($constant); + } elseif ($this->stubs->getEnum($constant->parentName, $this->sourceFilePath, false) !== null) { + $this->stubs->getEnum($constant->parentName, $this->sourceFilePath, false)->addConstant($constant); } elseif ($this->stubs->getClass($constant->parentName, $this->sourceFilePath, false) !== null) { $this->stubs->getClass($constant->parentName, $this->sourceFilePath, false)->addConstant($constant); } elseif ($this->stubs->getInterface($constant->parentName, $this->sourceFilePath, false) !== null) { @@ -71,7 +85,10 @@ public function enterNode(Node $node): void if ($this->isStubCore) { $method->stubBelongsToCore = true; } - if ($this->stubs->getClass($method->parentName, $this->sourceFilePath, false) !== null) { + if ($this->stubs->getEnum($method->parentName, $this->sourceFilePath, false) !== null) { + $this->stubs->getEnum($method->parentName, $this->sourceFilePath, false)->addMethod($method); + } + elseif ($this->stubs->getClass($method->parentName, $this->sourceFilePath, false) !== null) { $this->stubs->getClass($method->parentName, $this->sourceFilePath, false)->addMethod($method); } elseif ($this->stubs->getInterface($method->parentName, $this->sourceFilePath, false) !== null) { $this->stubs->getInterface($method->parentName, $this->sourceFilePath, false)->addMethod($method); @@ -90,6 +107,13 @@ public function enterNode(Node $node): void $class->stubBelongsToCore = true; } $this->stubs->addClass($class); + } elseif ($node instanceof Enum_) { + $enum = (new PHPEnum())->readObjectFromStubNode($node); + $enum->sourceFilePath = $this->sourceFilePath; + if ($this->isStubCore) { + $enum->stubBelongsToCore = true; + } + $this->stubs->addEnum($enum); } elseif ($node instanceof Node\Stmt\Property) { $property = (new PHPProperty())->readObjectFromStubNode($node); $property->sourceFilePath = $this->sourceFilePath; diff --git a/tests/StubsConstantsAndParametersValuesTest.php b/tests/StubsConstantsAndParametersValuesTest.php index 6498e3240..cc2c58135 100644 --- a/tests/StubsConstantsAndParametersValuesTest.php +++ b/tests/StubsConstantsAndParametersValuesTest.php @@ -7,6 +7,7 @@ use RuntimeException; use StubTests\Model\PHPClass; use StubTests\Model\PHPConst; +use StubTests\Model\PHPEnum; use StubTests\Model\PHPFunction; use StubTests\Model\PHPInterface; use StubTests\Model\PHPMethod; @@ -62,7 +63,9 @@ public function testFunctionsDefaultParametersValue(PHPFunction $function, PHPPa */ public function testMethodsDefaultParametersValue(PHPClass|PHPInterface $class, PHPMethod $method, PHPParameter $parameter) { - if ($class instanceof PHPClass) { + if ($class instanceof PHPEnum) { + $phpstormFunction = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($class->name)->getMethod($method->name); + } elseif ($class instanceof PHPClass) { $phpstormFunction = PhpStormStubsSingleton::getPhpStormStubs()->getClass($class->name)->getMethod($method->name); } else { $phpstormFunction = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($class->name)->getMethod($method->name); diff --git a/tests/StubsTypeHintsTest.php b/tests/StubsTypeHintsTest.php index 9b152a395..5b84b6123 100644 --- a/tests/StubsTypeHintsTest.php +++ b/tests/StubsTypeHintsTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\Exception; use RuntimeException; use StubTests\Model\PHPClass; +use StubTests\Model\PHPEnum; use StubTests\Model\PHPFunction; use StubTests\Model\PHPInterface; use StubTests\Model\PHPMethod; @@ -85,7 +86,9 @@ public function testFunctionsParametersTypeHints(PHPFunction $function, PHPParam public function testMethodsReturnTypeHints(PHPClass|PHPInterface $class, PHPMethod $method) { $functionName = $method->name; - if ($class instanceof PHPClass) { + if ($class instanceof PHPEnum) { + $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getEnum($class->name)->getMethod($method->name); + } elseif ($class instanceof PHPClass) { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getClass($class->name)->getMethod($functionName); } else { $stubMethod = PhpStormStubsSingleton::getPhpStormStubs()->getInterface($class->name)->getMethod($functionName); diff --git a/tests/TestData/Providers/Reflection/ReflectionMethodsProvider.php b/tests/TestData/Providers/Reflection/ReflectionMethodsProvider.php index 0f036174b..56015c4e0 100644 --- a/tests/TestData/Providers/Reflection/ReflectionMethodsProvider.php +++ b/tests/TestData/Providers/Reflection/ReflectionMethodsProvider.php @@ -47,7 +47,8 @@ public static function classMethodsWithParametersProvider(): ?Generator public static function classMethodsWithoutTentitiveReturnTypeProvider(): ?Generator { $classesAndInterfaces = ReflectionStubsSingleton::getReflectionStubs()->getClasses() + - ReflectionStubsSingleton::getReflectionStubs()->getInterfaces(); + ReflectionStubsSingleton::getReflectionStubs()->getInterfaces() + + ReflectionStubsSingleton::getReflectionStubs()->getEnums(); foreach (EntitiesFilter::getFiltered($classesAndInterfaces) as $class) { foreach (EntitiesFilter::getFiltered( $class->methods, @@ -64,7 +65,8 @@ public static function classMethodsWithoutTentitiveReturnTypeProvider(): ?Genera public static function classMethodsWithTentitiveReturnTypeProvider(): ?Generator { $classesAndInterfaces = ReflectionStubsSingleton::getReflectionStubs()->getClasses() + - ReflectionStubsSingleton::getReflectionStubs()->getInterfaces(); + ReflectionStubsSingleton::getReflectionStubs()->getInterfaces() + + ReflectionStubsSingleton::getReflectionStubs()->getEnums(); foreach (EntitiesFilter::getFiltered($classesAndInterfaces) as $class) { foreach (EntitiesFilter::getFiltered( $class->methods, @@ -81,7 +83,8 @@ public static function classMethodsWithTentitiveReturnTypeProvider(): ?Generator private static function yieldFilteredMethods(int ...$problemTypes): ?Generator { $classesAndInterfaces = ReflectionStubsSingleton::getReflectionStubs()->getClasses() + - ReflectionStubsSingleton::getReflectionStubs()->getInterfaces(); + ReflectionStubsSingleton::getReflectionStubs()->getInterfaces() + + ReflectionStubsSingleton::getReflectionStubs()->getEnums(); foreach (EntitiesFilter::getFiltered($classesAndInterfaces) as $class) { foreach (EntitiesFilter::getFiltered($class->methods, null, ...$problemTypes) as $method) { yield "Method $class->name::$method->name" => [$class, $method]; diff --git a/tests/TestData/mutedProblems.json b/tests/TestData/mutedProblems.json index afb9962a4..31b8f6385 100644 --- a/tests/TestData/mutedProblems.json +++ b/tests/TestData/mutedProblems.json @@ -1052,6 +1052,17 @@ ] } ] + }, + { + "name": "hash_pbkdf2", + "problems": [ + { + "description": "parameter mismatch", + "versions": [ + 8.2 + ] + } + ] } ], "classes": [ @@ -1153,7 +1164,8 @@ "versions": [ 8.0, 8.1, - 8.2 + 8.2, + 8.3 ] } ], @@ -3214,7 +3226,8 @@ "versions": [ 8.0, 8.1, - 8.2 + 8.2, + 8.3 ] } ] @@ -3241,7 +3254,8 @@ "versions": [ 8.0, 8.1, - 8.2 + 8.2, + 8.3 ] } ] @@ -3331,5 +3345,6 @@ } ] } - ] + ], + "enums": [] } diff --git a/xml/xml.php b/xml/xml.php index 5d22a2a91..151fa8399 100644 --- a/xml/xml.php +++ b/xml/xml.php @@ -521,13 +521,14 @@ function xml_parser_set_option(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], * @param int $option Which option to fetch. XML_OPTION_CASE_FOLDING * and XML_OPTION_TARGET_ENCODING are available. * See xml_parser_set_option for their description. - * @return string|int This function returns FALSE if parser does + * @return string|int|bool This function returns FALSE if parser does * not refer to a valid parser or if option isn't * valid (generates also a E_WARNING). * Else the option's value is returned. */ #[Pure] -function xml_parser_get_option(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, int $option): string|int {} +#[LanguageLevelTypeAware(["8.3" => "string|int|bool"], default: "string|int")] +function xml_parser_get_option(#[LanguageLevelTypeAware(["8.0" => "XMLParser"], default: "resource")] $parser, int $option) {} define('XML_ERROR_NONE', 0); define('XML_ERROR_NO_MEMORY', 1); From 026ffd05f5a6c848e7481e21c5d62cc4adcd63ac Mon Sep 17 00:00:00 2001 From: Ivan Fedorov+ * @param string $string
* The string to be measured. *
- * @param array $extrainfo [optional]+ * @param array $options [optional]
*