Composer updates
This commit is contained in:
1
vendor/vimeo/psalm/composer.json
vendored
1
vendor/vimeo/psalm/composer.json
vendored
@@ -44,6 +44,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"amphp/phpunit-util": "^2.0",
|
||||
"bamarni/composer-bin-plugin": "^1.4",
|
||||
"brianium/paratest": "^6.9",
|
||||
"mockery/mockery": "^1.5",
|
||||
|
||||
3
vendor/vimeo/psalm/config.xsd
vendored
3
vendor/vimeo/psalm/config.xsd
vendored
@@ -62,6 +62,7 @@
|
||||
<xs:attribute name="reportMixedIssues" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="useDocblockTypes" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="useDocblockPropertyTypes" type="xs:boolean" default="false" />
|
||||
<xs:attribute name="docblockPropertyTypesSealProperties" type="xs:boolean" default="true" />
|
||||
<xs:attribute name="usePhpDocMethodsWithoutMagicCall" type="xs:boolean" default="false" />
|
||||
<xs:attribute name="usePhpDocPropertiesWithoutMagicCall" type="xs:boolean" default="false" />
|
||||
<xs:attribute name="skipChecksOnUnresolvableIncludes" type="xs:boolean" default="false" />
|
||||
@@ -249,6 +250,7 @@
|
||||
<xs:element name="InaccessibleClassConstant" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="InaccessibleMethod" type="MethodIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="InaccessibleProperty" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="InheritorViolation" type="ClassIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="InterfaceInstantiation" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="InternalClass" type="ClassIssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="InternalMethod" type="MethodIssueHandlerType" minOccurs="0" />
|
||||
@@ -480,6 +482,7 @@
|
||||
<xs:element name="UnresolvableInclude" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UnsafeGenericInstantiation" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UnsafeInstantiation" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UnsupportedPropertyReferenceUsage" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UnsupportedReferenceUsage" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UnusedBaselineEntry" type="IssueHandlerType" minOccurs="0" />
|
||||
<xs:element name="UnusedClass" type="ClassIssueHandlerType" minOccurs="0" />
|
||||
|
||||
333
vendor/vimeo/psalm/dictionaries/CallMap.php
vendored
333
vendor/vimeo/psalm/dictionaries/CallMap.php
vendored
@@ -418,9 +418,7 @@ return [
|
||||
'array_uintersect_assoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable', '...rest='=>'array|callable(mixed,mixed):int'],
|
||||
'array_uintersect_uassoc' => ['array', 'array'=>'array', 'rest'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int', 'key_compare_func'=>'callable(mixed,mixed):int'],
|
||||
'array_uintersect_uassoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'],
|
||||
'array_unique' => ['array', 'array'=>'array', 'flags='=>'0'],
|
||||
'array_unique\'1' => ['array<int|float|string|null>', 'array'=>'array<int|float|string|null>', 'flags='=>'1'],
|
||||
'array_unique\'2' => ['array<int|float|string|bool|\Stringable|null>', 'array'=>'array<int|float|string|bool|\Stringable|null>', 'flags='=>'2|5'],
|
||||
'array_unique' => ['array', 'array'=>'array', 'flags='=>'int'],
|
||||
'array_unshift' => ['int', '&rw_array'=>'array', '...values='=>'mixed'],
|
||||
'array_values' => ['list<mixed>', 'array'=>'array'],
|
||||
'array_walk' => ['bool', '&rw_array'=>'array', 'callback'=>'callable', 'arg='=>'mixed'],
|
||||
@@ -612,7 +610,7 @@ return [
|
||||
'CallbackFilterIterator::next' => ['void'],
|
||||
'CallbackFilterIterator::rewind' => ['void'],
|
||||
'CallbackFilterIterator::valid' => ['bool'],
|
||||
'ceil' => ['float', 'num'=>'float'],
|
||||
'ceil' => ['float', 'num'=>'float|int'],
|
||||
'chdb::__construct' => ['void', 'pathname'=>'string'],
|
||||
'chdb::get' => ['string', 'key'=>'string'],
|
||||
'chdb_create' => ['bool', 'pathname'=>'string', 'data'=>'array'],
|
||||
@@ -1260,7 +1258,7 @@ return [
|
||||
'cubrid_unbuffered_query' => ['resource', 'query'=>'string', 'conn_identifier='=>''],
|
||||
'cubrid_version' => ['string'],
|
||||
'curl_close' => ['void', 'handle'=>'CurlHandle'],
|
||||
'curl_copy_handle' => ['CurlHandle', 'handle'=>'CurlHandle'],
|
||||
'curl_copy_handle' => ['CurlHandle|false', 'handle'=>'CurlHandle'],
|
||||
'curl_errno' => ['int', 'handle'=>'CurlHandle'],
|
||||
'curl_error' => ['string', 'handle'=>'CurlHandle'],
|
||||
'curl_escape' => ['string|false', 'handle'=>'CurlHandle', 'string'=>'string'],
|
||||
@@ -1293,7 +1291,6 @@ return [
|
||||
'curl_unescape' => ['string|false', 'handle'=>'CurlHandle', 'string'=>'string'],
|
||||
'curl_version' => ['array', 'version='=>'int'],
|
||||
'CURLFile::__construct' => ['void', 'filename'=>'string', 'mime_type='=>'?string', 'posted_filename='=>'?string'],
|
||||
'CURLFile::__wakeup' => ['void'],
|
||||
'CURLFile::getFilename' => ['string'],
|
||||
'CURLFile::getMimeType' => ['string'],
|
||||
'CURLFile::getPostFilename' => ['string'],
|
||||
@@ -1321,7 +1318,7 @@ return [
|
||||
'date_get_last_errors' => ['array{warning_count:int,warnings:array<int,string>,error_count:int,errors:array<int,string>}|false'],
|
||||
'date_interval_create_from_date_string' => ['DateInterval', 'datetime'=>'string'],
|
||||
'date_interval_format' => ['string', 'object'=>'DateInterval', 'format'=>'string'],
|
||||
'date_isodate_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'dayOfWeek='=>'int|mixed'],
|
||||
'date_isodate_set' => ['DateTime', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'dayOfWeek='=>'int'],
|
||||
'date_modify' => ['DateTime|false', 'object'=>'DateTime', 'modifier'=>'string'],
|
||||
'date_offset_get' => ['int', 'object'=>'DateTimeInterface'],
|
||||
'date_parse' => ['array', 'datetime'=>'string'],
|
||||
@@ -1350,7 +1347,7 @@ return [
|
||||
'datefmt_get_timezone_id' => ['string|false', 'formatter'=>'IntlDateFormatter'],
|
||||
'datefmt_is_lenient' => ['bool', 'formatter'=>'IntlDateFormatter'],
|
||||
'datefmt_localtime' => ['array|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
|
||||
'datefmt_parse' => ['int|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
|
||||
'datefmt_parse' => ['float|int|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
|
||||
'datefmt_set_calendar' => ['bool', 'formatter'=>'IntlDateFormatter', 'calendar'=>'IntlCalendar|int|null'],
|
||||
'datefmt_set_lenient' => ['void', 'formatter'=>'IntlDateFormatter', 'lenient'=>'bool'],
|
||||
'datefmt_set_pattern' => ['bool', 'formatter'=>'IntlDateFormatter', 'pattern'=>'string'],
|
||||
@@ -1463,20 +1460,20 @@ return [
|
||||
'db2_tableprivileges' => [''],
|
||||
'db2_tables' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'?string', 'schema='=>'?string', 'table_name='=>'?string', 'table_type='=>'?string'],
|
||||
'dba_close' => ['void', 'dba'=>'resource'],
|
||||
'dba_delete' => ['bool', 'key'=>'string', 'dba'=>'resource'],
|
||||
'dba_exists' => ['bool', 'key'=>'string', 'dba'=>'resource'],
|
||||
'dba_fetch' => ['string|false', 'key'=>'string', 'skip'=>'int', 'dba'=>'resource'],
|
||||
'dba_fetch\'1' => ['string|false', 'key'=>'string', 'skip'=>'resource'],
|
||||
'dba_delete' => ['bool', 'key'=>'array|string', 'dba'=>'resource'],
|
||||
'dba_exists' => ['bool', 'key'=>'array|string', 'dba'=>'resource'],
|
||||
'dba_fetch' => ['string|false', 'key'=>'array|string', 'skip'=>'int', 'dba'=>'resource'],
|
||||
'dba_fetch\'1' => ['string|false', 'key'=>'array|string', 'skip'=>'resource'],
|
||||
'dba_firstkey' => ['string', 'dba'=>'resource'],
|
||||
'dba_handlers' => ['array', 'full_info='=>'bool'],
|
||||
'dba_insert' => ['bool', 'key'=>'string', 'value'=>'string', 'dba'=>'resource'],
|
||||
'dba_insert' => ['bool', 'key'=>'array|string', 'value'=>'string', 'dba'=>'resource'],
|
||||
'dba_key_split' => ['array|false', 'key'=>'string|false|null'],
|
||||
'dba_list' => ['array'],
|
||||
'dba_nextkey' => ['string', 'dba'=>'resource'],
|
||||
'dba_open' => ['resource', 'path'=>'string', 'mode'=>'string', 'handler='=>'?string', 'permission='=>'int', 'map_size='=>'int', 'flags='=>'?int'],
|
||||
'dba_optimize' => ['bool', 'dba'=>'resource'],
|
||||
'dba_popen' => ['resource', 'path'=>'string', 'mode'=>'string', 'handler='=>'?string', 'permission='=>'int', 'map_size='=>'int', 'flags='=>'?int'],
|
||||
'dba_replace' => ['bool', 'key'=>'string', 'value'=>'string', 'dba'=>'resource'],
|
||||
'dba_replace' => ['bool', 'key'=>'array|string', 'value'=>'string', 'dba'=>'resource'],
|
||||
'dba_sync' => ['bool', 'dba'=>'resource'],
|
||||
'dbase_add_record' => ['bool', 'dbase_identifier'=>'resource', 'record'=>'array'],
|
||||
'dbase_close' => ['bool', 'dbase_identifier'=>'resource'],
|
||||
@@ -1990,7 +1987,7 @@ return [
|
||||
'Ds\Vector::sum' => ['int|float'],
|
||||
'Ds\Vector::toArray' => ['array'],
|
||||
'Ds\Vector::unshift' => ['void', '...values='=>'mixed'],
|
||||
'easter_date' => ['int', 'year='=>'?int'],
|
||||
'easter_date' => ['int', 'year='=>'?int', 'mode='=>'int'],
|
||||
'easter_days' => ['int', 'year='=>'?int', 'mode='=>'int'],
|
||||
'echo' => ['void', 'arg1'=>'string', '...args='=>'string'],
|
||||
'eio_busy' => ['resource', 'delay'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'],
|
||||
@@ -2882,7 +2879,7 @@ return [
|
||||
'finfo_set_flags' => ['bool', 'finfo'=>'finfo', 'flags'=>'int'],
|
||||
'floatval' => ['float', 'value'=>'mixed'],
|
||||
'flock' => ['bool', 'stream'=>'resource', 'operation'=>'int', '&w_would_block='=>'int'],
|
||||
'floor' => ['float', 'num'=>'float'],
|
||||
'floor' => ['float', 'num'=>'float|int'],
|
||||
'flush' => ['void'],
|
||||
'fmod' => ['float', 'num1'=>'float', 'num2'=>'float'],
|
||||
'fnmatch' => ['bool', 'pattern'=>'string', 'filename'=>'string', 'flags='=>'int'],
|
||||
@@ -3159,7 +3156,6 @@ return [
|
||||
'Gender\Gender::get' => ['int', 'name'=>'string', 'country='=>'int'],
|
||||
'Gender\Gender::isNick' => ['array', 'name0'=>'string', 'name1'=>'string', 'country='=>'int'],
|
||||
'Gender\Gender::similarNames' => ['array', 'name'=>'string', 'country='=>'int'],
|
||||
'Generator::__wakeup' => ['void'],
|
||||
'Generator::current' => ['mixed'],
|
||||
'Generator::getReturn' => ['mixed'],
|
||||
'Generator::key' => ['mixed'],
|
||||
@@ -3280,8 +3276,8 @@ return [
|
||||
'get_called_class' => ['class-string'],
|
||||
'get_cfg_var' => ['string|false', 'option'=>'string'],
|
||||
'get_class' => ['class-string', 'object='=>'object'],
|
||||
'get_class_methods' => ['list<string>', 'object_or_class'=>'object|class-string'],
|
||||
'get_class_vars' => ['array<string,mixed>', 'class'=>'string'],
|
||||
'get_class_methods' => ['list<non-falsy-string>', 'object_or_class'=>'object|class-string'],
|
||||
'get_class_vars' => ['array<non-falsy-string,mixed>', 'class'=>'string'],
|
||||
'get_current_user' => ['string'],
|
||||
'get_debug_type' => ['string', 'value'=>'mixed'],
|
||||
'get_declared_classes' => ['list<class-string>'],
|
||||
@@ -3333,7 +3329,7 @@ return [
|
||||
'gettimeofday' => ['array<string, int>'],
|
||||
'gettimeofday\'1' => ['float', 'as_float='=>'true'],
|
||||
'gettype' => ['string', 'value'=>'mixed'],
|
||||
'glob' => ['list<string>|false', 'pattern'=>'string', 'flags='=>'int'],
|
||||
'glob' => ['list<non-empty-string>|false', 'pattern'=>'non-empty-string', 'flags='=>'int<1, max>'],
|
||||
'GlobIterator::__construct' => ['void', 'pattern'=>'string', 'flags='=>'int'],
|
||||
'GlobIterator::count' => ['int'],
|
||||
'GlobIterator::current' => ['FilesystemIterator|SplFileInfo|string'],
|
||||
@@ -3555,9 +3551,7 @@ return [
|
||||
'GmagickPixel::setcolorvalue' => ['GmagickPixel', 'color'=>'int', 'value'=>'float'],
|
||||
'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int|null'],
|
||||
'gmmktime' => ['int|false', 'hour'=>'int', 'minute='=>'int|null', 'second='=>'int|null', 'month='=>'int|null', 'day='=>'int|null', 'year='=>'int|null'],
|
||||
'GMP::__construct' => ['void'],
|
||||
'GMP::__serialize' => ['array'],
|
||||
'GMP::__toString' => ['numeric-string'],
|
||||
'GMP::__unserialize' => ['void', 'data'=>'array'],
|
||||
'gmp_abs' => ['GMP', 'num'=>'GMP|string|int'],
|
||||
'gmp_add' => ['GMP', 'num1'=>'GMP|string|int', 'num2'=>'GMP|string|int'],
|
||||
@@ -3742,19 +3736,19 @@ return [
|
||||
'gzdeflate' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'],
|
||||
'gzencode' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'],
|
||||
'gzeof' => ['bool', 'stream'=>'resource'],
|
||||
'gzfile' => ['list<string>', 'filename'=>'string', 'use_include_path='=>'int'],
|
||||
'gzfile' => ['list<string>|false', 'filename'=>'string', 'use_include_path='=>'int'],
|
||||
'gzgetc' => ['string|false', 'stream'=>'resource'],
|
||||
'gzgets' => ['string|false', 'stream'=>'resource', 'length='=>'?int'],
|
||||
'gzinflate' => ['string|false', 'data'=>'string', 'max_length='=>'int'],
|
||||
'gzopen' => ['resource|false', 'filename'=>'string', 'mode'=>'string', 'use_include_path='=>'int'],
|
||||
'gzpassthru' => ['int', 'stream'=>'resource'],
|
||||
'gzputs' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
'gzputs' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
'gzread' => ['string|false', 'stream'=>'resource', 'length'=>'int'],
|
||||
'gzrewind' => ['bool', 'stream'=>'resource'],
|
||||
'gzseek' => ['int', 'stream'=>'resource', 'offset'=>'int', 'whence='=>'int'],
|
||||
'gztell' => ['int|false', 'stream'=>'resource'],
|
||||
'gzuncompress' => ['string|false', 'data'=>'string', 'max_length='=>'int'],
|
||||
'gzwrite' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
'gzwrite' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
'HaruAnnotation::setBorderStyle' => ['bool', 'width'=>'float', 'dash_on'=>'int', 'dash_off'=>'int'],
|
||||
'HaruAnnotation::setHighlightMode' => ['bool', 'mode'=>'int'],
|
||||
'HaruAnnotation::setIcon' => ['bool', 'icon'=>'int'],
|
||||
@@ -6129,10 +6123,10 @@ return [
|
||||
'Iterator::rewind' => ['void'],
|
||||
'Iterator::valid' => ['bool'],
|
||||
'iterator_apply' => ['0|positive-int', 'iterator'=>'Traversable', 'callback'=>'callable(mixed):bool', 'args='=>'?array'],
|
||||
'iterator_count' => ['0|positive-int', 'iterator'=>'Traversable'],
|
||||
'iterator_to_array' => ['array', 'iterator'=>'Traversable', 'preserve_keys='=>'bool'],
|
||||
'iterator_count' => ['0|positive-int', 'iterator'=>'Traversable|array'],
|
||||
'iterator_to_array' => ['array', 'iterator'=>'Traversable|array', 'preserve_keys='=>'bool'],
|
||||
'IteratorAggregate::getIterator' => ['Traversable'],
|
||||
'IteratorIterator::__construct' => ['void', 'it'=>'Traversable'],
|
||||
'IteratorIterator::__construct' => ['void', 'iterator'=>'Traversable', 'class='=>'?string'],
|
||||
'IteratorIterator::current' => ['mixed'],
|
||||
'IteratorIterator::getInnerIterator' => ['Iterator'],
|
||||
'IteratorIterator::key' => ['mixed'],
|
||||
@@ -6164,7 +6158,7 @@ return [
|
||||
'json_last_error_msg' => ['string'],
|
||||
'json_validate' => ['bool', 'json'=>'string', 'depth='=>'positive-int', 'flags='=>'int'],
|
||||
'JsonException::__clone' => ['void'],
|
||||
'JsonException::__construct' => ['void'],
|
||||
'JsonException::__construct' => ['void', "message="=>"string", 'code='=>'int', 'previous='=>'?Throwable'],
|
||||
'JsonException::__toString' => ['string'],
|
||||
'JsonException::__wakeup' => ['void'],
|
||||
'JsonException::getCode' => ['int'],
|
||||
@@ -6339,7 +6333,7 @@ return [
|
||||
'ldap_count_entries' => ['int', 'ldap'=>'LDAP\Connection', 'result'=>'LDAP\Result'],
|
||||
'ldap_delete' => ['bool', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'controls='=>'?array'],
|
||||
'ldap_delete_ext' => ['LDAP\Result|false', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'controls='=>'?array'],
|
||||
'ldap_dn2ufn' => ['string', 'dn'=>'string'],
|
||||
'ldap_dn2ufn' => ['string|false', 'dn'=>'string'],
|
||||
'ldap_err2str' => ['string', 'errno'=>'int'],
|
||||
'ldap_errno' => ['int', 'ldap'=>'LDAP\Connection'],
|
||||
'ldap_error' => ['string', 'ldap'=>'LDAP\Connection'],
|
||||
@@ -6359,7 +6353,7 @@ return [
|
||||
'ldap_get_option' => ['bool', 'ldap'=>'LDAP\Connection', 'option'=>'int', '&w_value='=>'array|string|int'],
|
||||
'ldap_get_values' => ['array|false', 'ldap'=>'LDAP\Connection', 'entry'=>'LDAP\ResultEntry', 'attribute'=>'string'],
|
||||
'ldap_get_values_len' => ['array|false', 'ldap'=>'LDAP\Connection', 'entry'=>'LDAP\ResultEntry', 'attribute'=>'string'],
|
||||
'ldap_list' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'ldap_list' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'ldap_mod_add' => ['bool', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'entry'=>'array', 'controls='=>'?array'],
|
||||
'ldap_mod_add_ext' => ['LDAP\Result|false', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'entry'=>'array', 'controls='=>'?array'],
|
||||
'ldap_mod_del' => ['bool', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'entry'=>'array', 'controls='=>'?array'],
|
||||
@@ -6374,11 +6368,11 @@ return [
|
||||
'ldap_parse_exop' => ['bool', 'ldap'=>'LDAP\Connection', 'result'=>'LDAP\Result', '&w_response_data='=>'string', '&w_response_oid='=>'string'],
|
||||
'ldap_parse_reference' => ['bool', 'ldap'=>'LDAP\Connection', 'entry'=>'LDAP\ResultEntry', '&w_referrals'=>'array'],
|
||||
'ldap_parse_result' => ['bool', 'ldap'=>'LDAP\Connection', 'result'=>'LDAP\Result', '&w_error_code'=>'int', '&w_matched_dn='=>'string', '&w_error_message='=>'string', '&w_referrals='=>'array', '&w_controls='=>'array'],
|
||||
'ldap_read' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'ldap_read' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'ldap_rename' => ['bool', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'?array'],
|
||||
'ldap_rename_ext' => ['LDAP\Result|false', 'ldap'=>'LDAP\Connection', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'?array'],
|
||||
'ldap_sasl_bind' => ['bool', 'ldap'=>'LDAP\Connection', 'dn='=>'?string', 'password='=>'?string', 'mech='=>'?string', 'realm='=>'?string', 'authc_id='=>'?string', 'authz_id='=>'?string', 'props='=>'?string'],
|
||||
'ldap_search' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'ldap_search' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'ldap_set_option' => ['bool', 'ldap'=>'LDAP\Connection|null', 'option'=>'int', 'value'=>'mixed'],
|
||||
'ldap_set_rebind_proc' => ['bool', 'ldap'=>'LDAP\Connection', 'callback'=>'?callable'],
|
||||
'ldap_start_tls' => ['bool', 'ldap'=>'LDAP\Connection'],
|
||||
@@ -6442,14 +6436,14 @@ return [
|
||||
'libxml_set_external_entity_loader' => ['bool', 'resolver_function'=>'(callable(string,string,array{directory:?string,intSubName:?string,extSubURI:?string,extSubSystem:?string}):(resource|string|null))|null'],
|
||||
'libxml_set_streams_context' => ['void', 'context'=>'resource'],
|
||||
'libxml_use_internal_errors' => ['bool', 'use_errors='=>'?bool'],
|
||||
'LimitIterator::__construct' => ['void', 'iterator'=>'Iterator', 'offset='=>'int', 'count='=>'int'],
|
||||
'LimitIterator::__construct' => ['void', 'iterator'=>'Iterator', 'offset='=>'int', 'limit='=>'int'],
|
||||
'LimitIterator::current' => ['mixed'],
|
||||
'LimitIterator::getInnerIterator' => ['Iterator'],
|
||||
'LimitIterator::getPosition' => ['int'],
|
||||
'LimitIterator::key' => ['mixed'],
|
||||
'LimitIterator::next' => ['void'],
|
||||
'LimitIterator::rewind' => ['void'],
|
||||
'LimitIterator::seek' => ['int', 'position'=>'int'],
|
||||
'LimitIterator::seek' => ['int', 'offset'=>'int'],
|
||||
'LimitIterator::valid' => ['bool'],
|
||||
'lineObj::__construct' => ['void'],
|
||||
'lineObj::add' => ['int', 'point'=>'pointObj'],
|
||||
@@ -6848,14 +6842,14 @@ return [
|
||||
'memory_reset_peak_usage' => ['void'],
|
||||
'MessageFormatter::__construct' => ['void', 'locale'=>'string', 'pattern'=>'string'],
|
||||
'MessageFormatter::create' => ['MessageFormatter', 'locale'=>'string', 'pattern'=>'string'],
|
||||
'MessageFormatter::format' => ['false|string', 'args'=>'array'],
|
||||
'MessageFormatter::formatMessage' => ['false|string', 'locale'=>'string', 'pattern'=>'string', 'args'=>'array'],
|
||||
'MessageFormatter::format' => ['false|string', 'values'=>'array'],
|
||||
'MessageFormatter::formatMessage' => ['false|string', 'locale'=>'string', 'pattern'=>'string', 'values'=>'array'],
|
||||
'MessageFormatter::getErrorCode' => ['int'],
|
||||
'MessageFormatter::getErrorMessage' => ['string'],
|
||||
'MessageFormatter::getLocale' => ['string'],
|
||||
'MessageFormatter::getPattern' => ['string'],
|
||||
'MessageFormatter::parse' => ['array|false', 'value'=>'string'],
|
||||
'MessageFormatter::parseMessage' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'source'=>'string'],
|
||||
'MessageFormatter::parse' => ['array|false', 'string'=>'string'],
|
||||
'MessageFormatter::parseMessage' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'message'=>'string'],
|
||||
'MessageFormatter::setPattern' => ['bool', 'pattern'=>'string'],
|
||||
'metaphone' => ['string', 'string'=>'string', 'max_phonemes='=>'int'],
|
||||
'method_exists' => ['bool', 'object_or_class'=>'object|class-string|interface-string|enum-string', 'method'=>'string'],
|
||||
@@ -7065,7 +7059,7 @@ return [
|
||||
'MongoDB::setReadPreference' => ['bool', 'read_preference'=>'string', 'tags='=>'array'],
|
||||
'MongoDB::setSlaveOkay' => ['bool', 'ok='=>'bool'],
|
||||
'MongoDB::setWriteConcern' => ['bool', 'w'=>'mixed', 'wtimeout='=>'int'],
|
||||
'MongoDB\BSON\Binary::__construct' => ['void', 'data' => 'string', 'type' => 'int'],
|
||||
'MongoDB\BSON\Binary::__construct' => ['void', 'data' => 'string', 'type=' => 'int'],
|
||||
'MongoDB\BSON\Binary::getData' => ['string'],
|
||||
'MongoDB\BSON\Binary::getType' => ['int'],
|
||||
'MongoDB\BSON\Binary::__toString' => ['string'],
|
||||
@@ -7623,7 +7617,7 @@ return [
|
||||
'mt_rand\'1' => ['int'],
|
||||
'mt_srand' => ['void', 'seed='=>'int', 'mode='=>'int'],
|
||||
'MultipleIterator::__construct' => ['void', 'flags='=>'int'],
|
||||
'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'infos='=>'string'],
|
||||
'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'info='=>'string|int|null'],
|
||||
'MultipleIterator::containsIterator' => ['bool', 'iterator'=>'Iterator'],
|
||||
'MultipleIterator::countIterators' => ['int'],
|
||||
'MultipleIterator::current' => ['array|false'],
|
||||
@@ -7811,7 +7805,6 @@ return [
|
||||
'mysqli::commit' => ['bool', 'flags='=>'int', 'name='=>'?string'],
|
||||
'mysqli::connect' => ['bool', 'hostname='=>'string|null', 'username='=>'string|null', 'password='=>'string|null', 'database='=>'string|null', 'port='=>'int|null', 'socket='=>'string|null'],
|
||||
'mysqli::debug' => ['bool', 'options'=>'string'],
|
||||
'mysqli::disable_reads_from_master' => ['bool'],
|
||||
'mysqli::dump_debug_info' => ['bool'],
|
||||
'mysqli::escape_string' => ['string', 'string'=>'string'],
|
||||
'mysqli::execute_query' => ['mysqli_result|bool', 'query'=>'non-empty-string', 'params='=>'list<mixed>|null'],
|
||||
@@ -7826,23 +7819,19 @@ return [
|
||||
'mysqli::next_result' => ['bool'],
|
||||
'mysqli::options' => ['bool', 'option'=>'int', 'value'=>'string|int'],
|
||||
'mysqli::ping' => ['bool'],
|
||||
'mysqli::poll' => ['int|false', '&w_read'=>'array', '&w_write'=>'array', '&w_error'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
|
||||
'mysqli::poll' => ['int|false', '&w_read'=>'?array', '&w_error'=>'?array', '&w_reject'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
|
||||
'mysqli::prepare' => ['mysqli_stmt|false', 'query'=>'string'],
|
||||
'mysqli::query' => ['bool|mysqli_result', 'query'=>'string', 'result_mode='=>'int'],
|
||||
'mysqli::real_connect' => ['bool', 'hostname='=>'string|null', 'username='=>'string|null', 'password='=>'string|null', 'database='=>'string|null', 'port='=>'int|null', 'socket='=>'string|null', 'flags='=>'int'],
|
||||
'mysqli::real_connect' => ['bool', 'hostname='=>'?string', 'username='=>'?string', 'password='=>'?string', 'database='=>'?string', 'port='=>'?int', 'socket='=>'?string', 'flags='=>'int'],
|
||||
'mysqli::real_escape_string' => ['string', 'string'=>'string'],
|
||||
'mysqli::real_query' => ['bool', 'query'=>'string'],
|
||||
'mysqli::reap_async_query' => ['mysqli_result|false'],
|
||||
'mysqli::refresh' => ['bool', 'flags'=>'int'],
|
||||
'mysqli::release_savepoint' => ['bool', 'name'=>'string'],
|
||||
'mysqli::rollback' => ['bool', 'flags='=>'int', 'name='=>'?string'],
|
||||
'mysqli::rpl_query_type' => ['int', 'query'=>'string'],
|
||||
'mysqli::savepoint' => ['bool', 'name'=>'string'],
|
||||
'mysqli::select_db' => ['bool', 'database'=>'string'],
|
||||
'mysqli::send_query' => ['bool', 'query'=>'string'],
|
||||
'mysqli::set_charset' => ['bool', 'charset'=>'string'],
|
||||
'mysqli::set_local_infile_default' => ['void'],
|
||||
'mysqli::set_local_infile_handler' => ['bool', 'read_func='=>'callable'],
|
||||
'mysqli::set_opt' => ['bool', 'option'=>'int', 'value'=>'string|int'],
|
||||
'mysqli::ssl_set' => ['bool', 'key'=>'?string', 'certificate'=>'?string', 'ca_certificate'=>'?string', 'ca_path'=>'?string', 'cipher_algos'=>'?string'],
|
||||
'mysqli::stat' => ['string|false'],
|
||||
@@ -7864,8 +7853,6 @@ return [
|
||||
'mysqli_debug' => ['true', 'options'=>'string'],
|
||||
'mysqli_disable_reads_from_master' => ['bool', 'link'=>'mysqli'],
|
||||
'mysqli_disable_rpl_parse' => ['bool', 'link'=>'mysqli'],
|
||||
'mysqli_driver::embedded_server_end' => ['void'],
|
||||
'mysqli_driver::embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'],
|
||||
'mysqli_dump_debug_info' => ['bool', 'mysql'=>'mysqli'],
|
||||
'mysqli_embedded_server_end' => ['void'],
|
||||
'mysqli_embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'],
|
||||
@@ -7885,9 +7872,9 @@ return [
|
||||
'mysqli_fetch_array\'2' => ['list<null|int|float|string>|false|null', 'result'=>'mysqli_result', 'mode='=>'2'],
|
||||
'mysqli_fetch_assoc' => ['array<string,null|int|float|string>|false|null', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_column' => ['null|int|float|string|false', 'result'=>'mysqli_result', 'column='=>'int'],
|
||||
'mysqli_fetch_field' => ['object|false', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_field_direct' => ['object|false', 'result'=>'mysqli_result', 'index'=>'int'],
|
||||
'mysqli_fetch_fields' => ['stdClass[]', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_field' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_field_direct' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'result'=>'mysqli_result', 'index'=>'int'],
|
||||
'mysqli_fetch_fields' => ['list<object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}>', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_lengths' => ['array|false', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_object' => ['object|false|null', 'result'=>'mysqli_result', 'class='=>'string', 'constructor_args='=>'array'],
|
||||
'mysqli_fetch_row' => ['list<null|int|float|string>|false|null', 'result'=>'mysqli_result'],
|
||||
@@ -7920,10 +7907,10 @@ return [
|
||||
'mysqli_num_rows' => ['int<0, max>|numeric-string', 'result'=>'mysqli_result'],
|
||||
'mysqli_options' => ['bool', 'mysql'=>'mysqli', 'option'=>'int', 'value'=>'string|int'],
|
||||
'mysqli_ping' => ['bool', 'mysql'=>'mysqli'],
|
||||
'mysqli_poll' => ['int|false', 'read'=>'array', 'write'=>'array', 'error'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
|
||||
'mysqli_poll' => ['int|false', '&w_read'=>'?array', '&w_error'=>'?array', '&w_reject'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
|
||||
'mysqli_prepare' => ['mysqli_stmt|false', 'mysql'=>'mysqli', 'query'=>'string'],
|
||||
'mysqli_query' => ['mysqli_result|bool', 'mysql'=>'mysqli', 'query'=>'string', 'result_mode='=>'int'],
|
||||
'mysqli_real_connect' => ['bool', 'mysql='=>'mysqli', 'hostname='=>'string|null', 'username='=>'string|null', 'password='=>'string|null', 'database='=>'string|null', 'port='=>'int|null', 'socket='=>'string|null', 'flags='=>'int'],
|
||||
'mysqli_real_connect' => ['bool', 'mysql'=>'mysqli', 'hostname='=>'?string', 'username='=>'?string', 'password='=>'?string', 'database='=>'?string', 'port='=>'?int', 'socket='=>'?string', 'flags='=>'int'],
|
||||
'mysqli_real_escape_string' => ['string', 'mysql'=>'mysqli', 'string'=>'string'],
|
||||
'mysqli_real_query' => ['bool', 'mysql'=>'mysqli', 'query'=>'string'],
|
||||
'mysqli_reap_async_query' => ['mysqli_result|false', 'mysql'=>'mysqli'],
|
||||
@@ -7941,9 +7928,9 @@ return [
|
||||
'mysqli_result::fetch_array\'2' => ['list<null|int|float|string>|false|null', 'mode='=>'2'],
|
||||
'mysqli_result::fetch_assoc' => ['array<string,null|int|float|string>|false|null'],
|
||||
'mysqli_result::fetch_column' => ['null|int|float|string|false', 'column='=>'int'],
|
||||
'mysqli_result::fetch_field' => ['object|false'],
|
||||
'mysqli_result::fetch_field_direct' => ['object|false', 'index'=>'int'],
|
||||
'mysqli_result::fetch_fields' => ['stdClass[]'],
|
||||
'mysqli_result::fetch_field' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false'],
|
||||
'mysqli_result::fetch_field_direct' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'index'=>'int'],
|
||||
'mysqli_result::fetch_fields' => ['list<object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}>'],
|
||||
'mysqli_result::fetch_object' => ['object|false|null', 'class='=>'string', 'constructor_args='=>'array'],
|
||||
'mysqli_result::fetch_row' => ['list<null|int|float|string>|false|null'],
|
||||
'mysqli_result::field_seek' => ['bool', 'index'=>'int'],
|
||||
@@ -7965,10 +7952,10 @@ return [
|
||||
'mysqli_sqlstate' => ['string', 'mysql'=>'mysqli'],
|
||||
'mysqli_ssl_set' => ['true', 'mysql'=>'mysqli', 'key'=>'?string', 'certificate'=>'?string', 'ca_certificate'=>'?string', 'ca_path'=>'?string', 'cipher_algos'=>'?string'],
|
||||
'mysqli_stat' => ['string|false', 'mysql'=>'mysqli'],
|
||||
'mysqli_stmt::__construct' => ['void', 'mysql'=>'mysqli', 'query'=>'string'],
|
||||
'mysqli_stmt::__construct' => ['void', 'mysql'=>'mysqli', 'query='=>'?string'],
|
||||
'mysqli_stmt::attr_get' => ['int', 'attribute'=>'int'],
|
||||
'mysqli_stmt::attr_set' => ['bool', 'attribute'=>'int', 'value'=>'int'],
|
||||
'mysqli_stmt::bind_param' => ['bool', 'types'=>'string', '&vars'=>'mixed', '&...args='=>'mixed'],
|
||||
'mysqli_stmt::bind_param' => ['bool', 'types'=>'string', '&var'=>'mixed', '&...vars='=>'mixed'],
|
||||
'mysqli_stmt::bind_result' => ['bool', '&w_var1'=>'', '&...w_vars='=>''],
|
||||
'mysqli_stmt::close' => ['bool'],
|
||||
'mysqli_stmt::data_seek' => ['void', 'offset'=>'int'],
|
||||
@@ -7988,7 +7975,7 @@ return [
|
||||
'mysqli_stmt_affected_rows' => ['int<-1, max>|numeric-string', 'statement'=>'mysqli_stmt'],
|
||||
'mysqli_stmt_attr_get' => ['int', 'statement'=>'mysqli_stmt', 'attribute'=>'int'],
|
||||
'mysqli_stmt_attr_set' => ['bool', 'statement'=>'mysqli_stmt', 'attribute'=>'int', 'value'=>'int'],
|
||||
'mysqli_stmt_bind_param' => ['bool', 'statement'=>'mysqli_stmt', 'types'=>'string', '&vars'=>'mixed', '&...args='=>'mixed'],
|
||||
'mysqli_stmt_bind_param' => ['bool', 'statement'=>'mysqli_stmt', 'types'=>'string', '&var'=>'mixed', '&...vars='=>'mixed'],
|
||||
'mysqli_stmt_bind_result' => ['bool', 'statement'=>'mysqli_stmt', '&w_var1'=>'', '&...w_vars='=>''],
|
||||
'mysqli_stmt_close' => ['true', 'statement'=>'mysqli_stmt'],
|
||||
'mysqli_stmt_data_seek' => ['void', 'statement'=>'mysqli_stmt', 'offset'=>'int'],
|
||||
@@ -8163,28 +8150,28 @@ return [
|
||||
'nsapi_response_headers' => ['array'],
|
||||
'nsapi_virtual' => ['bool', 'uri'=>'string'],
|
||||
'nthmac' => ['string', 'clent'=>'string', 'data'=>'string'],
|
||||
'number_format' => ['string', 'num'=>'float|int', 'decimals='=>'int', 'decimal_separator='=>'?string', 'thousands_separator='=>'?string'],
|
||||
'number_format' => ['string', 'num'=>'float', 'decimals='=>'int', 'decimal_separator='=>'?string', 'thousands_separator='=>'?string'],
|
||||
'NumberFormatter::__construct' => ['void', 'locale'=>'string', 'style'=>'int', 'pattern='=>'?string'],
|
||||
'NumberFormatter::create' => ['NumberFormatter|null', 'locale'=>'string', 'style'=>'int', 'pattern='=>'?string'],
|
||||
'NumberFormatter::format' => ['string|false', 'num'=>'', 'type='=>'int'],
|
||||
'NumberFormatter::formatCurrency' => ['string|false', 'num'=>'float', 'currency'=>'string'],
|
||||
'NumberFormatter::getAttribute' => ['int|false', 'attr'=>'int'],
|
||||
'NumberFormatter::formatCurrency' => ['string|false', 'amount'=>'float', 'currency'=>'string'],
|
||||
'NumberFormatter::getAttribute' => ['int|float|false', 'attribute'=>'int'],
|
||||
'NumberFormatter::getErrorCode' => ['int'],
|
||||
'NumberFormatter::getErrorMessage' => ['string'],
|
||||
'NumberFormatter::getLocale' => ['string', 'type='=>'int'],
|
||||
'NumberFormatter::getPattern' => ['string|false'],
|
||||
'NumberFormatter::getSymbol' => ['string|false', 'attr'=>'int'],
|
||||
'NumberFormatter::getTextAttribute' => ['string|false', 'attr'=>'int'],
|
||||
'NumberFormatter::parse' => ['float|false', 'string'=>'string', 'type='=>'int', '&rw_position='=>'int'],
|
||||
'NumberFormatter::parseCurrency' => ['float|false', 'string'=>'string', '&w_currency'=>'string', '&rw_position='=>'int'],
|
||||
'NumberFormatter::setAttribute' => ['bool', 'attr'=>'int', 'value'=>''],
|
||||
'NumberFormatter::getSymbol' => ['string|false', 'symbol'=>'int'],
|
||||
'NumberFormatter::getTextAttribute' => ['string|false', 'attribute'=>'int'],
|
||||
'NumberFormatter::parse' => ['int|float|false', 'string'=>'string', 'type='=>'int', '&rw_offset='=>'int'],
|
||||
'NumberFormatter::parseCurrency' => ['float|false', 'string'=>'string', '&w_currency'=>'string', '&rw_offset='=>'int'],
|
||||
'NumberFormatter::setAttribute' => ['bool', 'attribute'=>'int', 'value'=>'int|float'],
|
||||
'NumberFormatter::setPattern' => ['bool', 'pattern'=>'string'],
|
||||
'NumberFormatter::setSymbol' => ['bool', 'attr'=>'int', 'symbol'=>'string'],
|
||||
'NumberFormatter::setTextAttribute' => ['bool', 'attr'=>'int', 'value'=>'string'],
|
||||
'NumberFormatter::setSymbol' => ['bool', 'symbol'=>'int', 'value'=>'string'],
|
||||
'NumberFormatter::setTextAttribute' => ['bool', 'attribute'=>'int', 'value'=>'string'],
|
||||
'numfmt_create' => ['NumberFormatter|null', 'locale'=>'string', 'style'=>'int', 'pattern='=>'?string'],
|
||||
'numfmt_format' => ['string|false', 'formatter'=>'NumberFormatter', 'num'=>'int|float', 'type='=>'int'],
|
||||
'numfmt_format_currency' => ['string|false', 'formatter'=>'NumberFormatter', 'amount'=>'float', 'currency'=>'string'],
|
||||
'numfmt_get_attribute' => ['int|false', 'formatter'=>'NumberFormatter', 'attribute'=>'int'],
|
||||
'numfmt_get_attribute' => ['float|int|false', 'formatter'=>'NumberFormatter', 'attribute'=>'int'],
|
||||
'numfmt_get_error_code' => ['int', 'formatter'=>'NumberFormatter'],
|
||||
'numfmt_get_error_message' => ['string', 'formatter'=>'NumberFormatter'],
|
||||
'numfmt_get_locale' => ['string', 'formatter'=>'NumberFormatter', 'type='=>'int'],
|
||||
@@ -8193,7 +8180,7 @@ return [
|
||||
'numfmt_get_text_attribute' => ['string|false', 'formatter'=>'NumberFormatter', 'attribute'=>'int'],
|
||||
'numfmt_parse' => ['float|int|false', 'formatter'=>'NumberFormatter', 'string'=>'string', 'type='=>'int', '&rw_offset='=>'int'],
|
||||
'numfmt_parse_currency' => ['float|false', 'formatter'=>'NumberFormatter', 'string'=>'string', '&w_currency'=>'string', '&rw_offset='=>'int'],
|
||||
'numfmt_set_attribute' => ['bool', 'formatter'=>'NumberFormatter', 'attribute'=>'int', 'value'=>'int'],
|
||||
'numfmt_set_attribute' => ['bool', 'formatter'=>'NumberFormatter', 'attribute'=>'int', 'value'=>'float|int'],
|
||||
'numfmt_set_pattern' => ['bool', 'formatter'=>'NumberFormatter', 'pattern'=>'string'],
|
||||
'numfmt_set_symbol' => ['bool', 'formatter'=>'NumberFormatter', 'symbol'=>'int', 'value'=>'string'],
|
||||
'numfmt_set_text_attribute' => ['bool', 'formatter'=>'NumberFormatter', 'attribute'=>'int', 'value'=>'string'],
|
||||
@@ -8408,9 +8395,9 @@ return [
|
||||
'odbc_pconnect' => ['resource|false', 'dsn'=>'string', 'user'=>'string', 'password'=>'string', 'cursor_option='=>'int'],
|
||||
'odbc_prepare' => ['resource|false', 'odbc'=>'resource', 'query'=>'string'],
|
||||
'odbc_primarykeys' => ['resource|false', 'odbc'=>'resource', 'catalog'=>'?string', 'schema'=>'string', 'table'=>'string'],
|
||||
'odbc_procedurecolumns' => ['resource|false', 'odbc'=>'resource', 'catalog'=>'string', 'schema'=>'string', 'procedure'=>'string', 'column'=>'string'],
|
||||
'odbc_procedures' => ['resource|false', 'odbc'=>'resource', 'catalog'=>'string', 'schema'=>'string', 'procedure'=>'string'],
|
||||
'odbc_result' => ['mixed|false', 'statement'=>'resource', 'field'=>'mixed'],
|
||||
'odbc_procedurecolumns' => ['resource|false', 'odbc'=>'resource', 'catalog='=>'?string', 'schema='=>'?string', 'procedure='=>'?string', 'column='=>'?string'],
|
||||
'odbc_procedures' => ['resource|false', 'odbc'=>'resource', 'catalog='=>'?string', 'schema='=>'?string', 'procedure='=>'?string'],
|
||||
'odbc_result' => ['string|bool|null', 'statement'=>'resource', 'field'=>'string|int'],
|
||||
'odbc_result_all' => ['int|false', 'statement'=>'resource', 'format='=>'string'],
|
||||
'odbc_rollback' => ['bool', 'odbc'=>'resource'],
|
||||
'odbc_setoption' => ['bool', 'odbc'=>'resource', 'which'=>'int', 'option'=>'int', 'value'=>'int'],
|
||||
@@ -8476,7 +8463,7 @@ return [
|
||||
'openssl_pkcs12_read' => ['bool', 'pkcs12'=>'string', '&w_certificates'=>'array', 'passphrase'=>'string'],
|
||||
'openssl_pkcs7_decrypt' => ['bool', 'input_filename'=>'string', 'output_filename'=>'string', 'certificate'=>'OpenSSLCertificate|string', 'private_key='=>'OpenSSLAsymmetricKey|OpenSSLCertificate|array{OpenSSLAsymmetricKey|OpenSSLCertificate|string, string}|string|null'],
|
||||
'openssl_pkcs7_encrypt' => ['bool', 'input_filename'=>'string', 'output_filename'=>'string', 'certificate'=>'OpenSSLCertificate|list<OpenSSLCertificate|string>|string', 'headers'=>'array|null', 'flags='=>'int', 'cipher_algo='=>'int'],
|
||||
'openssl_pkcs7_read' => ['bool', 'input_filename'=>'string', '&w_certificates'=>'array'],
|
||||
'openssl_pkcs7_read' => ['bool', 'data'=>'string', '&w_certificates'=>'array'],
|
||||
'openssl_pkcs7_sign' => ['bool', 'input_filename'=>'string', 'output_filename'=>'string', 'certificate'=>'OpenSSLCertificate|string', 'private_key'=>'OpenSSLAsymmetricKey|OpenSSLCertificate|array{OpenSSLAsymmetricKey|OpenSSLCertificate|string, string}|string', 'headers'=>'array|null', 'flags='=>'int', 'untrusted_certificates_filename='=>'string|null'],
|
||||
'openssl_pkcs7_verify' => ['bool|int', 'input_filename'=>'string', 'flags'=>'int', 'signers_certificates_filename='=>'?string', 'ca_info='=>'array', 'untrusted_certificates_filename='=>'?string', 'content='=>'?string', 'output_filename='=>'?string'],
|
||||
'openssl_pkey_derive' => ['string|false', 'public_key'=>'OpenSSLAsymmetricKey|OpenSSLCertificate|array{OpenSSLAsymmetricKey|OpenSSLCertificate|string, string}|string', 'private_key'=>'OpenSSLAsymmetricKey|OpenSSLCertificate|array{OpenSSLAsymmetricKey|OpenSSLCertificate|string, string}|string', 'key_length='=>'int'],
|
||||
@@ -8998,8 +8985,6 @@ return [
|
||||
'PDFlib::utf32_to_utf16' => ['string', 'utf32string'=>'string', 'ordering'=>'string'],
|
||||
'PDFlib::utf8_to_utf16' => ['string', 'utf8string'=>'string', 'ordering'=>'string'],
|
||||
'PDO::__construct' => ['void', 'dsn'=>'string', 'username='=>'?string', 'password='=>'?string', 'options='=>'?array'],
|
||||
'PDO::__sleep' => ['list<string>'],
|
||||
'PDO::__wakeup' => ['void'],
|
||||
'PDO::beginTransaction' => ['bool'],
|
||||
'PDO::commit' => ['bool'],
|
||||
'PDO::cubrid_schema' => ['array', 'schema_type'=>'int', 'table_name='=>'string', 'col_name='=>'string'],
|
||||
@@ -9038,8 +9023,6 @@ return [
|
||||
'PDOException::getPrevious' => ['?Throwable'],
|
||||
'PDOException::getTrace' => ['list<array{file?:string,line?:int,function:string,class?:class-string,type?:\'::\'|\'->\',args?:array<mixed>}>'],
|
||||
'PDOException::getTraceAsString' => ['string'],
|
||||
'PDOStatement::__sleep' => ['list<string>'],
|
||||
'PDOStatement::__wakeup' => ['void'],
|
||||
'PDOStatement::bindColumn' => ['bool', 'column'=>'string|int', '&rw_var'=>'mixed', 'type='=>'int', 'maxLength='=>'int', 'driverOptions='=>'mixed'],
|
||||
'PDOStatement::bindParam' => ['bool', 'param'=>'string|int', '&rw_var'=>'mixed', 'type='=>'int', 'maxLength='=>'int', 'driverOptions='=>'mixed'],
|
||||
'PDOStatement::bindValue' => ['bool', 'param'=>'string|int', 'value'=>'mixed', 'type='=>'int'],
|
||||
@@ -9640,7 +9623,7 @@ return [
|
||||
'rand\'1' => ['int'],
|
||||
'random_bytes' => ['non-empty-string', 'length'=>'positive-int'],
|
||||
'random_int' => ['int', 'min'=>'int', 'max'=>'int'],
|
||||
'range' => ['array', 'start'=>'mixed', 'end'=>'mixed', 'step='=>'int|float'],
|
||||
'range' => ['non-empty-array', 'start'=>'string|int|float', 'end'=>'string|int|float', 'step='=>'int<1, max>|float'],
|
||||
'RangeException::__clone' => ['void'],
|
||||
'RangeException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'],
|
||||
'RangeException::__toString' => ['string'],
|
||||
@@ -10443,7 +10426,7 @@ return [
|
||||
'RedisCluster::zUnionStore' => ['int', 'Output'=>'string', 'ZSetKeys'=>'array', 'Weights='=>'?array', 'aggregateFunction='=>'string'],
|
||||
'Reflection::getModifierNames' => ['list<string>', 'modifiers'=>'int'],
|
||||
'ReflectionClass::__clone' => ['void'],
|
||||
'ReflectionClass::__construct' => ['void', 'argument'=>'object|class-string'],
|
||||
'ReflectionClass::__construct' => ['void', 'objectOrClass'=>'object|class-string'],
|
||||
'ReflectionClass::__toString' => ['string'],
|
||||
'ReflectionClass::getAttributes' => ['list<ReflectionAttribute>', 'name='=>'?string', 'flags='=>'int'],
|
||||
'ReflectionClass::getConstant' => ['mixed', 'name'=>'string'],
|
||||
@@ -10477,7 +10460,7 @@ return [
|
||||
'ReflectionClass::hasConstant' => ['bool', 'name'=>'string'],
|
||||
'ReflectionClass::hasMethod' => ['bool', 'name'=>'string'],
|
||||
'ReflectionClass::hasProperty' => ['bool', 'name'=>'string'],
|
||||
'ReflectionClass::implementsInterface' => ['bool', 'interface_name'=>'interface-string|ReflectionClass'],
|
||||
'ReflectionClass::implementsInterface' => ['bool', 'interface'=>'interface-string|ReflectionClass'],
|
||||
'ReflectionClass::inNamespace' => ['bool'],
|
||||
'ReflectionClass::isAbstract' => ['bool'],
|
||||
'ReflectionClass::isAnonymous' => ['bool'],
|
||||
@@ -10497,7 +10480,7 @@ return [
|
||||
'ReflectionClass::newInstanceArgs' => ['object', 'args='=>'list<mixed>|array<string, mixed>'],
|
||||
'ReflectionClass::newInstanceWithoutConstructor' => ['object'],
|
||||
'ReflectionClass::setStaticPropertyValue' => ['void', 'name'=>'string', 'value'=>'mixed'],
|
||||
'ReflectionClassConstant::__construct' => ['void', 'class'=>'mixed', 'name'=>'string'],
|
||||
'ReflectionClassConstant::__construct' => ['void', 'class'=>'object|class-string', 'constant'=>'string'],
|
||||
'ReflectionClassConstant::__toString' => ['string'],
|
||||
'ReflectionClassConstant::getAttributes' => ['list<ReflectionAttribute>', 'name='=>'?string', 'flags='=>'int'],
|
||||
'ReflectionClassConstant::getDeclaringClass' => ['ReflectionClass'],
|
||||
@@ -10530,7 +10513,7 @@ return [
|
||||
'ReflectionExtension::info' => ['void'],
|
||||
'ReflectionExtension::isPersistent' => ['bool'],
|
||||
'ReflectionExtension::isTemporary' => ['bool'],
|
||||
'ReflectionFunction::__construct' => ['void', 'name'=>'callable-string|Closure'],
|
||||
'ReflectionFunction::__construct' => ['void', 'function'=>'callable-string|Closure'],
|
||||
'ReflectionFunction::__toString' => ['string'],
|
||||
'ReflectionFunction::getClosure' => ['Closure'],
|
||||
'ReflectionFunction::getClosureScopeClass' => ['ReflectionClass'],
|
||||
@@ -10592,7 +10575,7 @@ return [
|
||||
'ReflectionFunctionAbstract::isUserDefined' => ['bool'],
|
||||
'ReflectionFunctionAbstract::isVariadic' => ['bool'],
|
||||
'ReflectionFunctionAbstract::returnsReference' => ['bool'],
|
||||
'ReflectionGenerator::__construct' => ['void', 'generator'=>'object'],
|
||||
'ReflectionGenerator::__construct' => ['void', 'generator'=>'Generator'],
|
||||
'ReflectionGenerator::getExecutingFile' => ['string'],
|
||||
'ReflectionGenerator::getExecutingGenerator' => ['Generator'],
|
||||
'ReflectionGenerator::getExecutingLine' => ['int'],
|
||||
@@ -10640,17 +10623,17 @@ return [
|
||||
'ReflectionMethod::isUserDefined' => ['bool'],
|
||||
'ReflectionMethod::isVariadic' => ['bool'],
|
||||
'ReflectionMethod::returnsReference' => ['bool'],
|
||||
'ReflectionMethod::setAccessible' => ['void', 'visible'=>'bool'],
|
||||
'ReflectionMethod::setAccessible' => ['void', 'accessible'=>'bool'],
|
||||
'ReflectionNamedType::__clone' => ['void'],
|
||||
'ReflectionNamedType::__toString' => ['string'],
|
||||
'ReflectionNamedType::allowsNull' => ['bool'],
|
||||
'ReflectionNamedType::getName' => ['string'],
|
||||
'ReflectionNamedType::isBuiltin' => ['bool'],
|
||||
'ReflectionObject::__clone' => ['void'],
|
||||
'ReflectionObject::__construct' => ['void', 'argument'=>'object'],
|
||||
'ReflectionObject::__construct' => ['void', 'object'=>'object'],
|
||||
'ReflectionObject::__toString' => ['string'],
|
||||
'ReflectionObject::getConstant' => ['mixed', 'name'=>'string'],
|
||||
'ReflectionObject::getConstants' => ['array<string,mixed>'],
|
||||
'ReflectionObject::getConstants' => ['array<string,mixed>', 'filter='=>'?int'],
|
||||
'ReflectionObject::getConstructor' => ['?ReflectionMethod'],
|
||||
'ReflectionObject::getDefaultProperties' => ['array'],
|
||||
'ReflectionObject::getDocComment' => ['false|string'],
|
||||
@@ -10669,7 +10652,7 @@ return [
|
||||
'ReflectionObject::getProperties' => ['ReflectionProperty[]', 'filter='=>'?int'],
|
||||
'ReflectionObject::getProperty' => ['ReflectionProperty', 'name'=>'string'],
|
||||
'ReflectionObject::getReflectionConstant' => ['ReflectionClassConstant', 'name'=>'string'],
|
||||
'ReflectionObject::getReflectionConstants' => ['list<\ReflectionClassConstant>'],
|
||||
'ReflectionObject::getReflectionConstants' => ['list<\ReflectionClassConstant>', 'filter='=>'?int'],
|
||||
'ReflectionObject::getShortName' => ['string'],
|
||||
'ReflectionObject::getStartLine' => ['false|int'],
|
||||
'ReflectionObject::getStaticProperties' => ['ReflectionProperty[]'],
|
||||
@@ -10680,7 +10663,7 @@ return [
|
||||
'ReflectionObject::hasConstant' => ['bool', 'name'=>'string'],
|
||||
'ReflectionObject::hasMethod' => ['bool', 'name'=>'string'],
|
||||
'ReflectionObject::hasProperty' => ['bool', 'name'=>'string'],
|
||||
'ReflectionObject::implementsInterface' => ['bool', 'interface_name'=>'ReflectionClass|string'],
|
||||
'ReflectionObject::implementsInterface' => ['bool', 'interface'=>'ReflectionClass|interface-string'],
|
||||
'ReflectionObject::inNamespace' => ['bool'],
|
||||
'ReflectionObject::isAbstract' => ['bool'],
|
||||
'ReflectionObject::isAnonymous' => ['bool'],
|
||||
@@ -10701,7 +10684,7 @@ return [
|
||||
'ReflectionObject::newInstanceWithoutConstructor' => ['object'],
|
||||
'ReflectionObject::setStaticPropertyValue' => ['void', 'name'=>'string', 'value'=>'string'],
|
||||
'ReflectionParameter::__clone' => ['void'],
|
||||
'ReflectionParameter::__construct' => ['void', 'function'=>'', 'parameter'=>''],
|
||||
'ReflectionParameter::__construct' => ['void', 'function'=>'string|array|object', 'param'=>'int|string'],
|
||||
'ReflectionParameter::__toString' => ['string'],
|
||||
'ReflectionParameter::allowsNull' => ['bool'],
|
||||
'ReflectionParameter::canBePassedByValue' => ['bool'],
|
||||
@@ -10723,7 +10706,7 @@ return [
|
||||
'ReflectionParameter::isPassedByReference' => ['bool'],
|
||||
'ReflectionParameter::isVariadic' => ['bool'],
|
||||
'ReflectionProperty::__clone' => ['void'],
|
||||
'ReflectionProperty::__construct' => ['void', 'class'=>'', 'name'=>'string'],
|
||||
'ReflectionProperty::__construct' => ['void', 'class'=>'object|class-string', 'property'=>'string'],
|
||||
'ReflectionProperty::__toString' => ['string'],
|
||||
'ReflectionProperty::getAttributes' => ['list<ReflectionAttribute>', 'name='=>'?string', 'flags='=>'int'],
|
||||
'ReflectionProperty::getDeclaringClass' => ['ReflectionClass'],
|
||||
@@ -10738,7 +10721,7 @@ return [
|
||||
'ReflectionProperty::isProtected' => ['bool'],
|
||||
'ReflectionProperty::isPublic' => ['bool'],
|
||||
'ReflectionProperty::isStatic' => ['bool'],
|
||||
'ReflectionProperty::setAccessible' => ['void', 'visible'=>'bool'],
|
||||
'ReflectionProperty::setAccessible' => ['void', 'accessible'=>'bool'],
|
||||
'ReflectionProperty::setValue' => ['void', 'object'=>'null|object', 'value'=>''],
|
||||
'ReflectionProperty::setValue\'1' => ['void', 'value'=>''],
|
||||
'ReflectionType::__clone' => ['void'],
|
||||
@@ -10776,13 +10759,13 @@ return [
|
||||
'rename' => ['bool', 'from'=>'string', 'to'=>'string', 'context='=>'resource'],
|
||||
'rename_function' => ['bool', 'original_name'=>'string', 'new_name'=>'string'],
|
||||
'reset' => ['mixed|false', '&r_array'=>'array|object'],
|
||||
'ResourceBundle::__construct' => ['void', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'],
|
||||
'ResourceBundle::__construct' => ['void', 'locale'=>'?string', 'bundle'=>'?string', 'fallback='=>'bool'],
|
||||
'ResourceBundle::count' => ['int'],
|
||||
'ResourceBundle::create' => ['?ResourceBundle', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'],
|
||||
'ResourceBundle::create' => ['?ResourceBundle', 'locale'=>'?string', 'bundle'=>'?string', 'fallback='=>'bool'],
|
||||
'ResourceBundle::get' => ['mixed', 'index'=>'string|int', 'fallback='=>'bool'],
|
||||
'ResourceBundle::getErrorCode' => ['int'],
|
||||
'ResourceBundle::getErrorMessage' => ['string'],
|
||||
'ResourceBundle::getLocales' => ['array', 'bundlename'=>'string'],
|
||||
'ResourceBundle::getLocales' => ['array|false', 'bundle'=>'string'],
|
||||
'resourcebundle_count' => ['int', 'bundle'=>'ResourceBundle'],
|
||||
'resourcebundle_create' => ['?ResourceBundle', 'locale'=>'?string', 'bundle'=>'?string', 'fallback='=>'bool'],
|
||||
'resourcebundle_get' => ['mixed|null', 'bundle'=>'ResourceBundle', 'index'=>'string|int', 'fallback='=>'bool'],
|
||||
@@ -10795,7 +10778,7 @@ return [
|
||||
'rewind' => ['bool', 'stream'=>'resource'],
|
||||
'rewinddir' => ['void', 'dir_handle='=>'resource'],
|
||||
'rmdir' => ['bool', 'directory'=>'string', 'context='=>'resource'],
|
||||
'round' => ['float', 'num'=>'float', 'precision='=>'int', 'mode='=>'0|positive-int'],
|
||||
'round' => ['float', 'num'=>'float|int', 'precision='=>'int', 'mode='=>'0|positive-int'],
|
||||
'rpm_close' => ['bool', 'rpmr'=>'resource'],
|
||||
'rpm_get_tag' => ['mixed', 'rpmr'=>'resource', 'tagnum'=>'int'],
|
||||
'rpm_is_valid' => ['bool', 'filename'=>'string'],
|
||||
@@ -11169,18 +11152,18 @@ return [
|
||||
'ServerResponse::setStatus' => ['void', 'status'=>'int'],
|
||||
'ServerResponse::setVersion' => ['void', 'version'=>'string'],
|
||||
'session_abort' => ['bool'],
|
||||
'session_cache_expire' => ['int', 'value='=>'?int'],
|
||||
'session_cache_limiter' => ['string', 'value='=>'?string'],
|
||||
'session_cache_expire' => ['int|false', 'value='=>'?int'],
|
||||
'session_cache_limiter' => ['string|false', 'value='=>'?string'],
|
||||
'session_commit' => ['bool'],
|
||||
'session_create_id' => ['string', 'prefix='=>'string'],
|
||||
'session_create_id' => ['string|false', 'prefix='=>'string'],
|
||||
'session_decode' => ['bool', 'data'=>'string'],
|
||||
'session_destroy' => ['bool'],
|
||||
'session_encode' => ['string'],
|
||||
'session_encode' => ['string|false'],
|
||||
'session_gc' => ['int|false'],
|
||||
'session_get_cookie_params' => ['array'],
|
||||
'session_id' => ['string|false', 'id='=>'?string'],
|
||||
'session_is_registered' => ['bool', 'name'=>'string'],
|
||||
'session_module_name' => ['string', 'module='=>'?string'],
|
||||
'session_module_name' => ['string|false', 'module='=>'?string'],
|
||||
'session_name' => ['string|false', 'name='=>'?string'],
|
||||
'session_pgsql_add_error' => ['bool', 'error_level'=>'int', 'error_message='=>'string'],
|
||||
'session_pgsql_get_error' => ['array', 'with_error_message='=>'bool'],
|
||||
@@ -11192,7 +11175,7 @@ return [
|
||||
'session_register' => ['bool', 'name'=>'mixed', '...args='=>'mixed'],
|
||||
'session_register_shutdown' => ['void'],
|
||||
'session_reset' => ['bool'],
|
||||
'session_save_path' => ['string', 'path='=>'?string'],
|
||||
'session_save_path' => ['string|false', 'path='=>'?string'],
|
||||
'session_set_cookie_params' => ['bool', 'lifetime'=>'int', 'path='=>'?string', 'domain='=>'?string', 'secure='=>'?bool', 'httponly='=>'?bool'],
|
||||
'session_set_cookie_params\'1' => ['bool', 'options'=>'array{lifetime?:?int,path?:?string,domain?:?string,secure?:?bool,httponly?:?bool,samesite?:?string}'],
|
||||
'session_set_save_handler' => ['bool', 'open'=>'callable(string,string):bool', 'close'=>'callable():bool', 'read'=>'callable(string):string', 'write'=>'callable(string,string):bool', 'destroy'=>'callable(string):bool', 'gc'=>'callable(string):bool', 'create_sid='=>'callable():string', 'validate_sid='=>'callable(string):bool', 'update_timestamp='=>'callable(string):bool'],
|
||||
@@ -11205,9 +11188,9 @@ return [
|
||||
'SessionHandler::close' => ['bool'],
|
||||
'SessionHandler::create_sid' => ['string'],
|
||||
'SessionHandler::destroy' => ['bool', 'id'=>'string'],
|
||||
'SessionHandler::gc' => ['bool', 'maxlifetime'=>'int'],
|
||||
'SessionHandler::open' => ['bool', 'save_path'=>'string', 'session_name'=>'string'],
|
||||
'SessionHandler::read' => ['string', 'id'=>'string'],
|
||||
'SessionHandler::gc' => ['int|false', 'max_lifetime'=>'int'],
|
||||
'SessionHandler::open' => ['bool', 'path'=>'string', 'name'=>'string'],
|
||||
'SessionHandler::read' => ['string|false', 'id'=>'string'],
|
||||
'SessionHandler::write' => ['bool', 'id'=>'string', 'data'=>'string'],
|
||||
'SessionHandlerInterface::close' => ['bool'],
|
||||
'SessionHandlerInterface::destroy' => ['bool', 'id'=>'string'],
|
||||
@@ -11305,40 +11288,40 @@ return [
|
||||
'simplexml_import_dom' => ['?SimpleXMLElement', 'node'=>'DOMNode', 'class_name='=>'?string'],
|
||||
'simplexml_load_file' => ['SimpleXMLElement|false', 'filename'=>'string', 'class_name='=>'?string', 'options='=>'int', 'namespace_or_prefix='=>'string', 'is_prefix='=>'bool'],
|
||||
'simplexml_load_string' => ['SimpleXMLElement|false', 'data'=>'string', 'class_name='=>'?string', 'options='=>'int', 'namespace_or_prefix='=>'string', 'is_prefix='=>'bool'],
|
||||
'SimpleXMLElement::__construct' => ['void', 'data'=>'string', 'options='=>'int', 'data_is_url='=>'bool', 'ns='=>'string', 'is_prefix='=>'bool'],
|
||||
'SimpleXMLElement::__construct' => ['void', 'data'=>'string', 'options='=>'int', 'dataIsURL='=>'bool', 'namespaceOrPrefix='=>'string', 'isPrefix='=>'bool'],
|
||||
'SimpleXMLElement::__get' => ['SimpleXMLElement', 'name'=>'string'],
|
||||
'SimpleXMLElement::__toString' => ['string'],
|
||||
'SimpleXMLElement::addAttribute' => ['void', 'name'=>'string', 'value='=>'string', 'ns='=>'string'],
|
||||
'SimpleXMLElement::addChild' => ['SimpleXMLElement', 'name'=>'string', 'value='=>'string', 'ns='=>'string'],
|
||||
'SimpleXMLElement::addAttribute' => ['void', 'qualifiedName'=>'string', 'value'=>'string', 'namespace='=>'?string'],
|
||||
'SimpleXMLElement::addChild' => ['?SimpleXMLElement', 'qualifiedName'=>'string', 'value='=>'?string', 'namespace='=>'?string'],
|
||||
'SimpleXMLElement::asXML' => ['string|bool', 'filename='=>'?string'],
|
||||
'SimpleXMLElement::asXML\'1' => ['string|false'],
|
||||
'SimpleXMLElement::attributes' => ['?SimpleXMLElement', 'ns='=>'string', 'is_prefix='=>'bool'],
|
||||
'SimpleXMLElement::children' => ['SimpleXMLElement', 'ns='=>'string', 'is_prefix='=>'bool'],
|
||||
'SimpleXMLElement::attributes' => ['?SimpleXMLElement', 'namespaceOrPrefix='=>'?string', 'isPrefix='=>'bool'],
|
||||
'SimpleXMLElement::children' => ['?SimpleXMLElement', 'namespaceOrPrefix='=>'?string', 'isPrefix='=>'bool'],
|
||||
'SimpleXMLElement::count' => ['int'],
|
||||
'SimpleXMLElement::getDocNamespaces' => ['string[]', 'recursive='=>'bool', 'from_root='=>'bool'],
|
||||
'SimpleXMLElement::getDocNamespaces' => ['array<string,string>', 'recursive='=>'bool', 'fromRoot='=>'bool'],
|
||||
'SimpleXMLElement::getName' => ['string'],
|
||||
'SimpleXMLElement::getNamespaces' => ['string[]', 'recursive='=>'bool'],
|
||||
'SimpleXMLElement::getNamespaces' => ['array<string,string>', 'recursive='=>'bool'],
|
||||
'SimpleXMLElement::offsetExists' => ['bool', 'offset'=>'int|string'],
|
||||
'SimpleXMLElement::offsetGet' => ['SimpleXMLElement', 'offset'=>'int|string'],
|
||||
'SimpleXMLElement::offsetSet' => ['void', 'offset'=>'int|string', 'value'=>'mixed'],
|
||||
'SimpleXMLElement::offsetUnset' => ['void', 'offset'=>'int|string'],
|
||||
'SimpleXMLElement::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'ns'=>'string'],
|
||||
'SimpleXMLElement::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'namespace'=>'string'],
|
||||
'SimpleXMLElement::saveXML' => ['string|bool', 'filename='=>'?string'],
|
||||
'SimpleXMLElement::xpath' => ['SimpleXMLElement[]|false', 'path'=>'string'],
|
||||
'SimpleXMLElement::xpath' => ['SimpleXMLElement[]|false|null', 'expression'=>'string'],
|
||||
'sin' => ['float', 'num'=>'float'],
|
||||
'sinh' => ['float', 'num'=>'float'],
|
||||
'sizeof' => ['int<0, max>', 'value'=>'Countable|array', 'mode='=>'int'],
|
||||
'sleep' => ['int', 'seconds'=>'0|positive-int'],
|
||||
'snmp2_get' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_getnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_real_walk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_set' => ['bool', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_walk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_get' => ['string|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_getnext' => ['string|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_real_walk' => ['array|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_set' => ['bool', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_walk' => ['array|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_get' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_getnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_real_walk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_set' => ['bool', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'type'=>'array|string', 'value'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_walk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_get' => ['string|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_getnext' => ['string|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_real_walk' => ['array|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_set' => ['bool', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'type'=>'array|string', 'value'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_walk' => ['array|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'SNMP::__construct' => ['void', 'version'=>'int', 'hostname'=>'string', 'community'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'SNMP::close' => ['bool'],
|
||||
'SNMP::get' => ['array|string|false', 'objectId'=>'string|array', 'preserveKeys='=>'bool'],
|
||||
@@ -11347,7 +11330,7 @@ return [
|
||||
'SNMP::getnext' => ['string|array|false', 'objectId'=>'string|array'],
|
||||
'SNMP::set' => ['bool', 'objectId'=>'string|array', 'type'=>'string|array', 'value'=>'string|array'],
|
||||
'SNMP::setSecurity' => ['bool', 'securityLevel'=>'string', 'authProtocol='=>'string', 'authPassphrase='=>'string', 'privacyProtocol='=>'string', 'privacyPassphrase='=>'string', 'contextName='=>'string', 'contextEngineId='=>'string'],
|
||||
'SNMP::walk' => ['array|false', 'objectId'=>'string', 'suffixAsKey='=>'bool', 'maxRepetitions='=>'int', 'nonRepeaters='=>'int'],
|
||||
'SNMP::walk' => ['array|false', 'objectId'=>'array|string', 'suffixAsKey='=>'bool', 'maxRepetitions='=>'int', 'nonRepeaters='=>'int'],
|
||||
'snmp_get_quick_print' => ['bool'],
|
||||
'snmp_get_valueretrieval' => ['int'],
|
||||
'snmp_read_mib' => ['bool', 'filename'=>'string'],
|
||||
@@ -11356,12 +11339,12 @@ return [
|
||||
'snmp_set_oid_output_format' => ['true', 'format'=>'int'],
|
||||
'snmp_set_quick_print' => ['bool', 'enable'=>'bool'],
|
||||
'snmp_set_valueretrieval' => ['true', 'method'=>'int'],
|
||||
'snmpget' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpgetnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmprealwalk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpset' => ['bool', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'type'=>'string|string[]', 'value'=>'string|string[]', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpwalk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpwalkoid' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpget' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpgetnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmprealwalk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpset' => ['bool', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'type'=>'string|string[]', 'value'=>'string|string[]', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpwalk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpwalkoid' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'SoapClient::__call' => ['', 'function_name'=>'string', 'arguments'=>'array'],
|
||||
'SoapClient::__construct' => ['void', 'wsdl'=>'mixed', 'options='=>'array|null'],
|
||||
'SoapClient::__doRequest' => ['?string', 'request'=>'string', 'location'=>'string', 'action'=>'string', 'version'=>'int', 'one_way='=>'bool'],
|
||||
@@ -11506,7 +11489,7 @@ return [
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_init_pull' => ['string', 'header'=>'string', 'key'=>'string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_init_push' => ['array', 'key'=>'string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_keygen' => ['non-empty-string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_pull' => ['array', '&r_state'=>'string', 'ciphertext'=>'string', 'additional_data='=>'string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_pull' => ['array|false', '&r_state'=>'string', 'ciphertext'=>'string', 'additional_data='=>'string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_push' => ['string', '&w_state'=>'string', 'message'=>'string', 'additional_data='=>'string', 'tag='=>'int'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_rekey' => ['void', '&w_state'=>'string'],
|
||||
'sodium_crypto_shorthash' => ['string', 'message'=>'string', 'key'=>'string'],
|
||||
@@ -12281,10 +12264,10 @@ return [
|
||||
'SplDoublyLinkedList::isEmpty' => ['bool'],
|
||||
'SplDoublyLinkedList::key' => ['int'],
|
||||
'SplDoublyLinkedList::next' => ['void'],
|
||||
'SplDoublyLinkedList::offsetExists' => ['bool', 'index'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetGet' => ['mixed', 'index'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetSet' => ['void', 'index'=>'mixed', 'value'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetUnset' => ['void', 'index'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetExists' => ['bool', 'index'=>'int'],
|
||||
'SplDoublyLinkedList::offsetGet' => ['mixed', 'index'=>'int'],
|
||||
'SplDoublyLinkedList::offsetSet' => ['void', 'index'=>'?int', 'value'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetUnset' => ['void', 'index'=>'int'],
|
||||
'SplDoublyLinkedList::pop' => ['mixed'],
|
||||
'SplDoublyLinkedList::prev' => ['void'],
|
||||
'SplDoublyLinkedList::push' => ['void', 'value'=>'mixed'],
|
||||
@@ -12300,7 +12283,6 @@ return [
|
||||
'SplEnum::getConstList' => ['array', 'include_default='=>'bool'],
|
||||
'SplFileInfo::__construct' => ['void', 'filename'=>'string'],
|
||||
'SplFileInfo::__toString' => ['string'],
|
||||
'SplFileInfo::__wakeup' => ['void'],
|
||||
'SplFileInfo::getATime' => ['int|false'],
|
||||
'SplFileInfo::getBasename' => ['string', 'suffix='=>'string'],
|
||||
'SplFileInfo::getCTime' => ['int|false'],
|
||||
@@ -12390,19 +12372,15 @@ return [
|
||||
'SplFixedArray::__construct' => ['void', 'size='=>'int'],
|
||||
'SplFixedArray::__wakeup' => ['void'],
|
||||
'SplFixedArray::count' => ['int'],
|
||||
'SplFixedArray::current' => ['mixed'],
|
||||
'SplFixedArray::fromArray' => ['SplFixedArray', 'array'=>'array', 'preserveKeys='=>'bool'],
|
||||
'SplFixedArray::getIterator' => ['Iterator'],
|
||||
'SplFixedArray::getSize' => ['int'],
|
||||
'SplFixedArray::key' => ['int'],
|
||||
'SplFixedArray::next' => ['void'],
|
||||
'SplFixedArray::offsetExists' => ['bool', 'index'=>'int'],
|
||||
'SplFixedArray::offsetGet' => ['mixed', 'index'=>'int'],
|
||||
'SplFixedArray::offsetSet' => ['void', 'index'=>'int', 'value'=>'mixed'],
|
||||
'SplFixedArray::offsetUnset' => ['void', 'index'=>'int'],
|
||||
'SplFixedArray::rewind' => ['void'],
|
||||
'SplFixedArray::setSize' => ['bool', 'size'=>'int'],
|
||||
'SplFixedArray::toArray' => ['array'],
|
||||
'SplFixedArray::valid' => ['bool'],
|
||||
'SplHeap::__construct' => ['void'],
|
||||
'SplHeap::compare' => ['int', 'value1'=>'mixed', 'value2'=>'mixed'],
|
||||
'SplHeap::count' => ['int'],
|
||||
@@ -12586,7 +12564,7 @@ return [
|
||||
'Spoofchecker::setChecks' => ['void', 'checks'=>'int'],
|
||||
'Spoofchecker::setRestrictionLevel' => ['void', 'level'=>'int'],
|
||||
'sprintf' => ['string', 'format'=>'string', '...values='=>'string|int|float'],
|
||||
'SQLite3::__construct' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryptionKey='=>'?string'],
|
||||
'SQLite3::__construct' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryptionKey='=>'string'],
|
||||
'SQLite3::busyTimeout' => ['bool', 'milliseconds'=>'int'],
|
||||
'SQLite3::changes' => ['int'],
|
||||
'SQLite3::close' => ['bool'],
|
||||
@@ -12600,7 +12578,7 @@ return [
|
||||
'SQLite3::lastErrorMsg' => ['string'],
|
||||
'SQLite3::lastInsertRowID' => ['int'],
|
||||
'SQLite3::loadExtension' => ['bool', 'name'=>'string'],
|
||||
'SQLite3::open' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryptionKey='=>'?string'],
|
||||
'SQLite3::open' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryptionKey='=>'string'],
|
||||
'SQLite3::openBlob' => ['resource|false', 'table'=>'string', 'column'=>'string', 'rowid'=>'int', 'database='=>'string', 'flags='=>'int'],
|
||||
'SQLite3::prepare' => ['SQLite3Stmt|false', 'query'=>'string'],
|
||||
'SQLite3::query' => ['SQLite3Result|false', 'query'=>'string'],
|
||||
@@ -12723,7 +12701,7 @@ return [
|
||||
'sqlsrv_commit' => ['bool', 'conn'=>'resource'],
|
||||
'sqlsrv_configure' => ['bool', 'setting'=>'string', 'value'=>'mixed'],
|
||||
'sqlsrv_connect' => ['resource|false', 'serverName'=>'string', 'connectionInfo='=>'array'],
|
||||
'sqlsrv_errors' => ['?array', 'errorsOrWarnings='=>'int'],
|
||||
'sqlsrv_errors' => ['?array', 'errorsAndOrWarnings='=>'int'],
|
||||
'sqlsrv_execute' => ['bool', 'stmt'=>'resource'],
|
||||
'sqlsrv_fetch' => ['?bool', 'stmt'=>'resource', 'row='=>'int', 'offset='=>'int'],
|
||||
'sqlsrv_fetch_array' => ['array|null|false', 'stmt'=>'resource', 'fetchType='=>'int', 'row='=>'int', 'offset='=>'int'],
|
||||
@@ -12898,7 +12876,7 @@ return [
|
||||
'str_replace' => ['string|string[]', 'search'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', '&w_count='=>'int'],
|
||||
'str_rot13' => ['string', 'string'=>'string'],
|
||||
'str_shuffle' => ['string', 'string'=>'string'],
|
||||
'str_split' => ['list<string>', 'string'=>'string', 'length='=>'positive-int'],
|
||||
'str_split' => ['list<non-empty-string>', 'string'=>'string', 'length='=>'positive-int'],
|
||||
'str_starts_with' => ['bool', 'haystack'=>'string', 'needle'=>'string'],
|
||||
'str_word_count' => ['array<int, string>|int', 'string'=>'string', 'format='=>'int', 'characters='=>'?string'],
|
||||
'strcasecmp' => ['int', 'string1'=>'string', 'string2'=>'string'],
|
||||
@@ -12913,7 +12891,7 @@ return [
|
||||
'stream_context_create' => ['resource', 'options='=>'?array', 'params='=>'?array'],
|
||||
'stream_context_get_default' => ['resource', 'options='=>'?array'],
|
||||
'stream_context_get_options' => ['array', 'stream_or_context'=>'resource'],
|
||||
'stream_context_get_params' => ['array', 'context'=>'resource'],
|
||||
'stream_context_get_params' => ['array{notification:string,options:array}', 'context'=>'resource'],
|
||||
'stream_context_set_default' => ['resource', 'options'=>'array'],
|
||||
'stream_context_set_option' => ['bool', 'context'=>'', 'wrapper_or_options'=>'string', 'option_name'=>'string', 'value'=>''],
|
||||
'stream_context_set_option\'1' => ['bool', 'context'=>'', 'wrapper_or_options'=>'array'],
|
||||
@@ -12944,10 +12922,10 @@ return [
|
||||
'stream_socket_accept' => ['resource|false', 'socket'=>'resource', 'timeout='=>'?float', '&w_peer_name='=>'string'],
|
||||
'stream_socket_client' => ['resource|false', 'address'=>'string', '&w_error_code='=>'int', '&w_error_message='=>'string', 'timeout='=>'?float', 'flags='=>'int', 'context='=>'?resource'],
|
||||
'stream_socket_enable_crypto' => ['int|bool', 'stream'=>'resource', 'enable'=>'bool', 'crypto_method='=>'?int', 'session_stream='=>'?resource'],
|
||||
'stream_socket_get_name' => ['string', 'socket'=>'resource', 'remote'=>'bool'],
|
||||
'stream_socket_get_name' => ['string|false', 'socket'=>'resource', 'remote'=>'bool'],
|
||||
'stream_socket_pair' => ['resource[]|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'],
|
||||
'stream_socket_recvfrom' => ['string', 'socket'=>'resource', 'length'=>'int', 'flags='=>'int', '&w_address='=>'string'],
|
||||
'stream_socket_sendto' => ['int', 'socket'=>'resource', 'data'=>'string', 'flags='=>'int', 'address='=>'string'],
|
||||
'stream_socket_recvfrom' => ['string|false', 'socket'=>'resource', 'length'=>'int', 'flags='=>'int', '&w_address='=>'string'],
|
||||
'stream_socket_sendto' => ['int|false', 'socket'=>'resource', 'data'=>'string', 'flags='=>'int', 'address='=>'string'],
|
||||
'stream_socket_server' => ['resource|false', 'address'=>'string', '&w_error_code='=>'int', '&w_error_message='=>'string', 'flags='=>'int', 'context='=>'resource'],
|
||||
'stream_socket_shutdown' => ['bool', 'stream'=>'resource', 'mode'=>'int'],
|
||||
'stream_supports_lock' => ['bool', 'stream'=>'resource'],
|
||||
@@ -13603,7 +13581,7 @@ return [
|
||||
'SyncSharedMemory::size' => ['int'],
|
||||
'SyncSharedMemory::write' => ['int', 'string='=>'string', 'start='=>'int'],
|
||||
'sys_get_temp_dir' => ['string'],
|
||||
'sys_getloadavg' => ['array'],
|
||||
'sys_getloadavg' => ['array|false'],
|
||||
'syslog' => ['true', 'priority'=>'int', 'message'=>'string'],
|
||||
'system' => ['string|false', 'command'=>'string', '&w_result_code='=>'int'],
|
||||
'taint' => ['bool', '&rw_string'=>'string', '&...w_other_strings='=>'string'],
|
||||
@@ -13985,7 +13963,7 @@ return [
|
||||
'Transliterator::getErrorCode' => ['int'],
|
||||
'Transliterator::getErrorMessage' => ['string'],
|
||||
'Transliterator::listIDs' => ['array'],
|
||||
'Transliterator::transliterate' => ['string|false', 'subject'=>'string', 'start='=>'int', 'end='=>'int'],
|
||||
'Transliterator::transliterate' => ['string|false', 'string'=>'string', 'start='=>'int', 'end='=>'int'],
|
||||
'transliterator_create' => ['?Transliterator', 'id'=>'string', 'direction='=>'int'],
|
||||
'transliterator_create_from_rules' => ['?Transliterator', 'rules'=>'string', 'direction='=>'int'],
|
||||
'transliterator_create_inverse' => ['?Transliterator', 'transliterator'=>'Transliterator'],
|
||||
@@ -14008,8 +13986,8 @@ return [
|
||||
'uasort' => ['true', '&rw_array'=>'array', 'callback'=>'callable(mixed,mixed):int'],
|
||||
'ucfirst' => ['string', 'string'=>'string'],
|
||||
'UConverter::__construct' => ['void', 'destination_encoding='=>'?string', 'source_encoding='=>'?string'],
|
||||
'UConverter::convert' => ['string', 'string'=>'string', 'reverse='=>'bool'],
|
||||
'UConverter::fromUCallback' => ['mixed', 'reason'=>'int', 'source'=>'string', 'codePoint'=>'string', '&w_error'=>'int'],
|
||||
'UConverter::convert' => ['string', 'str'=>'string', 'reverse='=>'bool'],
|
||||
'UConverter::fromUCallback' => ['string|int|array|null', 'reason'=>'int', 'source'=>'array', 'codePoint'=>'int', '&w_error'=>'int'],
|
||||
'UConverter::getAliases' => ['array|false|null', 'name'=>'string'],
|
||||
'UConverter::getAvailable' => ['array'],
|
||||
'UConverter::getDestinationEncoding' => ['string|false|null'],
|
||||
@@ -14020,12 +13998,12 @@ return [
|
||||
'UConverter::getSourceType' => ['int|false|null'],
|
||||
'UConverter::getStandards' => ['?array'],
|
||||
'UConverter::getSubstChars' => ['string|false|null'],
|
||||
'UConverter::reasonText' => ['string', 'reason='=>'int'],
|
||||
'UConverter::reasonText' => ['string', 'reason'=>'int'],
|
||||
'UConverter::setDestinationEncoding' => ['bool', 'encoding'=>'string'],
|
||||
'UConverter::setSourceEncoding' => ['bool', 'encoding'=>'string'],
|
||||
'UConverter::setSubstChars' => ['bool', 'chars'=>'string'],
|
||||
'UConverter::toUCallback' => ['string|int|array|null', 'reason'=>'int', 'source'=>'string', 'codeUnits'=>'string', '&w_error'=>'int'],
|
||||
'UConverter::transcode' => ['string', 'string'=>'string', 'toEncoding'=>'string', 'fromEncoding'=>'string', 'options='=>'?array'],
|
||||
'UConverter::transcode' => ['string', 'str'=>'string', 'toEncoding'=>'string', 'fromEncoding'=>'string', 'options='=>'?array'],
|
||||
'ucwords' => ['string', 'string'=>'string', 'separators='=>'string'],
|
||||
'udm_add_search_limit' => ['bool', 'agent'=>'resource', 'var'=>'int', 'value'=>'string'],
|
||||
'udm_alloc_agent' => ['resource', 'dbaddr'=>'string', 'dbmode='=>'string'],
|
||||
@@ -14239,7 +14217,7 @@ return [
|
||||
'UnexpectedValueException::getTrace' => ['list<array{file?:string,line?:int,function:string,class?:class-string,type?:\'::\'|\'->\',args?:array<mixed>}>'],
|
||||
'UnexpectedValueException::getTraceAsString' => ['string'],
|
||||
'uniqid' => ['non-empty-string', 'prefix='=>'string', 'more_entropy='=>'bool'],
|
||||
'unixtojd' => ['int', 'timestamp='=>'?int'],
|
||||
'unixtojd' => ['int|false', 'timestamp='=>'?int'],
|
||||
'unlink' => ['bool', 'filename'=>'string', 'context='=>'resource'],
|
||||
'unpack' => ['array|false', 'format'=>'string', 'string'=>'string', 'offset='=>'int'],
|
||||
'unregister_tick_function' => ['void', 'callback'=>'callable'],
|
||||
@@ -14502,17 +14480,12 @@ return [
|
||||
'wddx_packet_start' => ['resource|false', 'comment='=>'string'],
|
||||
'wddx_serialize_value' => ['string|false', 'value'=>'mixed', 'comment='=>'string'],
|
||||
'wddx_serialize_vars' => ['string|false', 'var_name'=>'mixed', '...vars='=>'mixed'],
|
||||
'WeakMap::__construct' => ['void'],
|
||||
'WeakMap::count' => ['int'],
|
||||
'WeakMap::current' => ['mixed'],
|
||||
'WeakMap::key' => ['object'],
|
||||
'WeakMap::next' => ['void'],
|
||||
'WeakMap::getIterator' => ['Iterator'],
|
||||
'WeakMap::offsetExists' => ['bool', 'object'=>'object'],
|
||||
'WeakMap::offsetGet' => ['mixed', 'object'=>'object'],
|
||||
'WeakMap::offsetSet' => ['void', 'object'=>'object', 'value'=>'mixed'],
|
||||
'WeakMap::offsetUnset' => ['void', 'object'=>'object'],
|
||||
'WeakMap::rewind' => ['void'],
|
||||
'WeakMap::valid' => ['bool'],
|
||||
'Weakref::acquire' => ['bool'],
|
||||
'Weakref::get' => ['object'],
|
||||
'Weakref::release' => ['bool'],
|
||||
@@ -14728,7 +14701,7 @@ return [
|
||||
'xml_parser_create' => ['XMLParser', 'encoding='=>'?string'],
|
||||
'xml_parser_create_ns' => ['XMLParser', 'encoding='=>'?string', 'separator='=>'string'],
|
||||
'xml_parser_free' => ['bool', 'parser'=>'XMLParser'],
|
||||
'xml_parser_get_option' => ['string', 'parser'=>'XMLParser', 'option'=>'int'],
|
||||
'xml_parser_get_option' => ['string|int', 'parser'=>'XMLParser', 'option'=>'int'],
|
||||
'xml_parser_set_option' => ['bool', 'parser'=>'XMLParser', 'option'=>'int', 'value'=>'mixed'],
|
||||
'xml_set_character_data_handler' => ['true', 'parser'=>'XMLParser', 'handler'=>'callable'],
|
||||
'xml_set_default_handler' => ['true', 'parser'=>'XMLParser', 'handler'=>'callable'],
|
||||
@@ -14753,18 +14726,18 @@ return [
|
||||
'XMLReader::expand' => ['DOMNode|false', 'baseNode='=>'?DOMNode'],
|
||||
'XMLReader::getAttribute' => ['?string', 'name'=>'string'],
|
||||
'XMLReader::getAttributeNo' => ['?string', 'index'=>'int'],
|
||||
'XMLReader::getAttributeNs' => ['?string', 'name'=>'string', 'namespaceuri'=>'string'],
|
||||
'XMLReader::getAttributeNs' => ['?string', 'name'=>'string', 'namespace'=>'string'],
|
||||
'XMLReader::getParserProperty' => ['bool', 'property'=>'int'],
|
||||
'XMLReader::isValid' => ['bool'],
|
||||
'XMLReader::lookupNamespace' => ['?string', 'prefix'=>'string'],
|
||||
'XMLReader::moveToAttribute' => ['bool', 'name'=>'string'],
|
||||
'XMLReader::moveToAttributeNo' => ['bool', 'index'=>'int'],
|
||||
'XMLReader::moveToAttributeNs' => ['bool', 'localname'=>'string', 'namespaceuri'=>'string'],
|
||||
'XMLReader::moveToAttributeNs' => ['bool', 'name'=>'string', 'namespace'=>'string'],
|
||||
'XMLReader::moveToElement' => ['bool'],
|
||||
'XMLReader::moveToFirstAttribute' => ['bool'],
|
||||
'XMLReader::moveToNextAttribute' => ['bool'],
|
||||
'XMLReader::next' => ['bool', 'localname='=>'string'],
|
||||
'XMLReader::open' => ['bool', 'uri'=>'string', 'encoding='=>'?string', 'options='=>'int'],
|
||||
'XMLReader::next' => ['bool', 'name='=>'?string'],
|
||||
'XMLReader::open' => ['bool|XmlReader', 'uri'=>'string', 'encoding='=>'?string', 'flags='=>'int'],
|
||||
'XMLReader::read' => ['bool'],
|
||||
'XMLReader::readInnerXML' => ['string'],
|
||||
'XMLReader::readOuterXML' => ['string'],
|
||||
@@ -14773,7 +14746,7 @@ return [
|
||||
'XMLReader::setRelaxNGSchema' => ['bool', 'filename'=>'?string'],
|
||||
'XMLReader::setRelaxNGSchemaSource' => ['bool', 'source'=>'?string'],
|
||||
'XMLReader::setSchema' => ['bool', 'filename'=>'?string'],
|
||||
'XMLReader::XML' => ['bool', 'source'=>'string', 'encoding='=>'?string', 'options='=>'int'],
|
||||
'XMLReader::XML' => ['bool|XMLReader', 'source'=>'string', 'encoding='=>'?string', 'flags='=>'int'],
|
||||
'XMLWriter::endAttribute' => ['bool'],
|
||||
'XMLWriter::endCdata' => ['bool'],
|
||||
'XMLWriter::endComment' => ['bool'],
|
||||
@@ -14866,13 +14839,13 @@ return [
|
||||
'XsltProcessor::getSecurityPrefs' => ['int'],
|
||||
'XSLTProcessor::hasExsltSupport' => ['bool'],
|
||||
'XSLTProcessor::importStylesheet' => ['bool', 'stylesheet'=>'object'],
|
||||
'XSLTProcessor::registerPHPFunctions' => ['void', 'functions='=>'mixed'],
|
||||
'XSLTProcessor::registerPHPFunctions' => ['void', 'functions='=>'array|string|null'],
|
||||
'XSLTProcessor::removeParameter' => ['bool', 'namespace'=>'string', 'name'=>'string'],
|
||||
'XSLTProcessor::setParameter' => ['bool', 'namespace'=>'string', 'name'=>'string', 'value'=>'string'],
|
||||
'XSLTProcessor::setParameter\'1' => ['bool', 'namespace'=>'string', 'options'=>'array'],
|
||||
'XSLTProcessor::setProfiling' => ['bool', 'filename'=>'?string'],
|
||||
'XsltProcessor::setSecurityPrefs' => ['int', 'preferences'=>'int'],
|
||||
'XSLTProcessor::transformToDoc' => ['DOMDocument|false', 'document'=>'DOMNode'],
|
||||
'XSLTProcessor::transformToDoc' => ['DOMDocument|false', 'document'=>'DOMNode', 'returnClass='=>'?string'],
|
||||
'XSLTProcessor::transformToURI' => ['int', 'document'=>'DOMDocument', 'uri'=>'string'],
|
||||
'XSLTProcessor::transformToXML' => ['string|false', 'document'=>'DOMDocument'],
|
||||
'yac::__construct' => ['void', 'prefix='=>'string'],
|
||||
@@ -15778,7 +15751,7 @@ return [
|
||||
'zip_entry_compressedsize' => ['int', 'zip_entry'=>'resource'],
|
||||
'zip_entry_compressionmethod' => ['string', 'zip_entry'=>'resource'],
|
||||
'zip_entry_filesize' => ['int', 'zip_entry'=>'resource'],
|
||||
'zip_entry_name' => ['string', 'zip_entry'=>'resource'],
|
||||
'zip_entry_name' => ['string|false', 'zip_entry'=>'resource'],
|
||||
'zip_entry_open' => ['bool', 'zip_dp'=>'resource', 'zip_entry'=>'resource', 'mode='=>'string'],
|
||||
'zip_entry_read' => ['string|false', 'zip_entry'=>'resource', 'len='=>'int'],
|
||||
'zip_open' => ['resource|int|false', 'filename'=>'string'],
|
||||
@@ -15806,8 +15779,8 @@ return [
|
||||
'ZipArchive::getStream' => ['resource|false', 'name'=>'string'],
|
||||
'ZipArchive::getStreamIndex' => ['resource|false', 'index'=>'int', 'flags='=>'int'],
|
||||
'ZipArchive::getStreamName' => ['resource|false', 'name'=>'string', 'flags='=>'int'],
|
||||
'ZipArchive::isCompressionMethodSupported' => ['bool', 'method'=>'int', 'encode='=>'bool'],
|
||||
'ZipArchive::isEncryptionMethodSupported' => ['bool', 'method'=>'int', 'encode='=>'bool'],
|
||||
'ZipArchive::isCompressionMethodSupported' => ['bool', 'method'=>'int', 'enc='=>'bool'],
|
||||
'ZipArchive::isEncryptionMethodSupported' => ['bool', 'method'=>'int', 'enc='=>'bool'],
|
||||
'ZipArchive::locateName' => ['int|false', 'name'=>'string', 'flags='=>'int'],
|
||||
'ZipArchive::open' => ['int|bool', 'filename'=>'string', 'flags='=>'int'],
|
||||
'ZipArchive::registerCancelCallback' => ['bool', 'callback'=>'callable'],
|
||||
@@ -15818,9 +15791,9 @@ return [
|
||||
'ZipArchive::setArchiveComment' => ['bool', 'comment'=>'string'],
|
||||
'ZipArchive::setCommentIndex' => ['bool', 'index'=>'int', 'comment'=>'string'],
|
||||
'ZipArchive::setCommentName' => ['bool', 'name'=>'string', 'comment'=>'string'],
|
||||
'ZipArchive::setCompressionIndex' => ['bool', 'index'=>'int', 'comp_method'=>'int', 'comp_flags='=>'int'],
|
||||
'ZipArchive::setCompressionName' => ['bool', 'name'=>'string', 'comp_method'=>'int', 'comp_flags='=>'int'],
|
||||
'ZipArchive::setEncryptionIndex' => ['bool', 'index'=>'int', 'method'=>'string', 'password='=>'?string'],
|
||||
'ZipArchive::setCompressionIndex' => ['bool', 'index'=>'int', 'method'=>'int', 'compflags='=>'int'],
|
||||
'ZipArchive::setCompressionName' => ['bool', 'name'=>'string', 'method'=>'int', 'compflags='=>'int'],
|
||||
'ZipArchive::setEncryptionIndex' => ['bool', 'index'=>'int', 'method'=>'int', 'password='=>'?string'],
|
||||
'ZipArchive::setEncryptionName' => ['bool', 'name'=>'string', 'method'=>'int', 'password='=>'?string'],
|
||||
'ZipArchive::setExternalAttributesIndex' => ['bool', 'index'=>'int', 'opsys'=>'int', 'attr'=>'int', 'flags='=>'int'],
|
||||
'ZipArchive::setExternalAttributesName' => ['bool', 'name'=>'string', 'opsys'=>'int', 'attr'=>'int', 'flags='=>'int'],
|
||||
|
||||
@@ -30,7 +30,7 @@ return [
|
||||
'sapi_windows_cp_get' => ['int', 'kind='=>'string'],
|
||||
'sapi_windows_cp_is_utf8' => ['bool'],
|
||||
'sapi_windows_cp_set' => ['bool', 'codepage'=>'int'],
|
||||
'session_create_id' => ['string', 'prefix='=>'string'],
|
||||
'session_create_id' => ['string|false', 'prefix='=>'string'],
|
||||
'session_gc' => ['int|false'],
|
||||
],
|
||||
'changed' => [
|
||||
@@ -42,6 +42,10 @@ return [
|
||||
'old' => ['string|false', 'value'=>'IntlCalendar|DateTime|array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int, 6: int, 7: int, 8: int}|array{tm_sec: int, tm_min: int, tm_hour: int, tm_mday: int, tm_mon: int, tm_year: int, tm_wday: int, tm_yday: int, tm_isdst: int}|string|int|float'],
|
||||
'new' => ['string|false', 'value'=>'IntlCalendar|DateTimeInterface|array{0: int, 1: int, 2: int, 3: int, 4: int, 5: int, 6: int, 7: int, 8: int}|array{tm_sec: int, tm_min: int, tm_hour: int, tm_mday: int, tm_mon: int, tm_year: int, tm_wday: int, tm_yday: int, tm_isdst: int}|string|int|float'],
|
||||
],
|
||||
'SessionHandler::gc' => [
|
||||
'old' => ['bool', 'max_lifetime'=>'int'],
|
||||
'new' => ['int|false', 'max_lifetime'=>'int'],
|
||||
],
|
||||
'SQLite3::createFunction' => [
|
||||
'old' => ['bool', 'name'=>'string', 'callback'=>'callable', 'argCount='=>'int'],
|
||||
'new' => ['bool', 'name'=>'string', 'callback'=>'callable', 'argCount='=>'int', 'flags='=>'int'],
|
||||
|
||||
@@ -19,7 +19,7 @@ return [
|
||||
'DOMNodeList::count' => ['int'],
|
||||
'ReflectionClass::isIterable' => ['bool'],
|
||||
'ZipArchive::count' => ['int'],
|
||||
'ZipArchive::setEncryptionIndex' => ['bool', 'index'=>'int', 'method'=>'string', 'password='=>'string'],
|
||||
'ZipArchive::setEncryptionIndex' => ['bool', 'index'=>'int', 'method'=>'int', 'password='=>'string'],
|
||||
'ZipArchive::setEncryptionName' => ['bool', 'name'=>'string', 'method'=>'int', 'password='=>'string'],
|
||||
'ftp_append' => ['bool', 'ftp'=>'resource', 'remote_filename'=>'string', 'local_filename'=>'string', 'mode='=>'int'],
|
||||
'hash_hmac_algos' => ['list<string>'],
|
||||
@@ -103,7 +103,7 @@ return [
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_init_pull' => ['string', 'header'=>'string', 'key'=>'string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_init_push' => ['array', 'key'=>'string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_keygen' => ['non-empty-string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_pull' => ['array', '&r_state'=>'string', 'ciphertext'=>'string', 'additional_data='=>'string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_pull' => ['array|false', '&r_state'=>'string', 'ciphertext'=>'string', 'additional_data='=>'string'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_push' => ['string', '&w_state'=>'string', 'message'=>'string', 'additional_data='=>'string', 'tag='=>'int'],
|
||||
'sodium_crypto_secretstream_xchacha20poly1305_rekey' => ['void', '&w_state'=>'string'],
|
||||
'sodium_crypto_shorthash' => ['string', 'message'=>'string', 'key'=>'string'],
|
||||
|
||||
@@ -18,7 +18,7 @@ return [
|
||||
'added' => [
|
||||
'DateTime::createFromImmutable' => ['static', 'object'=>'DateTimeImmutable'],
|
||||
'JsonException::__clone' => ['void'],
|
||||
'JsonException::__construct' => ['void'],
|
||||
'JsonException::__construct' => ['void', "message="=>"string", 'code='=>'int', 'previous='=>'?Throwable'],
|
||||
'JsonException::__toString' => ['string'],
|
||||
'JsonException::__wakeup' => ['void'],
|
||||
'JsonException::getCode' => ['int'],
|
||||
@@ -77,8 +77,8 @@ return [
|
||||
'new' => ['bool|string', 'ldap'=>'resource', 'user='=>'string', 'old_password='=>'string', 'new_password='=>'string', '&w_controls='=>'array'],
|
||||
],
|
||||
'ldap_list' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
],
|
||||
'ldap_mod_add' => [
|
||||
'old' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'entry'=>'array'],
|
||||
@@ -101,16 +101,16 @@ return [
|
||||
'new' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'modifications_info'=>'array', 'controls='=>'array'],
|
||||
],
|
||||
'ldap_read' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
],
|
||||
'ldap_rename' => [
|
||||
'old' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool'],
|
||||
'new' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'array'],
|
||||
],
|
||||
'ldap_search' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|resource[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|resource[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'old' => ['resource[]|resource|false', 'ldap'=>'resource|resource[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'new' => ['resource[]|resource|false', 'ldap'=>'resource|resource[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
],
|
||||
],
|
||||
'removed' => [
|
||||
|
||||
@@ -28,6 +28,13 @@ return [
|
||||
'ReflectionParameter::getAttributes' => ['list<ReflectionAttribute>', 'name='=>'?string', 'flags='=>'int'],
|
||||
'ReflectionProperty::getAttributes' => ['list<ReflectionAttribute>', 'name='=>'?string', 'flags='=>'int'],
|
||||
'ReflectionUnionType::getTypes' => ['list<ReflectionNamedType>'],
|
||||
'SplFixedArray::getIterator' => ['Iterator'],
|
||||
'WeakMap::count' => ['int'],
|
||||
'WeakMap::getIterator' => ['Iterator'],
|
||||
'WeakMap::offsetExists' => ['bool', 'object'=>'object'],
|
||||
'WeakMap::offsetGet' => ['mixed', 'object'=>'object'],
|
||||
'WeakMap::offsetSet' => ['void', 'object'=>'object', 'value'=>'mixed'],
|
||||
'WeakMap::offsetUnset' => ['void', 'object'=>'object'],
|
||||
'fdiv' => ['float', 'num1'=>'float', 'num2'=>'float'],
|
||||
'get_debug_type' => ['string', 'value'=>'mixed'],
|
||||
'get_resource_id' => ['int', 'resource'=>'resource'],
|
||||
@@ -217,6 +224,10 @@ return [
|
||||
'old' => ['string', 'locale'=>'string', 'displayLocale='=>'string'],
|
||||
'new' => ['string', 'locale'=>'string', 'displayLocale='=>'?string'],
|
||||
],
|
||||
'mysqli_stmt::__construct' => [
|
||||
'old' => ['void', 'mysql'=>'mysqli', 'query='=>'string'],
|
||||
'new' => ['void', 'mysql'=>'mysqli', 'query='=>'?string'],
|
||||
],
|
||||
'NumberFormatter::__construct' => [
|
||||
'old' => ['void', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'],
|
||||
'new' => ['void', 'locale'=>'string', 'style'=>'int', 'pattern='=>'?string'],
|
||||
@@ -373,6 +384,14 @@ return [
|
||||
'old' => ['?Closure', 'object='=>'object'],
|
||||
'new' => ['Closure', 'object='=>'?object'],
|
||||
],
|
||||
'ReflectionObject::getConstants' => [
|
||||
'old' => ['array<string,mixed>'],
|
||||
'new' => ['array<string,mixed>', 'filter='=>'?int'],
|
||||
],
|
||||
'ReflectionObject::getReflectionConstants' => [
|
||||
'old' => ['list<\ReflectionClassConstant>'],
|
||||
'new' => ['list<\ReflectionClassConstant>', 'filter='=>'?int'],
|
||||
],
|
||||
'ReflectionObject::newInstanceArgs' => [
|
||||
'old' => ['object', 'args='=>'list<mixed>'],
|
||||
'new' => ['object', 'args='=>'list<mixed>|array<string, mixed>'],
|
||||
@@ -461,6 +480,10 @@ return [
|
||||
'old' => ['string|false'],
|
||||
'new' => ['string'],
|
||||
],
|
||||
'XMLReader::next' => [
|
||||
'old' => ['bool', 'name='=>'string'],
|
||||
'new' => ['bool', 'name='=>'?string'],
|
||||
],
|
||||
'XMLWriter::startAttributeNs' => [
|
||||
'old' => ['bool', 'prefix'=>'string', 'name'=>'string', 'namespace'=>'?string'],
|
||||
'new' => ['bool', 'prefix'=>'?string', 'name'=>'string', 'namespace'=>'?string'],
|
||||
@@ -478,8 +501,8 @@ return [
|
||||
'new' => ['string'],
|
||||
],
|
||||
'ZipArchive::setEncryptionIndex' => [
|
||||
'old' => ['bool', 'index'=>'int', 'method'=>'string', 'password='=>'string'],
|
||||
'new' => ['bool', 'index'=>'int', 'method'=>'string', 'password='=>'?string'],
|
||||
'old' => ['bool', 'index'=>'int', 'method'=>'int', 'password='=>'string'],
|
||||
'new' => ['bool', 'index'=>'int', 'method'=>'int', 'password='=>'?string'],
|
||||
],
|
||||
'ZipArchive::setEncryptionName' => [
|
||||
'old' => ['bool', 'name'=>'string', 'method'=>'int', 'password='=>'string'],
|
||||
@@ -618,8 +641,8 @@ return [
|
||||
'new' => ['void', 'handle'=>'CurlHandle'],
|
||||
],
|
||||
'curl_copy_handle' => [
|
||||
'old' => ['resource', 'ch'=>'resource'],
|
||||
'new' => ['CurlHandle', 'handle'=>'CurlHandle'],
|
||||
'old' => ['resource|false', 'ch'=>'resource'],
|
||||
'new' => ['CurlHandle|false', 'handle'=>'CurlHandle'],
|
||||
],
|
||||
'curl_errno' => [
|
||||
'old' => ['int', 'ch'=>'resource'],
|
||||
@@ -798,8 +821,8 @@ return [
|
||||
'new' => ['DOMElement', 'node'=>'SimpleXMLElement'],
|
||||
],
|
||||
'easter_date' => [
|
||||
'old' => ['int', 'year='=>'int'],
|
||||
'new' => ['int', 'year='=>'?int'],
|
||||
'old' => ['int', 'year='=>'int', 'mode='=>'int'],
|
||||
'new' => ['int', 'year='=>'?int', 'mode='=>'int'],
|
||||
],
|
||||
'easter_days' => [
|
||||
'old' => ['int', 'year='=>'int', 'mode='=>'int'],
|
||||
@@ -934,8 +957,8 @@ return [
|
||||
'new' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
],
|
||||
'get_class_methods' => [
|
||||
'old' => ['list<string>|null', 'object_or_class'=>'mixed'],
|
||||
'new' => ['list<string>', 'object_or_class'=>'object|class-string'],
|
||||
'old' => ['list<non-falsy-string>|null', 'object_or_class'=>'mixed'],
|
||||
'new' => ['list<non-falsy-string>', 'object_or_class'=>'object|class-string'],
|
||||
],
|
||||
'get_headers' => [
|
||||
'old' => ['array|false', 'url'=>'string', 'associative='=>'int', 'context='=>'?resource'],
|
||||
@@ -982,12 +1005,12 @@ return [
|
||||
'new' => ['string|false', 'stream'=>'resource', 'length='=>'?int'],
|
||||
],
|
||||
'gzputs' => [
|
||||
'old' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'],
|
||||
'new' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
'old' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'],
|
||||
'new' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
],
|
||||
'gzwrite' => [
|
||||
'old' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'],
|
||||
'new' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
'old' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'],
|
||||
'new' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'?int'],
|
||||
],
|
||||
'hash' => [
|
||||
'old' => ['string|false', 'algo'=>'string', 'data'=>'string', 'binary='=>'bool'],
|
||||
@@ -1506,8 +1529,8 @@ return [
|
||||
'new' => ['bool|string', 'ldap'=>'resource', 'user='=>'string', 'old_password='=>'string', 'new_password='=>'string', '&w_controls='=>'array|null'],
|
||||
],
|
||||
'ldap_list' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
],
|
||||
'ldap_rename_ext' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'array'],
|
||||
@@ -1546,16 +1569,16 @@ return [
|
||||
'new' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'modifications_info'=>'array', 'controls='=>'?array'],
|
||||
],
|
||||
'ldap_read' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
],
|
||||
'ldap_rename' => [
|
||||
'old' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'array'],
|
||||
'new' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'?array'],
|
||||
],
|
||||
'ldap_search' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|resource[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'new' => ['resource|false', 'ldap'=>'resource|resource[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'old' => ['resource[]|resource|false', 'ldap'=>'resource|resource[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'array'],
|
||||
'new' => ['resource[]|resource|false', 'ldap'=>'resource|resource[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
],
|
||||
'ldap_set_rebind_proc' => [
|
||||
'old' => ['bool', 'ldap'=>'resource', 'callback'=>'callable'],
|
||||
@@ -1866,8 +1889,8 @@ return [
|
||||
'new' => ['bool', 'mysql'=>'mysqli', 'flags='=>'int', 'name='=>'?string'],
|
||||
],
|
||||
'number_format' => [
|
||||
'old' => ['string', 'num'=>'float|int', 'decimals='=>'int'],
|
||||
'new' => ['string', 'num'=>'float|int', 'decimals='=>'int', 'decimal_separator='=>'?string', 'thousands_separator='=>'?string'],
|
||||
'old' => ['string', 'num'=>'float', 'decimals='=>'int'],
|
||||
'new' => ['string', 'num'=>'float', 'decimals='=>'int', 'decimal_separator='=>'?string', 'thousands_separator='=>'?string'],
|
||||
],
|
||||
'numfmt_create' => [
|
||||
'old' => ['NumberFormatter|null', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'],
|
||||
@@ -2186,28 +2209,28 @@ return [
|
||||
'new' => ['bool', 'semaphore'=>'SysvSemaphore'],
|
||||
],
|
||||
'session_cache_expire' => [
|
||||
'old' => ['int', 'value='=>'int'],
|
||||
'new' => ['int', 'value='=>'?int'],
|
||||
'old' => ['int|false', 'value='=>'int'],
|
||||
'new' => ['int|false', 'value='=>'?int'],
|
||||
],
|
||||
'session_cache_limiter' => [
|
||||
'old' => ['string', 'value='=>'string'],
|
||||
'new' => ['string', 'value='=>'?string'],
|
||||
'old' => ['string|false', 'value='=>'string'],
|
||||
'new' => ['string|false', 'value='=>'?string'],
|
||||
],
|
||||
'session_id' => [
|
||||
'old' => ['string|false', 'id='=>'string'],
|
||||
'new' => ['string|false', 'id='=>'?string'],
|
||||
],
|
||||
'session_module_name' => [
|
||||
'old' => ['string', 'module='=>'string'],
|
||||
'new' => ['string', 'module='=>'?string'],
|
||||
'old' => ['string|false', 'module='=>'string'],
|
||||
'new' => ['string|false', 'module='=>'?string'],
|
||||
],
|
||||
'session_name' => [
|
||||
'old' => ['string|false', 'name='=>'string'],
|
||||
'new' => ['string|false', 'name='=>'?string'],
|
||||
],
|
||||
'session_save_path' => [
|
||||
'old' => ['string', 'path='=>'string'],
|
||||
'new' => ['string', 'path='=>'?string'],
|
||||
'old' => ['string|false', 'path='=>'string'],
|
||||
'new' => ['string|false', 'path='=>'?string'],
|
||||
],
|
||||
'session_set_cookie_params' => [
|
||||
'old' => ['bool', 'lifetime'=>'int', 'path='=>'string', 'domain='=>'string', 'secure='=>'bool', 'httponly='=>'bool'],
|
||||
@@ -2578,8 +2601,8 @@ return [
|
||||
'new' => ['int', 'mask='=>'?int'],
|
||||
],
|
||||
'unixtojd' => [
|
||||
'old' => ['int', 'timestamp='=>'int'],
|
||||
'new' => ['int', 'timestamp='=>'?int'],
|
||||
'old' => ['int|false', 'timestamp='=>'int'],
|
||||
'new' => ['int|false', 'timestamp='=>'?int'],
|
||||
],
|
||||
'xml_get_current_byte_index' => [
|
||||
'old' => ['int|false', 'parser'=>'resource'],
|
||||
@@ -2618,8 +2641,8 @@ return [
|
||||
'new' => ['bool', 'parser'=>'XMLParser'],
|
||||
],
|
||||
'xml_parser_get_option' => [
|
||||
'old' => ['string|false', 'parser'=>'resource', 'option'=>'int'],
|
||||
'new' => ['string', 'parser'=>'XMLParser', 'option'=>'int'],
|
||||
'old' => ['string|int', 'parser'=>'resource', 'option'=>'int'],
|
||||
'new' => ['string|int', 'parser'=>'XMLParser', 'option'=>'int'],
|
||||
],
|
||||
'xml_parser_set_option' => [
|
||||
'old' => ['bool', 'parser'=>'resource', 'option'=>'int', 'value'=>'mixed'],
|
||||
@@ -2862,7 +2885,7 @@ return [
|
||||
'ldap_control_paged_result' => ['bool', 'link_identifier'=>'resource', 'pagesize'=>'int', 'iscritical='=>'bool', 'cookie='=>'string'],
|
||||
'ldap_control_paged_result_response' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', '&w_cookie'=>'string', '&w_estimated'=>'int'],
|
||||
'ldap_sort' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', 'sortfilter'=>'string'],
|
||||
'number_format\'1' => ['string', 'num'=>'float|int', 'decimals'=>'int', 'decimal_separator'=>'?string', 'thousands_separator'=>'?string'],
|
||||
'number_format\'1' => ['string', 'num'=>'float', 'decimals'=>'int', 'decimal_separator'=>'?string', 'thousands_separator'=>'?string'],
|
||||
'png2wbmp' => ['bool', 'pngname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'],
|
||||
'read_exif_data' => ['array', 'filename'=>'string', 'sections_needed='=>'string', 'sub_arrays='=>'bool', 'read_thumbnail='=>'bool'],
|
||||
'Reflection::export' => ['?string', 'r'=>'reflector', 'return='=>'bool'],
|
||||
@@ -2883,6 +2906,11 @@ return [
|
||||
'SimpleXMLIterator::next' => ['void'],
|
||||
'SimpleXMLIterator::hasChildren' => ['bool'],
|
||||
'SimpleXMLIterator::getChildren' => ['?SimpleXMLIterator'],
|
||||
'SplFixedArray::current' => ['mixed'],
|
||||
'SplFixedArray::key' => ['int'],
|
||||
'SplFixedArray::next' => ['void'],
|
||||
'SplFixedArray::rewind' => ['void'],
|
||||
'SplFixedArray::valid' => ['bool'],
|
||||
'SplTempFileObject::fgetss' => ['string', 'allowable_tags='=>'string'],
|
||||
'xmlrpc_decode' => ['mixed', 'xml'=>'string', 'encoding='=>'string'],
|
||||
'xmlrpc_decode_request' => ['?array', 'xml'=>'string', '&w_method'=>'string', 'encoding='=>'string'],
|
||||
|
||||
@@ -619,8 +619,8 @@ return [
|
||||
'new' => ['array|false', 'ldap'=>'LDAP\Connection', 'entry'=>'LDAP\ResultEntry', 'attribute'=>'string'],
|
||||
],
|
||||
'ldap_list' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'new' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'new' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
],
|
||||
'ldap_mod_add' => [
|
||||
'old' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'entry'=>'array', 'controls='=>'?array'],
|
||||
@@ -679,8 +679,8 @@ return [
|
||||
'new' => ['bool', 'ldap'=>'LDAP\Connection', 'result'=>'LDAP\Result', '&w_error_code'=>'int', '&w_matched_dn='=>'string', '&w_error_message='=>'string', '&w_referrals='=>'array', '&w_controls='=>'array'],
|
||||
],
|
||||
'ldap_read' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'new' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'old' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'new' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
],
|
||||
'ldap_rename' => [
|
||||
'old' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'?array'],
|
||||
@@ -695,8 +695,8 @@ return [
|
||||
'new' => ['bool', 'ldap'=>'LDAP\Connection', 'dn='=>'?string', 'password='=>'?string', 'mech='=>'?string', 'realm='=>'?string', 'authc_id='=>'?string', 'authz_id='=>'?string', 'props='=>'?string'],
|
||||
],
|
||||
'ldap_search' => [
|
||||
'old' => ['resource|false', 'ldap'=>'resource|resource[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'new' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'old' => ['resource[]|resource|false', 'ldap'=>'resource|resource[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
'new' => ['LDAP\Result|LDAP\Result[]|false', 'ldap'=>'LDAP\Connection|LDAP\Connection[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int', 'controls='=>'?array'],
|
||||
],
|
||||
'ldap_set_option' => [
|
||||
'old' => ['bool', 'ldap'=>'resource|null', 'option'=>'int', 'value'=>'mixed'],
|
||||
|
||||
@@ -41,9 +41,17 @@ return [
|
||||
'old' => ['resource', 'path'=>'string', 'mode'=>'string', 'handler='=>'string', '...handler_params='=>'string'],
|
||||
'new' => ['resource', 'path'=>'string', 'mode'=>'string', 'handler='=>'?string', 'permission='=>'int', 'map_size='=>'int', 'flags='=>'?int'],
|
||||
],
|
||||
'iterator_count' => [
|
||||
'old' => ['0|positive-int', 'iterator'=>'Traversable'],
|
||||
'new' => ['0|positive-int', 'iterator'=>'Traversable|array'],
|
||||
],
|
||||
'iterator_to_array' => [
|
||||
'old' => ['array', 'iterator'=>'Traversable', 'preserve_keys='=>'bool'],
|
||||
'new' => ['array', 'iterator'=>'Traversable|array', 'preserve_keys='=>'bool'],
|
||||
],
|
||||
'str_split' => [
|
||||
'old' => ['non-empty-list<string>', 'string'=>'string', 'length='=>'positive-int'],
|
||||
'new' => ['list<string>', 'string'=>'string', 'length='=>'positive-int'],
|
||||
'new' => ['list<non-empty-string>', 'string'=>'string', 'length='=>'positive-int'],
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
@@ -293,7 +293,6 @@ return [
|
||||
'COMPersistHelper::SaveToStream' => ['int', 'stream'=>''],
|
||||
'COMPersistHelper::__construct' => ['void', 'variant'=>'object'],
|
||||
'CURLFile::__construct' => ['void', 'filename'=>'string', 'mime_type='=>'string', 'posted_filename='=>'string'],
|
||||
'CURLFile::__wakeup' => ['void'],
|
||||
'CURLFile::getFilename' => ['string'],
|
||||
'CURLFile::getMimeType' => ['string'],
|
||||
'CURLFile::getPostFilename' => ['string'],
|
||||
@@ -1623,8 +1622,6 @@ return [
|
||||
'GEOSWKTWriter::setRoundingPrecision' => ['void', 'prec'=>'int'],
|
||||
'GEOSWKTWriter::setTrim' => ['void', 'trim'=>'bool'],
|
||||
'GEOSWKTWriter::write' => ['string', 'geom'=>'GEOSGeometry'],
|
||||
'GMP::__construct' => ['void'],
|
||||
'GMP::__toString' => ['numeric-string'],
|
||||
'GearmanClient::__construct' => ['void'],
|
||||
'GearmanClient::addOptions' => ['bool', 'options'=>'int'],
|
||||
'GearmanClient::addServer' => ['bool', 'host='=>'string', 'port='=>'int'],
|
||||
@@ -1738,7 +1735,6 @@ return [
|
||||
'Gender\Gender::get' => ['int', 'name'=>'string', 'country='=>'int'],
|
||||
'Gender\Gender::isNick' => ['array', 'name0'=>'string', 'name1'=>'string', 'country='=>'int'],
|
||||
'Gender\Gender::similarNames' => ['array', 'name'=>'string', 'country='=>'int'],
|
||||
'Generator::__wakeup' => ['void'],
|
||||
'Generator::current' => ['mixed'],
|
||||
'Generator::getReturn' => ['mixed'],
|
||||
'Generator::key' => ['mixed'],
|
||||
@@ -3265,7 +3261,7 @@ return [
|
||||
'Iterator::rewind' => ['void'],
|
||||
'Iterator::valid' => ['bool'],
|
||||
'IteratorAggregate::getIterator' => ['Traversable'],
|
||||
'IteratorIterator::__construct' => ['void', 'it'=>'Traversable'],
|
||||
'IteratorIterator::__construct' => ['void', 'iterator'=>'Traversable', 'class='=>'?string'],
|
||||
'IteratorIterator::current' => ['mixed'],
|
||||
'IteratorIterator::getInnerIterator' => ['Iterator'],
|
||||
'IteratorIterator::key' => ['mixed'],
|
||||
@@ -3387,14 +3383,14 @@ return [
|
||||
'LevelDBWriteBatch::delete' => ['', 'key'=>'', 'write_options='=>'array'],
|
||||
'LevelDBWriteBatch::put' => ['', 'key'=>'', 'value'=>'', 'write_options='=>'array'],
|
||||
'LevelDBWriteBatch::set' => ['', 'key'=>'', 'value'=>'', 'write_options='=>'array'],
|
||||
'LimitIterator::__construct' => ['void', 'iterator'=>'Iterator', 'offset='=>'int', 'count='=>'int'],
|
||||
'LimitIterator::__construct' => ['void', 'iterator'=>'Iterator', 'offset='=>'int', 'limit='=>'int'],
|
||||
'LimitIterator::current' => ['mixed'],
|
||||
'LimitIterator::getInnerIterator' => ['Iterator'],
|
||||
'LimitIterator::getPosition' => ['int'],
|
||||
'LimitIterator::key' => ['mixed'],
|
||||
'LimitIterator::next' => ['void'],
|
||||
'LimitIterator::rewind' => ['void'],
|
||||
'LimitIterator::seek' => ['int', 'position'=>'int'],
|
||||
'LimitIterator::seek' => ['int', 'offset'=>'int'],
|
||||
'LimitIterator::valid' => ['bool'],
|
||||
'Locale::acceptFromHttp' => ['string|false', 'header'=>'string'],
|
||||
'Locale::canonicalize' => ['string', 'locale'=>'string'],
|
||||
@@ -3539,14 +3535,14 @@ return [
|
||||
'Memcached::touchByKey' => ['bool', 'server_key'=>'string', 'key'=>'string', 'expiration='=>'int'],
|
||||
'MessageFormatter::__construct' => ['void', 'locale'=>'string', 'pattern'=>'string'],
|
||||
'MessageFormatter::create' => ['MessageFormatter', 'locale'=>'string', 'pattern'=>'string'],
|
||||
'MessageFormatter::format' => ['false|string', 'args'=>'array'],
|
||||
'MessageFormatter::formatMessage' => ['false|string', 'locale'=>'string', 'pattern'=>'string', 'args'=>'array'],
|
||||
'MessageFormatter::format' => ['false|string', 'values'=>'array'],
|
||||
'MessageFormatter::formatMessage' => ['false|string', 'locale'=>'string', 'pattern'=>'string', 'values'=>'array'],
|
||||
'MessageFormatter::getErrorCode' => ['int'],
|
||||
'MessageFormatter::getErrorMessage' => ['string'],
|
||||
'MessageFormatter::getLocale' => ['string'],
|
||||
'MessageFormatter::getPattern' => ['string'],
|
||||
'MessageFormatter::parse' => ['array|false', 'value'=>'string'],
|
||||
'MessageFormatter::parseMessage' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'source'=>'string'],
|
||||
'MessageFormatter::parse' => ['array|false', 'string'=>'string'],
|
||||
'MessageFormatter::parseMessage' => ['array|false', 'locale'=>'string', 'pattern'=>'string', 'message'=>'string'],
|
||||
'MessageFormatter::setPattern' => ['bool', 'pattern'=>'string'],
|
||||
'Mongo::__construct' => ['void', 'server='=>'string', 'options='=>'array', 'driver_options='=>'array'],
|
||||
'Mongo::__get' => ['MongoDB', 'dbname'=>'string'],
|
||||
@@ -3735,7 +3731,7 @@ return [
|
||||
'MongoDBRef::create' => ['array', 'collection'=>'string', 'id'=>'mixed', 'database='=>'string'],
|
||||
'MongoDBRef::get' => ['?array', 'db'=>'MongoDB', 'ref'=>'array'],
|
||||
'MongoDBRef::isRef' => ['bool', 'ref'=>'mixed'],
|
||||
'MongoDB\BSON\Binary::__construct' => ['void', 'data' => 'string', 'type' => 'int'],
|
||||
'MongoDB\BSON\Binary::__construct' => ['void', 'data' => 'string', 'type=' => 'int'],
|
||||
'MongoDB\BSON\Binary::getData' => ['string'],
|
||||
'MongoDB\BSON\Binary::getType' => ['int'],
|
||||
'MongoDB\BSON\Binary::__toString' => ['string'],
|
||||
@@ -4191,7 +4187,7 @@ return [
|
||||
'MongoWriteConcernException::getTrace' => ['list<array{file?:string,line?:int,function:string,class?:class-string,type?:\'::\'|\'->\',args?:array<mixed>}>'],
|
||||
'MongoWriteConcernException::getTraceAsString' => ['string'],
|
||||
'MultipleIterator::__construct' => ['void', 'flags='=>'int'],
|
||||
'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'infos='=>'string'],
|
||||
'MultipleIterator::attachIterator' => ['void', 'iterator'=>'Iterator', 'info='=>'string|int|null'],
|
||||
'MultipleIterator::containsIterator' => ['bool', 'iterator'=>'Iterator'],
|
||||
'MultipleIterator::countIterators' => ['int'],
|
||||
'MultipleIterator::current' => ['array|false'],
|
||||
@@ -4273,20 +4269,20 @@ return [
|
||||
'NumberFormatter::__construct' => ['void', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'],
|
||||
'NumberFormatter::create' => ['NumberFormatter|null', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'],
|
||||
'NumberFormatter::format' => ['string|false', 'num'=>'', 'type='=>'int'],
|
||||
'NumberFormatter::formatCurrency' => ['string|false', 'num'=>'float', 'currency'=>'string'],
|
||||
'NumberFormatter::getAttribute' => ['int|false', 'attr'=>'int'],
|
||||
'NumberFormatter::formatCurrency' => ['string|false', 'amount'=>'float', 'currency'=>'string'],
|
||||
'NumberFormatter::getAttribute' => ['int|float|false', 'attribute'=>'int'],
|
||||
'NumberFormatter::getErrorCode' => ['int'],
|
||||
'NumberFormatter::getErrorMessage' => ['string'],
|
||||
'NumberFormatter::getLocale' => ['string', 'type='=>'int'],
|
||||
'NumberFormatter::getPattern' => ['string|false'],
|
||||
'NumberFormatter::getSymbol' => ['string|false', 'attr'=>'int'],
|
||||
'NumberFormatter::getTextAttribute' => ['string|false', 'attr'=>'int'],
|
||||
'NumberFormatter::parse' => ['float|false', 'string'=>'string', 'type='=>'int', '&rw_position='=>'int'],
|
||||
'NumberFormatter::parseCurrency' => ['float|false', 'string'=>'string', '&w_currency'=>'string', '&rw_position='=>'int'],
|
||||
'NumberFormatter::setAttribute' => ['bool', 'attr'=>'int', 'value'=>''],
|
||||
'NumberFormatter::getSymbol' => ['string|false', 'symbol'=>'int'],
|
||||
'NumberFormatter::getTextAttribute' => ['string|false', 'attribute'=>'int'],
|
||||
'NumberFormatter::parse' => ['int|float|false', 'string'=>'string', 'type='=>'int', '&rw_offset='=>'int'],
|
||||
'NumberFormatter::parseCurrency' => ['float|false', 'string'=>'string', '&w_currency'=>'string', '&rw_offset='=>'int'],
|
||||
'NumberFormatter::setAttribute' => ['bool', 'attribute'=>'int', 'value'=>'int|float'],
|
||||
'NumberFormatter::setPattern' => ['bool', 'pattern'=>'string'],
|
||||
'NumberFormatter::setSymbol' => ['bool', 'attr'=>'int', 'symbol'=>'string'],
|
||||
'NumberFormatter::setTextAttribute' => ['bool', 'attr'=>'int', 'value'=>'string'],
|
||||
'NumberFormatter::setSymbol' => ['bool', 'symbol'=>'int', 'value'=>'string'],
|
||||
'NumberFormatter::setTextAttribute' => ['bool', 'attribute'=>'int', 'value'=>'string'],
|
||||
'OAuth::__construct' => ['void', 'consumer_key'=>'string', 'consumer_secret'=>'string', 'signature_method='=>'string', 'auth_type='=>'int'],
|
||||
'OAuth::disableDebug' => ['bool'],
|
||||
'OAuth::disableRedirects' => ['bool'],
|
||||
@@ -4710,8 +4706,6 @@ return [
|
||||
'PDFlib::utf32_to_utf16' => ['string', 'utf32string'=>'string', 'ordering'=>'string'],
|
||||
'PDFlib::utf8_to_utf16' => ['string', 'utf8string'=>'string', 'ordering'=>'string'],
|
||||
'PDO::__construct' => ['void', 'dsn'=>'string', 'username='=>'?string', 'password='=>'?string', 'options='=>'?array'],
|
||||
'PDO::__sleep' => ['list<string>'],
|
||||
'PDO::__wakeup' => ['void'],
|
||||
'PDO::beginTransaction' => ['bool'],
|
||||
'PDO::commit' => ['bool'],
|
||||
'PDO::cubrid_schema' => ['array', 'schema_type'=>'int', 'table_name='=>'string', 'col_name='=>'string'],
|
||||
@@ -4749,8 +4743,6 @@ return [
|
||||
'PDOException::getPrevious' => ['?Throwable'],
|
||||
'PDOException::getTrace' => ['list<array{file?:string,line?:int,function:string,class?:class-string,type?:\'::\'|\'->\',args?:array<mixed>}>'],
|
||||
'PDOException::getTraceAsString' => ['string'],
|
||||
'PDOStatement::__sleep' => ['list<string>'],
|
||||
'PDOStatement::__wakeup' => ['void'],
|
||||
'PDOStatement::bindColumn' => ['bool', 'column'=>'string|int', '&rw_var'=>'mixed', 'type='=>'int', 'maxLength='=>'int', 'driverOptions='=>'mixed'],
|
||||
'PDOStatement::bindParam' => ['bool', 'param'=>'string|int', '&rw_var'=>'mixed', 'type='=>'int', 'maxLength='=>'int', 'driverOptions='=>'mixed'],
|
||||
'PDOStatement::bindValue' => ['bool', 'param'=>'string|int', 'value'=>'mixed', 'type='=>'int'],
|
||||
@@ -5758,7 +5750,7 @@ return [
|
||||
'Reflection::export' => ['?string', 'r'=>'reflector', 'return='=>'bool'],
|
||||
'Reflection::getModifierNames' => ['list<string>', 'modifiers'=>'int'],
|
||||
'ReflectionClass::__clone' => ['void'],
|
||||
'ReflectionClass::__construct' => ['void', 'argument'=>'object|class-string'],
|
||||
'ReflectionClass::__construct' => ['void', 'objectOrClass'=>'object|class-string'],
|
||||
'ReflectionClass::__toString' => ['string'],
|
||||
'ReflectionClass::export' => ['?string', 'argument'=>'string|object', 'return='=>'bool'],
|
||||
'ReflectionClass::getConstant' => ['mixed', 'name'=>'string'],
|
||||
@@ -5792,7 +5784,7 @@ return [
|
||||
'ReflectionClass::hasConstant' => ['bool', 'name'=>'string'],
|
||||
'ReflectionClass::hasMethod' => ['bool', 'name'=>'string'],
|
||||
'ReflectionClass::hasProperty' => ['bool', 'name'=>'string'],
|
||||
'ReflectionClass::implementsInterface' => ['bool', 'interface_name'=>'interface-string|ReflectionClass'],
|
||||
'ReflectionClass::implementsInterface' => ['bool', 'interface'=>'interface-string|ReflectionClass'],
|
||||
'ReflectionClass::inNamespace' => ['bool'],
|
||||
'ReflectionClass::isAbstract' => ['bool'],
|
||||
'ReflectionClass::isAnonymous' => ['bool'],
|
||||
@@ -5810,7 +5802,7 @@ return [
|
||||
'ReflectionClass::newInstanceArgs' => ['object', 'args='=>'list<mixed>'],
|
||||
'ReflectionClass::newInstanceWithoutConstructor' => ['object'],
|
||||
'ReflectionClass::setStaticPropertyValue' => ['void', 'name'=>'string', 'value'=>'mixed'],
|
||||
'ReflectionClassConstant::__construct' => ['void', 'class'=>'mixed', 'name'=>'string'],
|
||||
'ReflectionClassConstant::__construct' => ['void', 'class'=>'object|class-string', 'constant'=>'string'],
|
||||
'ReflectionClassConstant::__toString' => ['string'],
|
||||
'ReflectionClassConstant::export' => ['string', 'class'=>'mixed', 'name'=>'string', 'return='=>'bool'],
|
||||
'ReflectionClassConstant::getDeclaringClass' => ['ReflectionClass'],
|
||||
@@ -5836,7 +5828,7 @@ return [
|
||||
'ReflectionExtension::info' => ['void'],
|
||||
'ReflectionExtension::isPersistent' => ['bool'],
|
||||
'ReflectionExtension::isTemporary' => ['bool'],
|
||||
'ReflectionFunction::__construct' => ['void', 'name'=>'callable-string|Closure'],
|
||||
'ReflectionFunction::__construct' => ['void', 'function'=>'callable-string|Closure'],
|
||||
'ReflectionFunction::__toString' => ['string'],
|
||||
'ReflectionFunction::export' => ['?string', 'name'=>'string', 'return='=>'bool'],
|
||||
'ReflectionFunction::getClosure' => ['Closure'],
|
||||
@@ -5896,7 +5888,7 @@ return [
|
||||
'ReflectionFunctionAbstract::isUserDefined' => ['bool'],
|
||||
'ReflectionFunctionAbstract::isVariadic' => ['bool'],
|
||||
'ReflectionFunctionAbstract::returnsReference' => ['bool'],
|
||||
'ReflectionGenerator::__construct' => ['void', 'generator'=>'object'],
|
||||
'ReflectionGenerator::__construct' => ['void', 'generator'=>'Generator'],
|
||||
'ReflectionGenerator::getExecutingFile' => ['string'],
|
||||
'ReflectionGenerator::getExecutingGenerator' => ['Generator'],
|
||||
'ReflectionGenerator::getExecutingLine' => ['int'],
|
||||
@@ -5946,14 +5938,14 @@ return [
|
||||
'ReflectionMethod::isUserDefined' => ['bool'],
|
||||
'ReflectionMethod::isVariadic' => ['bool'],
|
||||
'ReflectionMethod::returnsReference' => ['bool'],
|
||||
'ReflectionMethod::setAccessible' => ['void', 'visible'=>'bool'],
|
||||
'ReflectionMethod::setAccessible' => ['void', 'accessible'=>'bool'],
|
||||
'ReflectionNamedType::__clone' => ['void'],
|
||||
'ReflectionNamedType::__toString' => ['string'],
|
||||
'ReflectionNamedType::allowsNull' => ['bool'],
|
||||
'ReflectionNamedType::getName' => ['string'],
|
||||
'ReflectionNamedType::isBuiltin' => ['bool'],
|
||||
'ReflectionObject::__clone' => ['void'],
|
||||
'ReflectionObject::__construct' => ['void', 'argument'=>'object'],
|
||||
'ReflectionObject::__construct' => ['void', 'object'=>'object'],
|
||||
'ReflectionObject::__toString' => ['string'],
|
||||
'ReflectionObject::export' => ['?string', 'argument'=>'object', 'return='=>'bool'],
|
||||
'ReflectionObject::getConstant' => ['mixed', 'name'=>'string'],
|
||||
@@ -5987,7 +5979,7 @@ return [
|
||||
'ReflectionObject::hasConstant' => ['bool', 'name'=>'string'],
|
||||
'ReflectionObject::hasMethod' => ['bool', 'name'=>'string'],
|
||||
'ReflectionObject::hasProperty' => ['bool', 'name'=>'string'],
|
||||
'ReflectionObject::implementsInterface' => ['bool', 'interface_name'=>'ReflectionClass|string'],
|
||||
'ReflectionObject::implementsInterface' => ['bool', 'interface'=>'ReflectionClass|interface-string'],
|
||||
'ReflectionObject::inNamespace' => ['bool'],
|
||||
'ReflectionObject::isAbstract' => ['bool'],
|
||||
'ReflectionObject::isAnonymous' => ['bool'],
|
||||
@@ -6007,7 +5999,7 @@ return [
|
||||
'ReflectionObject::newInstanceWithoutConstructor' => ['object'],
|
||||
'ReflectionObject::setStaticPropertyValue' => ['void', 'name'=>'string', 'value'=>'string'],
|
||||
'ReflectionParameter::__clone' => ['void'],
|
||||
'ReflectionParameter::__construct' => ['void', 'function'=>'', 'parameter'=>''],
|
||||
'ReflectionParameter::__construct' => ['void', 'function'=>'string|array|object', 'param'=>'int|string'],
|
||||
'ReflectionParameter::__toString' => ['string'],
|
||||
'ReflectionParameter::allowsNull' => ['bool'],
|
||||
'ReflectionParameter::canBePassedByValue' => ['bool'],
|
||||
@@ -6029,7 +6021,7 @@ return [
|
||||
'ReflectionParameter::isPassedByReference' => ['bool'],
|
||||
'ReflectionParameter::isVariadic' => ['bool'],
|
||||
'ReflectionProperty::__clone' => ['void'],
|
||||
'ReflectionProperty::__construct' => ['void', 'class'=>'', 'name'=>'string'],
|
||||
'ReflectionProperty::__construct' => ['void', 'class'=>'object|class-string', 'property'=>'string'],
|
||||
'ReflectionProperty::__toString' => ['string'],
|
||||
'ReflectionProperty::export' => ['?string', 'class'=>'mixed', 'name'=>'string', 'return='=>'bool'],
|
||||
'ReflectionProperty::getDeclaringClass' => ['ReflectionClass'],
|
||||
@@ -6043,7 +6035,7 @@ return [
|
||||
'ReflectionProperty::isProtected' => ['bool'],
|
||||
'ReflectionProperty::isPublic' => ['bool'],
|
||||
'ReflectionProperty::isStatic' => ['bool'],
|
||||
'ReflectionProperty::setAccessible' => ['void', 'visible'=>'bool'],
|
||||
'ReflectionProperty::setAccessible' => ['void', 'accessible'=>'bool'],
|
||||
'ReflectionProperty::setValue' => ['void', 'object'=>'null|object', 'value'=>''],
|
||||
'ReflectionProperty::setValue\'1' => ['void', 'value'=>''],
|
||||
'ReflectionType::__clone' => ['void'],
|
||||
@@ -6076,13 +6068,13 @@ return [
|
||||
'RegexIterator::setMode' => ['void', 'mode'=>'int'],
|
||||
'RegexIterator::setPregFlags' => ['void', 'pregFlags'=>'int'],
|
||||
'RegexIterator::valid' => ['bool'],
|
||||
'ResourceBundle::__construct' => ['void', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'],
|
||||
'ResourceBundle::__construct' => ['void', 'locale'=>'?string', 'bundle'=>'?string', 'fallback='=>'bool'],
|
||||
'ResourceBundle::count' => ['int'],
|
||||
'ResourceBundle::create' => ['?ResourceBundle', 'locale'=>'string', 'bundlename'=>'string', 'fallback='=>'bool'],
|
||||
'ResourceBundle::create' => ['?ResourceBundle', 'locale'=>'?string', 'bundle'=>'?string', 'fallback='=>'bool'],
|
||||
'ResourceBundle::get' => ['mixed', 'index'=>'string|int', 'fallback='=>'bool'],
|
||||
'ResourceBundle::getErrorCode' => ['int'],
|
||||
'ResourceBundle::getErrorMessage' => ['string'],
|
||||
'ResourceBundle::getLocales' => ['array', 'bundlename'=>'string'],
|
||||
'ResourceBundle::getLocales' => ['array|false', 'bundle'=>'string'],
|
||||
'Runkit_Sandbox::__construct' => ['void', 'options='=>'array'],
|
||||
'Runkit_Sandbox_Parent' => [''],
|
||||
'Runkit_Sandbox_Parent::__construct' => ['void'],
|
||||
@@ -6193,8 +6185,8 @@ return [
|
||||
'SNMP::getnext' => ['string|array|false', 'objectId'=>'string|array'],
|
||||
'SNMP::set' => ['bool', 'objectId'=>'string|array', 'type'=>'string|array', 'value'=>'string|array'],
|
||||
'SNMP::setSecurity' => ['bool', 'securityLevel'=>'string', 'authProtocol='=>'string', 'authPassphrase='=>'string', 'privacyProtocol='=>'string', 'privacyPassphrase='=>'string', 'contextName='=>'string', 'contextEngineId='=>'string'],
|
||||
'SNMP::walk' => ['array|false', 'objectId'=>'string', 'suffixAsKey='=>'bool', 'maxRepetitions='=>'int', 'nonRepeaters='=>'int'],
|
||||
'SQLite3::__construct' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryptionKey='=>'?string'],
|
||||
'SNMP::walk' => ['array|false', 'objectId'=>'array|string', 'suffixAsKey='=>'bool', 'maxRepetitions='=>'int', 'nonRepeaters='=>'int'],
|
||||
'SQLite3::__construct' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryptionKey='=>'string'],
|
||||
'SQLite3::busyTimeout' => ['bool', 'milliseconds'=>'int'],
|
||||
'SQLite3::changes' => ['int'],
|
||||
'SQLite3::close' => ['bool'],
|
||||
@@ -6208,7 +6200,7 @@ return [
|
||||
'SQLite3::lastErrorMsg' => ['string'],
|
||||
'SQLite3::lastInsertRowID' => ['int'],
|
||||
'SQLite3::loadExtension' => ['bool', 'name'=>'string'],
|
||||
'SQLite3::open' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryptionKey='=>'?string'],
|
||||
'SQLite3::open' => ['void', 'filename'=>'string', 'flags='=>'int', 'encryptionKey='=>'string'],
|
||||
'SQLite3::openBlob' => ['resource|false', 'table'=>'string', 'column'=>'string', 'rowid'=>'int', 'dbname='=>'string'],
|
||||
'SQLite3::prepare' => ['SQLite3Stmt|false', 'query'=>'string'],
|
||||
'SQLite3::query' => ['SQLite3Result|false', 'query'=>'string'],
|
||||
@@ -6619,9 +6611,9 @@ return [
|
||||
'SessionHandler::close' => ['bool'],
|
||||
'SessionHandler::create_sid' => ['string'],
|
||||
'SessionHandler::destroy' => ['bool', 'id'=>'string'],
|
||||
'SessionHandler::gc' => ['bool', 'maxlifetime'=>'int'],
|
||||
'SessionHandler::open' => ['bool', 'save_path'=>'string', 'session_name'=>'string'],
|
||||
'SessionHandler::read' => ['string', 'id'=>'string'],
|
||||
'SessionHandler::gc' => ['bool', 'max_lifetime'=>'int'],
|
||||
'SessionHandler::open' => ['bool', 'path'=>'string', 'name'=>'string'],
|
||||
'SessionHandler::read' => ['string|false', 'id'=>'string'],
|
||||
'SessionHandler::write' => ['bool', 'id'=>'string', 'data'=>'string'],
|
||||
'SessionHandlerInterface::close' => ['bool'],
|
||||
'SessionHandlerInterface::destroy' => ['bool', 'id'=>'string'],
|
||||
@@ -6634,26 +6626,26 @@ return [
|
||||
'SessionUpdateTimestampHandler::validateId' => ['char', 'id'=>'string'],
|
||||
'SessionUpdateTimestampHandlerInterface::updateTimestamp' => ['bool', 'key'=>'string', 'value'=>'string'],
|
||||
'SessionUpdateTimestampHandlerInterface::validateId' => ['bool', 'key'=>'string'],
|
||||
'SimpleXMLElement::__construct' => ['void', 'data'=>'string', 'options='=>'int', 'data_is_url='=>'bool', 'ns='=>'string', 'is_prefix='=>'bool'],
|
||||
'SimpleXMLElement::__construct' => ['void', 'data'=>'string', 'options='=>'int', 'dataIsURL='=>'bool', 'namespaceOrPrefix='=>'string', 'isPrefix='=>'bool'],
|
||||
'SimpleXMLElement::__get' => ['SimpleXMLElement', 'name'=>'string'],
|
||||
'SimpleXMLElement::__toString' => ['string'],
|
||||
'SimpleXMLElement::addAttribute' => ['void', 'name'=>'string', 'value='=>'string', 'ns='=>'string'],
|
||||
'SimpleXMLElement::addChild' => ['SimpleXMLElement', 'name'=>'string', 'value='=>'string', 'ns='=>'string'],
|
||||
'SimpleXMLElement::addAttribute' => ['void', 'qualifiedName'=>'string', 'value'=>'string', 'namespace='=>'?string'],
|
||||
'SimpleXMLElement::addChild' => ['?SimpleXMLElement', 'qualifiedName'=>'string', 'value='=>'?string', 'namespace='=>'?string'],
|
||||
'SimpleXMLElement::asXML' => ['string|bool', 'filename'=>'string'],
|
||||
'SimpleXMLElement::asXML\'1' => ['string|false'],
|
||||
'SimpleXMLElement::attributes' => ['?SimpleXMLElement', 'ns='=>'string', 'is_prefix='=>'bool'],
|
||||
'SimpleXMLElement::children' => ['SimpleXMLElement', 'ns='=>'string', 'is_prefix='=>'bool'],
|
||||
'SimpleXMLElement::attributes' => ['?SimpleXMLElement', 'namespaceOrPrefix='=>'?string', 'isPrefix='=>'bool'],
|
||||
'SimpleXMLElement::children' => ['?SimpleXMLElement', 'namespaceOrPrefix='=>'?string', 'isPrefix='=>'bool'],
|
||||
'SimpleXMLElement::count' => ['int'],
|
||||
'SimpleXMLElement::getDocNamespaces' => ['string[]', 'recursive='=>'bool', 'from_root='=>'bool'],
|
||||
'SimpleXMLElement::getDocNamespaces' => ['array<string,string>', 'recursive='=>'bool', 'fromRoot='=>'bool'],
|
||||
'SimpleXMLElement::getName' => ['string'],
|
||||
'SimpleXMLElement::getNamespaces' => ['string[]', 'recursive='=>'bool'],
|
||||
'SimpleXMLElement::getNamespaces' => ['array<string,string>', 'recursive='=>'bool'],
|
||||
'SimpleXMLElement::offsetExists' => ['bool', 'offset'=>'int|string'],
|
||||
'SimpleXMLElement::offsetGet' => ['SimpleXMLElement', 'offset'=>'int|string'],
|
||||
'SimpleXMLElement::offsetSet' => ['void', 'offset'=>'int|string', 'value'=>'mixed'],
|
||||
'SimpleXMLElement::offsetUnset' => ['void', 'offset'=>'int|string'],
|
||||
'SimpleXMLElement::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'ns'=>'string'],
|
||||
'SimpleXMLElement::registerXPathNamespace' => ['bool', 'prefix'=>'string', 'namespace'=>'string'],
|
||||
'SimpleXMLElement::saveXML' => ['string|bool', 'filename='=>'string'],
|
||||
'SimpleXMLElement::xpath' => ['SimpleXMLElement[]|false', 'path'=>'string'],
|
||||
'SimpleXMLElement::xpath' => ['SimpleXMLElement[]|false|null', 'expression'=>'string'],
|
||||
'SimpleXMLIterator::current' => ['?SimpleXMLIterator'],
|
||||
'SimpleXMLIterator::getChildren' => ['?SimpleXMLIterator'],
|
||||
'SimpleXMLIterator::hasChildren' => ['bool'],
|
||||
@@ -7496,10 +7488,10 @@ return [
|
||||
'SplDoublyLinkedList::isEmpty' => ['bool'],
|
||||
'SplDoublyLinkedList::key' => ['int'],
|
||||
'SplDoublyLinkedList::next' => ['void'],
|
||||
'SplDoublyLinkedList::offsetExists' => ['bool', 'index'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetGet' => ['mixed', 'index'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetSet' => ['void', 'index'=>'mixed', 'value'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetUnset' => ['void', 'index'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetExists' => ['bool', 'index'=>'int'],
|
||||
'SplDoublyLinkedList::offsetGet' => ['mixed', 'index'=>'int'],
|
||||
'SplDoublyLinkedList::offsetSet' => ['void', 'index'=>'?int', 'value'=>'mixed'],
|
||||
'SplDoublyLinkedList::offsetUnset' => ['void', 'index'=>'int'],
|
||||
'SplDoublyLinkedList::pop' => ['mixed'],
|
||||
'SplDoublyLinkedList::prev' => ['void'],
|
||||
'SplDoublyLinkedList::push' => ['void', 'value'=>'mixed'],
|
||||
@@ -7515,7 +7507,6 @@ return [
|
||||
'SplEnum::getConstList' => ['array', 'include_default='=>'bool'],
|
||||
'SplFileInfo::__construct' => ['void', 'filename'=>'string'],
|
||||
'SplFileInfo::__toString' => ['string'],
|
||||
'SplFileInfo::__wakeup' => ['void'],
|
||||
'SplFileInfo::getATime' => ['int|false'],
|
||||
'SplFileInfo::getBasename' => ['string', 'suffix='=>'string'],
|
||||
'SplFileInfo::getCTime' => ['int|false'],
|
||||
@@ -7989,7 +7980,7 @@ return [
|
||||
'Transliterator::getErrorCode' => ['int'],
|
||||
'Transliterator::getErrorMessage' => ['string'],
|
||||
'Transliterator::listIDs' => ['array'],
|
||||
'Transliterator::transliterate' => ['string|false', 'subject'=>'string', 'start='=>'int', 'end='=>'int'],
|
||||
'Transliterator::transliterate' => ['string|false', 'string'=>'string', 'start='=>'int', 'end='=>'int'],
|
||||
'TypeError::__clone' => ['void'],
|
||||
'TypeError::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'],
|
||||
'TypeError::__toString' => ['string'],
|
||||
@@ -8001,8 +7992,8 @@ return [
|
||||
'TypeError::getTrace' => ['list<array{file?:string,line?:int,function:string,class?:class-string,type?:\'::\'|\'->\',args?:array<mixed>}>'],
|
||||
'TypeError::getTraceAsString' => ['string'],
|
||||
'UConverter::__construct' => ['void', 'destination_encoding='=>'?string', 'source_encoding='=>'?string'],
|
||||
'UConverter::convert' => ['string', 'string'=>'string', 'reverse='=>'bool'],
|
||||
'UConverter::fromUCallback' => ['mixed', 'reason'=>'int', 'source'=>'string', 'codePoint'=>'string', '&w_error'=>'int'],
|
||||
'UConverter::convert' => ['string', 'str'=>'string', 'reverse='=>'bool'],
|
||||
'UConverter::fromUCallback' => ['string|int|array|null', 'reason'=>'int', 'source'=>'array', 'codePoint'=>'int', '&w_error'=>'int'],
|
||||
'UConverter::getAliases' => ['array|false|null', 'name'=>'string'],
|
||||
'UConverter::getAvailable' => ['array'],
|
||||
'UConverter::getDestinationEncoding' => ['string|false|null'],
|
||||
@@ -8013,12 +8004,12 @@ return [
|
||||
'UConverter::getSourceType' => ['int|false|null'],
|
||||
'UConverter::getStandards' => ['?array'],
|
||||
'UConverter::getSubstChars' => ['string|false|null'],
|
||||
'UConverter::reasonText' => ['string', 'reason='=>'int'],
|
||||
'UConverter::reasonText' => ['string', 'reason'=>'int'],
|
||||
'UConverter::setDestinationEncoding' => ['bool', 'encoding'=>'string'],
|
||||
'UConverter::setSourceEncoding' => ['bool', 'encoding'=>'string'],
|
||||
'UConverter::setSubstChars' => ['bool', 'chars'=>'string'],
|
||||
'UConverter::toUCallback' => ['string|int|array|null', 'reason'=>'int', 'source'=>'string', 'codeUnits'=>'string', '&w_error'=>'int'],
|
||||
'UConverter::transcode' => ['string', 'string'=>'string', 'toEncoding'=>'string', 'fromEncoding'=>'string', 'options='=>'?array'],
|
||||
'UConverter::transcode' => ['string', 'str'=>'string', 'toEncoding'=>'string', 'fromEncoding'=>'string', 'options='=>'?array'],
|
||||
'UnderflowException::__clone' => ['void'],
|
||||
'UnderflowException::__construct' => ['void', 'message='=>'string', 'code='=>'int', 'previous='=>'?Throwable'],
|
||||
'UnderflowException::__toString' => ['string'],
|
||||
@@ -8183,17 +8174,6 @@ return [
|
||||
'Vtiful\Kernel\Validation::validationType' => ['?Vtiful\Kernel\Validation', 'type'=>'int'],
|
||||
'Vtiful\Kernel\Validation::valueList' => ['?Vtiful\Kernel\Validation', 'value_list'=>'array'],
|
||||
'Vtiful\Kernel\Validation::valueNumber' => ['?Vtiful\Kernel\Validation', 'value_number'=>'int'],
|
||||
'WeakMap::__construct' => ['void'],
|
||||
'WeakMap::count' => ['int'],
|
||||
'WeakMap::current' => ['mixed'],
|
||||
'WeakMap::key' => ['object'],
|
||||
'WeakMap::next' => ['void'],
|
||||
'WeakMap::offsetExists' => ['bool', 'object'=>'object'],
|
||||
'WeakMap::offsetGet' => ['mixed', 'object'=>'object'],
|
||||
'WeakMap::offsetSet' => ['void', 'object'=>'object', 'value'=>'mixed'],
|
||||
'WeakMap::offsetUnset' => ['void', 'object'=>'object'],
|
||||
'WeakMap::rewind' => ['void'],
|
||||
'WeakMap::valid' => ['bool'],
|
||||
'Weakref::acquire' => ['bool'],
|
||||
'Weakref::get' => ['object'],
|
||||
'Weakref::release' => ['bool'],
|
||||
@@ -8252,23 +8232,23 @@ return [
|
||||
'XMLDiff\File::merge' => ['string', 'src'=>'string', 'diff'=>'string'],
|
||||
'XMLDiff\Memory::diff' => ['string', 'from'=>'string', 'to'=>'string'],
|
||||
'XMLDiff\Memory::merge' => ['string', 'src'=>'string', 'diff'=>'string'],
|
||||
'XMLReader::XML' => ['bool', 'source'=>'string', 'encoding='=>'?string', 'options='=>'int'],
|
||||
'XMLReader::XML' => ['bool|XMLReader', 'source'=>'string', 'encoding='=>'?string', 'flags='=>'int'],
|
||||
'XMLReader::close' => ['bool'],
|
||||
'XMLReader::expand' => ['DOMNode|false', 'baseNode='=>'?DOMNode'],
|
||||
'XMLReader::getAttribute' => ['?string', 'name'=>'string'],
|
||||
'XMLReader::getAttributeNo' => ['?string', 'index'=>'int'],
|
||||
'XMLReader::getAttributeNs' => ['?string', 'name'=>'string', 'namespaceuri'=>'string'],
|
||||
'XMLReader::getAttributeNs' => ['?string', 'name'=>'string', 'namespace'=>'string'],
|
||||
'XMLReader::getParserProperty' => ['bool', 'property'=>'int'],
|
||||
'XMLReader::isValid' => ['bool'],
|
||||
'XMLReader::lookupNamespace' => ['?string', 'prefix'=>'string'],
|
||||
'XMLReader::moveToAttribute' => ['bool', 'name'=>'string'],
|
||||
'XMLReader::moveToAttributeNo' => ['bool', 'index'=>'int'],
|
||||
'XMLReader::moveToAttributeNs' => ['bool', 'localname'=>'string', 'namespaceuri'=>'string'],
|
||||
'XMLReader::moveToAttributeNs' => ['bool', 'name'=>'string', 'namespace'=>'string'],
|
||||
'XMLReader::moveToElement' => ['bool'],
|
||||
'XMLReader::moveToFirstAttribute' => ['bool'],
|
||||
'XMLReader::moveToNextAttribute' => ['bool'],
|
||||
'XMLReader::next' => ['bool', 'localname='=>'string'],
|
||||
'XMLReader::open' => ['bool', 'uri'=>'string', 'encoding='=>'?string', 'options='=>'int'],
|
||||
'XMLReader::next' => ['bool', 'name='=>'string'],
|
||||
'XMLReader::open' => ['bool|XmlReader', 'uri'=>'string', 'encoding='=>'?string', 'flags='=>'int'],
|
||||
'XMLReader::read' => ['bool'],
|
||||
'XMLReader::readInnerXML' => ['string'],
|
||||
'XMLReader::readOuterXML' => ['string'],
|
||||
@@ -8322,12 +8302,12 @@ return [
|
||||
'XSLTProcessor::getParameter' => ['string|false', 'namespace'=>'string', 'name'=>'string'],
|
||||
'XSLTProcessor::hasExsltSupport' => ['bool'],
|
||||
'XSLTProcessor::importStylesheet' => ['bool', 'stylesheet'=>'object'],
|
||||
'XSLTProcessor::registerPHPFunctions' => ['void', 'functions='=>'mixed'],
|
||||
'XSLTProcessor::registerPHPFunctions' => ['void', 'functions='=>'array|string|null'],
|
||||
'XSLTProcessor::removeParameter' => ['bool', 'namespace'=>'string', 'name'=>'string'],
|
||||
'XSLTProcessor::setParameter' => ['bool', 'namespace'=>'string', 'name'=>'string', 'value'=>'string'],
|
||||
'XSLTProcessor::setParameter\'1' => ['bool', 'namespace'=>'string', 'options'=>'array'],
|
||||
'XSLTProcessor::setProfiling' => ['bool', 'filename'=>'?string'],
|
||||
'XSLTProcessor::transformToDoc' => ['DOMDocument|false', 'document'=>'DOMNode'],
|
||||
'XSLTProcessor::transformToDoc' => ['DOMDocument|false', 'document'=>'DOMNode', 'returnClass='=>'?string'],
|
||||
'XSLTProcessor::transformToURI' => ['int', 'document'=>'DOMDocument', 'uri'=>'string'],
|
||||
'XSLTProcessor::transformToXML' => ['string|false', 'document'=>'DOMDocument'],
|
||||
'Xcom::__construct' => ['void', 'fabric_url='=>'string', 'fabric_token='=>'string', 'capability_token='=>'string'],
|
||||
@@ -9216,8 +9196,8 @@ return [
|
||||
'ZipArchive::getNameIndex' => ['string|false', 'index'=>'int', 'flags='=>'int'],
|
||||
'ZipArchive::getStatusString' => ['string|false'],
|
||||
'ZipArchive::getStream' => ['resource|false', 'name'=>'string'],
|
||||
'ZipArchive::isCompressionMethodSupported' => ['bool', 'method'=>'int', 'encode='=>'bool'],
|
||||
'ZipArchive::isEncryptionMethodSupported' => ['bool', 'method'=>'int', 'encode='=>'bool'],
|
||||
'ZipArchive::isCompressionMethodSupported' => ['bool', 'method'=>'int', 'enc='=>'bool'],
|
||||
'ZipArchive::isEncryptionMethodSupported' => ['bool', 'method'=>'int', 'enc='=>'bool'],
|
||||
'ZipArchive::locateName' => ['int|false', 'name'=>'string', 'flags='=>'int'],
|
||||
'ZipArchive::open' => ['int|bool', 'filename'=>'string', 'flags='=>'int'],
|
||||
'ZipArchive::registerCancelCallback' => ['bool', 'callback'=>'callable'],
|
||||
@@ -9228,8 +9208,8 @@ return [
|
||||
'ZipArchive::setArchiveComment' => ['bool', 'comment'=>'string'],
|
||||
'ZipArchive::setCommentIndex' => ['bool', 'index'=>'int', 'comment'=>'string'],
|
||||
'ZipArchive::setCommentName' => ['bool', 'name'=>'string', 'comment'=>'string'],
|
||||
'ZipArchive::setCompressionIndex' => ['bool', 'index'=>'int', 'comp_method'=>'int', 'comp_flags='=>'int'],
|
||||
'ZipArchive::setCompressionName' => ['bool', 'name'=>'string', 'comp_method'=>'int', 'comp_flags='=>'int'],
|
||||
'ZipArchive::setCompressionIndex' => ['bool', 'index'=>'int', 'method'=>'int', 'compflags='=>'int'],
|
||||
'ZipArchive::setCompressionName' => ['bool', 'name'=>'string', 'method'=>'int', 'compflags='=>'int'],
|
||||
'ZipArchive::setExternalAttributesIndex' => ['bool', 'index'=>'int', 'opsys'=>'int', 'attr'=>'int', 'flags='=>'int'],
|
||||
'ZipArchive::setExternalAttributesName' => ['bool', 'name'=>'string', 'opsys'=>'int', 'attr'=>'int', 'flags='=>'int'],
|
||||
'ZipArchive::setMtimeIndex' => ['bool', 'index'=>'int', 'timestamp'=>'int', 'flags='=>'int'],
|
||||
@@ -9401,9 +9381,7 @@ return [
|
||||
'array_uintersect_assoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable', '...rest='=>'array|callable(mixed,mixed):int'],
|
||||
'array_uintersect_uassoc' => ['array', 'array'=>'array', 'rest'=>'array', 'data_compare_func'=>'callable(mixed,mixed):int', 'key_compare_func'=>'callable(mixed,mixed):int'],
|
||||
'array_uintersect_uassoc\'1' => ['array', 'array'=>'array', 'rest'=>'array', 'arr3'=>'array', 'arg4'=>'array|callable(mixed,mixed):int', 'arg5'=>'array|callable(mixed,mixed):int', '...rest='=>'array|callable(mixed,mixed):int'],
|
||||
'array_unique' => ['array', 'array'=>'array', 'flags='=>'0'],
|
||||
'array_unique\'1' => ['array<int|float|string|null>', 'array'=>'array<int|float|string|null>', 'flags='=>'1'],
|
||||
'array_unique\'2' => ['array<int|float|string|bool|\Stringable|null>', 'array'=>'array<int|float|string|bool|\Stringable|null>', 'flags='=>'2|5'],
|
||||
'array_unique' => ['array', 'array'=>'array', 'flags='=>'int'],
|
||||
'array_unshift' => ['int', '&rw_array'=>'array', '...values'=>'mixed'],
|
||||
'array_values' => ['list<mixed>', 'array'=>'array'],
|
||||
'array_walk' => ['bool', '&rw_array'=>'array', 'callback'=>'callable', 'arg='=>'mixed'],
|
||||
@@ -9500,7 +9478,7 @@ return [
|
||||
'call_user_func_array' => ['mixed|false', 'callback'=>'callable', 'args'=>'list<mixed>'],
|
||||
'call_user_method' => ['mixed', 'method_name'=>'string', 'object'=>'object', 'parameter='=>'mixed', '...args='=>'mixed'],
|
||||
'call_user_method_array' => ['mixed', 'method_name'=>'string', 'object'=>'object', 'params'=>'list<mixed>'],
|
||||
'ceil' => ['float', 'num'=>'float'],
|
||||
'ceil' => ['float', 'num'=>'float|int'],
|
||||
'chdb::__construct' => ['void', 'pathname'=>'string'],
|
||||
'chdb::get' => ['string', 'key'=>'string'],
|
||||
'chdb_create' => ['bool', 'pathname'=>'string', 'data'=>'array'],
|
||||
@@ -9763,7 +9741,7 @@ return [
|
||||
'cubrid_unbuffered_query' => ['resource', 'query'=>'string', 'conn_identifier='=>''],
|
||||
'cubrid_version' => ['string'],
|
||||
'curl_close' => ['void', 'ch'=>'resource'],
|
||||
'curl_copy_handle' => ['resource', 'ch'=>'resource'],
|
||||
'curl_copy_handle' => ['resource|false', 'ch'=>'resource'],
|
||||
'curl_errno' => ['int', 'ch'=>'resource'],
|
||||
'curl_error' => ['string', 'ch'=>'resource'],
|
||||
'curl_escape' => ['string|false', 'ch'=>'resource', 'string'=>'string'],
|
||||
@@ -9812,7 +9790,7 @@ return [
|
||||
'date_get_last_errors' => ['array{warning_count:int,warnings:array<int,string>,error_count:int,errors:array<int,string>}|false'],
|
||||
'date_interval_create_from_date_string' => ['DateInterval', 'datetime'=>'string'],
|
||||
'date_interval_format' => ['string', 'object'=>'DateInterval', 'format'=>'string'],
|
||||
'date_isodate_set' => ['DateTime|false', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'dayOfWeek='=>'int|mixed'],
|
||||
'date_isodate_set' => ['DateTime', 'object'=>'DateTime', 'year'=>'int', 'week'=>'int', 'dayOfWeek='=>'int'],
|
||||
'date_modify' => ['DateTime|false', 'object'=>'DateTime', 'modifier'=>'string'],
|
||||
'date_offset_get' => ['int|false', 'object'=>'DateTimeInterface'],
|
||||
'date_parse' => ['array|false', 'datetime'=>'string'],
|
||||
@@ -9841,7 +9819,7 @@ return [
|
||||
'datefmt_get_timezone_id' => ['string|false', 'formatter'=>'IntlDateFormatter'],
|
||||
'datefmt_is_lenient' => ['bool', 'formatter'=>'IntlDateFormatter'],
|
||||
'datefmt_localtime' => ['array|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
|
||||
'datefmt_parse' => ['int|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
|
||||
'datefmt_parse' => ['float|int|false', 'formatter'=>'IntlDateFormatter', 'string'=>'string', '&rw_offset='=>'int'],
|
||||
'datefmt_set_calendar' => ['bool', 'formatter'=>'IntlDateFormatter', 'calendar'=>'IntlCalendar|int|null'],
|
||||
'datefmt_set_lenient' => ['void', 'formatter'=>'IntlDateFormatter', 'lenient'=>'bool'],
|
||||
'datefmt_set_pattern' => ['bool', 'formatter'=>'IntlDateFormatter', 'pattern'=>'string'],
|
||||
@@ -9903,20 +9881,20 @@ return [
|
||||
'db2_tableprivileges' => [''],
|
||||
'db2_tables' => ['resource|false', 'connection'=>'resource', 'qualifier='=>'?string', 'schema='=>'?string', 'table_name='=>'?string', 'table_type='=>'?string'],
|
||||
'dba_close' => ['void', 'dba'=>'resource'],
|
||||
'dba_delete' => ['bool', 'key'=>'string', 'dba'=>'resource'],
|
||||
'dba_exists' => ['bool', 'key'=>'string', 'dba'=>'resource'],
|
||||
'dba_fetch' => ['string|false', 'key'=>'string', 'skip'=>'int', 'dba'=>'resource'],
|
||||
'dba_fetch\'1' => ['string|false', 'key'=>'string', 'skip'=>'resource'],
|
||||
'dba_delete' => ['bool', 'key'=>'array|string', 'dba'=>'resource'],
|
||||
'dba_exists' => ['bool', 'key'=>'array|string', 'dba'=>'resource'],
|
||||
'dba_fetch' => ['string|false', 'key'=>'array|string', 'skip'=>'int', 'dba'=>'resource'],
|
||||
'dba_fetch\'1' => ['string|false', 'key'=>'array|string', 'skip'=>'resource'],
|
||||
'dba_firstkey' => ['string', 'dba'=>'resource'],
|
||||
'dba_handlers' => ['array', 'full_info='=>'bool'],
|
||||
'dba_insert' => ['bool', 'key'=>'string', 'value'=>'string', 'dba'=>'resource'],
|
||||
'dba_insert' => ['bool', 'key'=>'array|string', 'value'=>'string', 'dba'=>'resource'],
|
||||
'dba_key_split' => ['array|false', 'key'=>'string|false|null'],
|
||||
'dba_list' => ['array'],
|
||||
'dba_nextkey' => ['string', 'dba'=>'resource'],
|
||||
'dba_open' => ['resource', 'path'=>'string', 'mode'=>'string', 'handler='=>'string', '...handler_params='=>'string'],
|
||||
'dba_optimize' => ['bool', 'dba'=>'resource'],
|
||||
'dba_popen' => ['resource', 'path'=>'string', 'mode'=>'string', 'handler='=>'string', '...handler_params='=>'string'],
|
||||
'dba_replace' => ['bool', 'key'=>'string', 'value'=>'string', 'dba'=>'resource'],
|
||||
'dba_replace' => ['bool', 'key'=>'array|string', 'value'=>'string', 'dba'=>'resource'],
|
||||
'dba_sync' => ['bool', 'dba'=>'resource'],
|
||||
'dbase_add_record' => ['bool', 'dbase_identifier'=>'resource', 'record'=>'array'],
|
||||
'dbase_close' => ['bool', 'dbase_identifier'=>'resource'],
|
||||
@@ -10048,7 +10026,7 @@ return [
|
||||
'dotnet_load' => ['int', 'assembly_name'=>'string', 'datatype_name='=>'string', 'codepage='=>'int'],
|
||||
'doubleval' => ['float', 'value'=>'mixed'],
|
||||
'each' => ['array{0:int|string,key:int|string,1:mixed,value:mixed}', '&r_arr'=>'array'],
|
||||
'easter_date' => ['int', 'year='=>'int'],
|
||||
'easter_date' => ['int', 'year='=>'int', 'mode='=>'int'],
|
||||
'easter_days' => ['int', 'year='=>'int', 'mode='=>'int'],
|
||||
'echo' => ['void', 'arg1'=>'string', '...args='=>'string'],
|
||||
'eio_busy' => ['resource', 'delay'=>'int', 'pri='=>'int', 'callback='=>'callable', 'data='=>'mixed'],
|
||||
@@ -10514,7 +10492,7 @@ return [
|
||||
'finfo_set_flags' => ['bool', 'finfo'=>'resource', 'flags'=>'int'],
|
||||
'floatval' => ['float', 'value'=>'mixed'],
|
||||
'flock' => ['bool', 'stream'=>'resource', 'operation'=>'int', '&w_would_block='=>'int'],
|
||||
'floor' => ['float', 'num'=>'float'],
|
||||
'floor' => ['float', 'num'=>'float|int'],
|
||||
'flush' => ['void'],
|
||||
'fmod' => ['float', 'num1'=>'float', 'num2'=>'float'],
|
||||
'fnmatch' => ['bool', 'pattern'=>'string', 'filename'=>'string', 'flags='=>'int'],
|
||||
@@ -10699,8 +10677,8 @@ return [
|
||||
'get_called_class' => ['class-string'],
|
||||
'get_cfg_var' => ['string|false', 'option'=>'string'],
|
||||
'get_class' => ['class-string', 'object='=>'object'],
|
||||
'get_class_methods' => ['list<string>|null', 'object_or_class'=>'mixed'],
|
||||
'get_class_vars' => ['array<string,mixed>', 'class'=>'string'],
|
||||
'get_class_methods' => ['list<non-falsy-string>|null', 'object_or_class'=>'mixed'],
|
||||
'get_class_vars' => ['array<non-falsy-string,mixed>', 'class'=>'string'],
|
||||
'get_current_user' => ['string'],
|
||||
'get_declared_classes' => ['list<class-string>'],
|
||||
'get_declared_interfaces' => ['list<class-string>'],
|
||||
@@ -10749,7 +10727,7 @@ return [
|
||||
'gettimeofday' => ['array<string, int>'],
|
||||
'gettimeofday\'1' => ['float', 'as_float='=>'true'],
|
||||
'gettype' => ['string', 'value'=>'mixed'],
|
||||
'glob' => ['list<string>|false', 'pattern'=>'string', 'flags='=>'int'],
|
||||
'glob' => ['list<non-empty-string>|false', 'pattern'=>'non-empty-string', 'flags='=>'int<1, max>'],
|
||||
'gmdate' => ['string', 'format'=>'string', 'timestamp='=>'int'],
|
||||
'gmmktime' => ['int|false', 'hour='=>'int', 'minute='=>'int', 'second='=>'int', 'month='=>'int', 'day='=>'int', 'year='=>'int'],
|
||||
'gmp_abs' => ['GMP', 'num'=>'GMP|string|int'],
|
||||
@@ -10899,20 +10877,20 @@ return [
|
||||
'gzdeflate' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'],
|
||||
'gzencode' => ['string|false', 'data'=>'string', 'level='=>'int', 'encoding='=>'int'],
|
||||
'gzeof' => ['bool', 'stream'=>'resource'],
|
||||
'gzfile' => ['list<string>', 'filename'=>'string', 'use_include_path='=>'int'],
|
||||
'gzfile' => ['list<string>|false', 'filename'=>'string', 'use_include_path='=>'int'],
|
||||
'gzgetc' => ['string|false', 'stream'=>'resource'],
|
||||
'gzgets' => ['string|false', 'stream'=>'resource', 'length='=>'int'],
|
||||
'gzgetss' => ['string|false', 'zp'=>'resource', 'length'=>'int', 'allowable_tags='=>'string'],
|
||||
'gzinflate' => ['string|false', 'data'=>'string', 'max_length='=>'int'],
|
||||
'gzopen' => ['resource|false', 'filename'=>'string', 'mode'=>'string', 'use_include_path='=>'int'],
|
||||
'gzpassthru' => ['int', 'stream'=>'resource'],
|
||||
'gzputs' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'],
|
||||
'gzputs' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'],
|
||||
'gzread' => ['string|0', 'stream'=>'resource', 'length'=>'int'],
|
||||
'gzrewind' => ['bool', 'stream'=>'resource'],
|
||||
'gzseek' => ['int', 'stream'=>'resource', 'offset'=>'int', 'whence='=>'int'],
|
||||
'gztell' => ['int|false', 'stream'=>'resource'],
|
||||
'gzuncompress' => ['string|false', 'data'=>'string', 'max_length='=>'int'],
|
||||
'gzwrite' => ['int', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'],
|
||||
'gzwrite' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'],
|
||||
'hash' => ['string|false', 'algo'=>'string', 'data'=>'string', 'binary='=>'bool'],
|
||||
'hashTableObj::clear' => ['void'],
|
||||
'hashTableObj::get' => ['string', 'key'=>'string'],
|
||||
@@ -12127,7 +12105,7 @@ return [
|
||||
'ldap_count_entries' => ['int', 'ldap'=>'resource', 'result'=>'resource'],
|
||||
'ldap_delete' => ['bool', 'ldap'=>'resource', 'dn'=>'string'],
|
||||
'ldap_delete_ext' => ['resource|false', 'ldap'=>'resource', 'dn'=>'string', 'controls='=>'array'],
|
||||
'ldap_dn2ufn' => ['string', 'dn'=>'string'],
|
||||
'ldap_dn2ufn' => ['string|false', 'dn'=>'string'],
|
||||
'ldap_err2str' => ['string', 'errno'=>'int'],
|
||||
'ldap_errno' => ['int', 'ldap'=>'resource'],
|
||||
'ldap_error' => ['string', 'ldap'=>'resource'],
|
||||
@@ -12143,7 +12121,7 @@ return [
|
||||
'ldap_get_option' => ['bool', 'ldap'=>'resource', 'option'=>'int', '&w_value='=>'array|string|int'],
|
||||
'ldap_get_values' => ['array|false', 'ldap'=>'resource', 'entry'=>'resource', 'attribute'=>'string'],
|
||||
'ldap_get_values_len' => ['array|false', 'ldap'=>'resource', 'entry'=>'resource', 'attribute'=>'string'],
|
||||
'ldap_list' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'ldap_list' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'ldap_mod_add' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'entry'=>'array'],
|
||||
'ldap_mod_add_ext' => ['resource|false', 'ldap'=>'resource', 'dn'=>'string', 'entry'=>'array', 'controls='=>'array'],
|
||||
'ldap_mod_del' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'entry'=>'array'],
|
||||
@@ -12157,11 +12135,11 @@ return [
|
||||
'ldap_next_reference' => ['resource|false', 'ldap'=>'resource', 'entry'=>'resource'],
|
||||
'ldap_parse_reference' => ['bool', 'ldap'=>'resource', 'entry'=>'resource', '&w_referrals'=>'array'],
|
||||
'ldap_parse_result' => ['bool', 'ldap'=>'resource', 'result'=>'resource', '&w_error_code'=>'int', '&w_matched_dn='=>'string', '&w_error_message='=>'string', '&w_referrals='=>'array', '&w_controls='=>'array'],
|
||||
'ldap_read' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'ldap_read' => ['resource|false', 'ldap'=>'resource|array', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'ldap_rename' => ['bool', 'ldap'=>'resource', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool'],
|
||||
'ldap_rename_ext' => ['resource|false', 'ldap'=>'resource', 'dn'=>'string', 'new_rdn'=>'string', 'new_parent'=>'string', 'delete_old_rdn'=>'bool', 'controls='=>'array'],
|
||||
'ldap_sasl_bind' => ['bool', 'ldap'=>'resource', 'dn='=>'string', 'password='=>'string', 'mech='=>'string', 'realm='=>'string', 'authc_id='=>'string', 'authz_id='=>'string', 'props='=>'string'],
|
||||
'ldap_search' => ['resource|false', 'ldap'=>'resource|resource[]', 'base'=>'string', 'filter'=>'string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'ldap_search' => ['resource[]|resource|false', 'ldap'=>'resource|resource[]', 'base'=>'array|string', 'filter'=>'array|string', 'attributes='=>'array', 'attributes_only='=>'int', 'sizelimit='=>'int', 'timelimit='=>'int', 'deref='=>'int'],
|
||||
'ldap_set_option' => ['bool', 'ldap'=>'resource|null', 'option'=>'int', 'value'=>'mixed'],
|
||||
'ldap_set_rebind_proc' => ['bool', 'ldap'=>'resource', 'callback'=>'callable'],
|
||||
'ldap_sort' => ['bool', 'link_identifier'=>'resource', 'result_identifier'=>'resource', 'sortfilter'=>'string'],
|
||||
@@ -12726,7 +12704,6 @@ return [
|
||||
'mysqli::commit' => ['bool', 'flags='=>'int', 'name='=>'string'],
|
||||
'mysqli::connect' => ['null|false', 'hostname='=>'string', 'username='=>'string', 'password='=>'string', 'database='=>'string', 'port='=>'int', 'socket='=>'string'],
|
||||
'mysqli::debug' => ['bool', 'options'=>'string'],
|
||||
'mysqli::disable_reads_from_master' => ['bool'],
|
||||
'mysqli::dump_debug_info' => ['bool'],
|
||||
'mysqli::escape_string' => ['string', 'string'=>'string'],
|
||||
'mysqli::get_charset' => ['object'],
|
||||
@@ -12740,23 +12717,19 @@ return [
|
||||
'mysqli::next_result' => ['bool'],
|
||||
'mysqli::options' => ['bool', 'option'=>'int', 'value'=>'string|int'],
|
||||
'mysqli::ping' => ['bool'],
|
||||
'mysqli::poll' => ['int|false', '&w_read'=>'array', '&w_write'=>'array', '&w_error'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
|
||||
'mysqli::poll' => ['int|false', '&w_read'=>'?array', '&w_error'=>'?array', '&w_reject'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
|
||||
'mysqli::prepare' => ['mysqli_stmt|false', 'query'=>'string'],
|
||||
'mysqli::query' => ['bool|mysqli_result', 'query'=>'string', 'result_mode='=>'int'],
|
||||
'mysqli::real_connect' => ['bool', 'hostname='=>'string|null', 'username='=>'string|null', 'password='=>'string|null', 'database='=>'string|null', 'port='=>'int|null', 'socket='=>'string|null', 'flags='=>'int'],
|
||||
'mysqli::real_connect' => ['bool', 'hostname='=>'?string', 'username='=>'?string', 'password='=>'?string', 'database='=>'?string', 'port='=>'?int', 'socket='=>'?string', 'flags='=>'int'],
|
||||
'mysqli::real_escape_string' => ['string', 'string'=>'string'],
|
||||
'mysqli::real_query' => ['bool', 'query'=>'string'],
|
||||
'mysqli::reap_async_query' => ['mysqli_result|false'],
|
||||
'mysqli::refresh' => ['bool', 'flags'=>'int'],
|
||||
'mysqli::release_savepoint' => ['bool', 'name'=>'string'],
|
||||
'mysqli::rollback' => ['bool', 'flags='=>'int', 'name='=>'string'],
|
||||
'mysqli::rpl_query_type' => ['int', 'query'=>'string'],
|
||||
'mysqli::savepoint' => ['bool', 'name'=>'string'],
|
||||
'mysqli::select_db' => ['bool', 'database'=>'string'],
|
||||
'mysqli::send_query' => ['bool', 'query'=>'string'],
|
||||
'mysqli::set_charset' => ['bool', 'charset'=>'string'],
|
||||
'mysqli::set_local_infile_default' => ['void'],
|
||||
'mysqli::set_local_infile_handler' => ['bool', 'read_func='=>'callable'],
|
||||
'mysqli::set_opt' => ['bool', 'option'=>'int', 'value'=>'string|int'],
|
||||
'mysqli::ssl_set' => ['bool', 'key'=>'?string', 'certificate'=>'?string', 'ca_certificate'=>'?string', 'ca_path'=>'?string', 'cipher_algos'=>'?string'],
|
||||
'mysqli::stat' => ['string|false'],
|
||||
@@ -12778,8 +12751,6 @@ return [
|
||||
'mysqli_debug' => ['true', 'options'=>'string'],
|
||||
'mysqli_disable_reads_from_master' => ['bool', 'link'=>'mysqli'],
|
||||
'mysqli_disable_rpl_parse' => ['bool', 'link'=>'mysqli'],
|
||||
'mysqli_driver::embedded_server_end' => ['void'],
|
||||
'mysqli_driver::embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'],
|
||||
'mysqli_dump_debug_info' => ['bool', 'mysql'=>'mysqli'],
|
||||
'mysqli_embedded_server_end' => ['void'],
|
||||
'mysqli_embedded_server_start' => ['bool', 'start'=>'int', 'arguments'=>'array', 'groups'=>'array'],
|
||||
@@ -12797,9 +12768,9 @@ return [
|
||||
'mysqli_fetch_array\'1' => ['array<string,null|int|float|string>|false|null', 'result'=>'mysqli_result', 'mode='=>'1'],
|
||||
'mysqli_fetch_array\'2' => ['list<null|int|float|string>|false|null', 'result'=>'mysqli_result', 'mode='=>'2'],
|
||||
'mysqli_fetch_assoc' => ['array<string,null|int|float|string>|false|null', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_field' => ['object|false', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_field_direct' => ['object|false', 'result'=>'mysqli_result', 'index'=>'int'],
|
||||
'mysqli_fetch_fields' => ['stdClass[]', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_field' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_field_direct' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'result'=>'mysqli_result', 'index'=>'int'],
|
||||
'mysqli_fetch_fields' => ['list<object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}>', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_lengths' => ['array|false', 'result'=>'mysqli_result'],
|
||||
'mysqli_fetch_object' => ['object|false|null', 'result'=>'mysqli_result', 'class='=>'string', 'constructor_args='=>'array'],
|
||||
'mysqli_fetch_row' => ['list<null|int|float|string>|false|null', 'result'=>'mysqli_result'],
|
||||
@@ -12832,10 +12803,10 @@ return [
|
||||
'mysqli_num_rows' => ['int<0, max>|numeric-string', 'result'=>'mysqli_result'],
|
||||
'mysqli_options' => ['bool', 'mysql'=>'mysqli', 'option'=>'int', 'value'=>'string|int'],
|
||||
'mysqli_ping' => ['bool', 'mysql'=>'mysqli'],
|
||||
'mysqli_poll' => ['int|false', 'read'=>'array', 'write'=>'array', 'error'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
|
||||
'mysqli_poll' => ['int|false', '&w_read'=>'?array', '&w_error'=>'?array', '&w_reject'=>'array', 'seconds'=>'int', 'microseconds='=>'int'],
|
||||
'mysqli_prepare' => ['mysqli_stmt|false', 'mysql'=>'mysqli', 'query'=>'string'],
|
||||
'mysqli_query' => ['mysqli_result|bool', 'mysql'=>'mysqli', 'query'=>'string', 'result_mode='=>'int'],
|
||||
'mysqli_real_connect' => ['bool', 'mysql='=>'mysqli', 'hostname='=>'string|null', 'username='=>'string|null', 'password='=>'string|null', 'database='=>'string|null', 'port='=>'int|null', 'socket='=>'string|null', 'flags='=>'int'],
|
||||
'mysqli_real_connect' => ['bool', 'mysql'=>'mysqli', 'hostname='=>'?string', 'username='=>'?string', 'password='=>'?string', 'database='=>'?string', 'port='=>'?int', 'socket='=>'?string', 'flags='=>'int'],
|
||||
'mysqli_real_escape_string' => ['string', 'mysql'=>'mysqli', 'string'=>'string'],
|
||||
'mysqli_real_query' => ['bool', 'mysql'=>'mysqli', 'query'=>'string'],
|
||||
'mysqli_reap_async_query' => ['mysqli_result|false', 'mysql'=>'mysqli'],
|
||||
@@ -12852,9 +12823,9 @@ return [
|
||||
'mysqli_result::fetch_array\'1' => ['array<string,null|int|float|string>|false|null', 'mode='=>'1'],
|
||||
'mysqli_result::fetch_array\'2' => ['list<null|int|float|string>|false|null', 'mode='=>'2'],
|
||||
'mysqli_result::fetch_assoc' => ['array<string,null|int|float|string>|false|null'],
|
||||
'mysqli_result::fetch_field' => ['object|false'],
|
||||
'mysqli_result::fetch_field_direct' => ['object|false', 'index'=>'int'],
|
||||
'mysqli_result::fetch_fields' => ['stdClass[]'],
|
||||
'mysqli_result::fetch_field' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false'],
|
||||
'mysqli_result::fetch_field_direct' => ['object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}|false', 'index'=>'int'],
|
||||
'mysqli_result::fetch_fields' => ['list<object{name:non-empty-string,orgname:string,table:string,orgtable:string,max_length:int,length:int,charsetnr:int,flags:int,type:int,decimals:int,db:string,def:string,catalog:string}>'],
|
||||
'mysqli_result::fetch_object' => ['object|false|null', 'class='=>'string', 'constructor_args='=>'array'],
|
||||
'mysqli_result::fetch_row' => ['list<null|int|float|string>|false|null'],
|
||||
'mysqli_result::field_seek' => ['bool', 'index'=>'int'],
|
||||
@@ -12876,10 +12847,10 @@ return [
|
||||
'mysqli_sqlstate' => ['string', 'mysql'=>'mysqli'],
|
||||
'mysqli_ssl_set' => ['true', 'mysql'=>'mysqli', 'key'=>'?string', 'certificate'=>'?string', 'ca_certificate'=>'?string', 'ca_path'=>'?string', 'cipher_algos'=>'?string'],
|
||||
'mysqli_stat' => ['string|false', 'mysql'=>'mysqli'],
|
||||
'mysqli_stmt::__construct' => ['void', 'mysql'=>'mysqli', 'query'=>'string'],
|
||||
'mysqli_stmt::__construct' => ['void', 'mysql'=>'mysqli', 'query='=>'string'],
|
||||
'mysqli_stmt::attr_get' => ['int', 'attribute'=>'int'],
|
||||
'mysqli_stmt::attr_set' => ['bool', 'attribute'=>'int', 'value'=>'int'],
|
||||
'mysqli_stmt::bind_param' => ['bool', 'types'=>'string', '&vars'=>'mixed', '&...args='=>'mixed'],
|
||||
'mysqli_stmt::bind_param' => ['bool', 'types'=>'string', '&var'=>'mixed', '&...vars='=>'mixed'],
|
||||
'mysqli_stmt::bind_result' => ['bool', '&w_var1'=>'', '&...w_vars='=>''],
|
||||
'mysqli_stmt::close' => ['bool'],
|
||||
'mysqli_stmt::data_seek' => ['void', 'offset'=>'int'],
|
||||
@@ -12899,7 +12870,7 @@ return [
|
||||
'mysqli_stmt_affected_rows' => ['int<-1, max>|numeric-string', 'statement'=>'mysqli_stmt'],
|
||||
'mysqli_stmt_attr_get' => ['int', 'statement'=>'mysqli_stmt', 'attribute'=>'int'],
|
||||
'mysqli_stmt_attr_set' => ['bool', 'statement'=>'mysqli_stmt', 'attribute'=>'int', 'value'=>'int'],
|
||||
'mysqli_stmt_bind_param' => ['bool', 'statement'=>'mysqli_stmt', 'types'=>'string', '&vars'=>'mixed', '&...args='=>'mixed'],
|
||||
'mysqli_stmt_bind_param' => ['bool', 'statement'=>'mysqli_stmt', 'types'=>'string', '&var'=>'mixed', '&...vars='=>'mixed'],
|
||||
'mysqli_stmt_bind_result' => ['bool', 'statement'=>'mysqli_stmt', '&w_var1'=>'', '&...w_vars='=>''],
|
||||
'mysqli_stmt_close' => ['true', 'statement'=>'mysqli_stmt'],
|
||||
'mysqli_stmt_data_seek' => ['void', 'statement'=>'mysqli_stmt', 'offset'=>'int'],
|
||||
@@ -13008,12 +12979,12 @@ return [
|
||||
'nsapi_response_headers' => ['array'],
|
||||
'nsapi_virtual' => ['bool', 'uri'=>'string'],
|
||||
'nthmac' => ['string', 'clent'=>'string', 'data'=>'string'],
|
||||
'number_format' => ['string', 'num'=>'float|int', 'decimals='=>'int'],
|
||||
'number_format\'1' => ['string', 'num'=>'float|int', 'decimals'=>'int', 'decimal_separator'=>'?string', 'thousands_separator'=>'?string'],
|
||||
'number_format' => ['string', 'num'=>'float', 'decimals='=>'int'],
|
||||
'number_format\'1' => ['string', 'num'=>'float', 'decimals'=>'int', 'decimal_separator'=>'?string', 'thousands_separator'=>'?string'],
|
||||
'numfmt_create' => ['NumberFormatter|null', 'locale'=>'string', 'style'=>'int', 'pattern='=>'string'],
|
||||
'numfmt_format' => ['string|false', 'formatter'=>'NumberFormatter', 'num'=>'int|float', 'type='=>'int'],
|
||||
'numfmt_format_currency' => ['string|false', 'formatter'=>'NumberFormatter', 'amount'=>'float', 'currency'=>'string'],
|
||||
'numfmt_get_attribute' => ['int|false', 'formatter'=>'NumberFormatter', 'attribute'=>'int'],
|
||||
'numfmt_get_attribute' => ['float|int|false', 'formatter'=>'NumberFormatter', 'attribute'=>'int'],
|
||||
'numfmt_get_error_code' => ['int', 'formatter'=>'NumberFormatter'],
|
||||
'numfmt_get_error_message' => ['string', 'formatter'=>'NumberFormatter'],
|
||||
'numfmt_get_locale' => ['string', 'formatter'=>'NumberFormatter', 'type='=>'int'],
|
||||
@@ -13022,7 +12993,7 @@ return [
|
||||
'numfmt_get_text_attribute' => ['string|false', 'formatter'=>'NumberFormatter', 'attribute'=>'int'],
|
||||
'numfmt_parse' => ['float|int|false', 'formatter'=>'NumberFormatter', 'string'=>'string', 'type='=>'int', '&rw_offset='=>'int'],
|
||||
'numfmt_parse_currency' => ['float|false', 'formatter'=>'NumberFormatter', 'string'=>'string', '&w_currency'=>'string', '&rw_offset='=>'int'],
|
||||
'numfmt_set_attribute' => ['bool', 'formatter'=>'NumberFormatter', 'attribute'=>'int', 'value'=>'int'],
|
||||
'numfmt_set_attribute' => ['bool', 'formatter'=>'NumberFormatter', 'attribute'=>'int', 'value'=>'float|int'],
|
||||
'numfmt_set_pattern' => ['bool', 'formatter'=>'NumberFormatter', 'pattern'=>'string'],
|
||||
'numfmt_set_symbol' => ['bool', 'formatter'=>'NumberFormatter', 'symbol'=>'int', 'value'=>'string'],
|
||||
'numfmt_set_text_attribute' => ['bool', 'formatter'=>'NumberFormatter', 'attribute'=>'int', 'value'=>'string'],
|
||||
@@ -13163,9 +13134,9 @@ return [
|
||||
'odbc_pconnect' => ['resource|false', 'dsn'=>'string', 'user'=>'string', 'password'=>'string', 'cursor_option='=>'int'],
|
||||
'odbc_prepare' => ['resource|false', 'odbc'=>'resource', 'query'=>'string'],
|
||||
'odbc_primarykeys' => ['resource|false', 'odbc'=>'resource', 'catalog'=>'?string', 'schema'=>'string', 'table'=>'string'],
|
||||
'odbc_procedurecolumns' => ['resource|false', 'odbc'=>'resource', 'catalog'=>'string', 'schema'=>'string', 'procedure'=>'string', 'column'=>'string'],
|
||||
'odbc_procedures' => ['resource|false', 'odbc'=>'resource', 'catalog'=>'string', 'schema'=>'string', 'procedure'=>'string'],
|
||||
'odbc_result' => ['mixed|false', 'statement'=>'resource', 'field'=>'mixed'],
|
||||
'odbc_procedurecolumns' => ['resource|false', 'odbc'=>'resource', 'catalog='=>'?string', 'schema='=>'?string', 'procedure='=>'?string', 'column='=>'?string'],
|
||||
'odbc_procedures' => ['resource|false', 'odbc'=>'resource', 'catalog='=>'?string', 'schema='=>'?string', 'procedure='=>'?string'],
|
||||
'odbc_result' => ['string|bool|null', 'statement'=>'resource', 'field'=>'string|int'],
|
||||
'odbc_result_all' => ['int|false', 'statement'=>'resource', 'format='=>'string'],
|
||||
'odbc_rollback' => ['bool', 'odbc'=>'resource'],
|
||||
'odbc_setoption' => ['bool', 'odbc'=>'resource', 'which'=>'int', 'option'=>'int', 'value'=>'int'],
|
||||
@@ -13229,7 +13200,7 @@ return [
|
||||
'openssl_pkcs12_read' => ['bool', 'pkcs12'=>'string', '&w_certificates'=>'array', 'passphrase'=>'string'],
|
||||
'openssl_pkcs7_decrypt' => ['bool', 'input_filename'=>'string', 'output_filename'=>'string', 'certificate'=>'string|resource', 'private_key='=>'string|resource|array'],
|
||||
'openssl_pkcs7_encrypt' => ['bool', 'input_filename'=>'string', 'output_filename'=>'string', 'certificate'=>'string|resource|array', 'headers'=>'array', 'flags='=>'int', 'cipher_algo='=>'int'],
|
||||
'openssl_pkcs7_read' => ['bool', 'input_filename'=>'string', '&w_certificates'=>'array'],
|
||||
'openssl_pkcs7_read' => ['bool', 'data'=>'string', '&w_certificates'=>'array'],
|
||||
'openssl_pkcs7_sign' => ['bool', 'input_filename'=>'string', 'output_filename'=>'string', 'certificate'=>'string|resource', 'private_key'=>'string|resource|array', 'headers'=>'array', 'flags='=>'int', 'untrusted_certificates_filename='=>'string'],
|
||||
'openssl_pkcs7_verify' => ['bool|int', 'input_filename'=>'string', 'flags'=>'int', 'signers_certificates_filename='=>'string', 'ca_info='=>'array', 'untrusted_certificates_filename='=>'string', 'content='=>'string', 'output_filename='=>'string'],
|
||||
'openssl_pkey_export' => ['bool', 'key'=>'resource', '&w_output'=>'string', 'passphrase='=>'string|null', 'options='=>'array'],
|
||||
@@ -13758,7 +13729,7 @@ return [
|
||||
'rand\'1' => ['int'],
|
||||
'random_bytes' => ['non-empty-string', 'length'=>'positive-int'],
|
||||
'random_int' => ['int', 'min'=>'int', 'max'=>'int'],
|
||||
'range' => ['array', 'start'=>'mixed', 'end'=>'mixed', 'step='=>'int|float'],
|
||||
'range' => ['non-empty-array', 'start'=>'string|int|float', 'end'=>'string|int|float', 'step='=>'int<1, max>|float'],
|
||||
'rar_allow_broken_set' => ['bool', 'rarfile'=>'RarArchive', 'allow_broken'=>'bool'],
|
||||
'rar_broken_is' => ['bool', 'rarfile'=>'rararchive'],
|
||||
'rar_close' => ['bool', 'rarfile'=>'rararchive'],
|
||||
@@ -13823,7 +13794,7 @@ return [
|
||||
'rewind' => ['bool', 'stream'=>'resource'],
|
||||
'rewinddir' => ['void', 'dir_handle='=>'resource'],
|
||||
'rmdir' => ['bool', 'directory'=>'string', 'context='=>'resource'],
|
||||
'round' => ['float', 'num'=>'float', 'precision='=>'int', 'mode='=>'0|positive-int'],
|
||||
'round' => ['float', 'num'=>'float|int', 'precision='=>'int', 'mode='=>'0|positive-int'],
|
||||
'rpm_close' => ['bool', 'rpmr'=>'resource'],
|
||||
'rpm_get_tag' => ['mixed', 'rpmr'=>'resource', 'tagnum'=>'int'],
|
||||
'rpm_is_valid' => ['bool', 'filename'=>'string'],
|
||||
@@ -13907,16 +13878,16 @@ return [
|
||||
'sem_remove' => ['bool', 'semaphore'=>'resource'],
|
||||
'serialize' => ['string', 'value'=>'mixed'],
|
||||
'session_abort' => ['bool'],
|
||||
'session_cache_expire' => ['int', 'value='=>'int'],
|
||||
'session_cache_limiter' => ['string', 'value='=>'string'],
|
||||
'session_cache_expire' => ['int|false', 'value='=>'int'],
|
||||
'session_cache_limiter' => ['string|false', 'value='=>'string'],
|
||||
'session_commit' => ['bool'],
|
||||
'session_decode' => ['bool', 'data'=>'string'],
|
||||
'session_destroy' => ['bool'],
|
||||
'session_encode' => ['string'],
|
||||
'session_encode' => ['string|false'],
|
||||
'session_get_cookie_params' => ['array'],
|
||||
'session_id' => ['string|false', 'id='=>'string'],
|
||||
'session_is_registered' => ['bool', 'name'=>'string'],
|
||||
'session_module_name' => ['string', 'module='=>'string'],
|
||||
'session_module_name' => ['string|false', 'module='=>'string'],
|
||||
'session_name' => ['string|false', 'name='=>'string'],
|
||||
'session_pgsql_add_error' => ['bool', 'error_level'=>'int', 'error_message='=>'string'],
|
||||
'session_pgsql_get_error' => ['array', 'with_error_message='=>'bool'],
|
||||
@@ -13928,7 +13899,7 @@ return [
|
||||
'session_register' => ['bool', 'name'=>'mixed', '...args='=>'mixed'],
|
||||
'session_register_shutdown' => ['void'],
|
||||
'session_reset' => ['bool'],
|
||||
'session_save_path' => ['string', 'path='=>'string'],
|
||||
'session_save_path' => ['string|false', 'path='=>'string'],
|
||||
'session_set_cookie_params' => ['bool', 'lifetime'=>'int', 'path='=>'string', 'domain='=>'string', 'secure='=>'bool', 'httponly='=>'bool'],
|
||||
'session_set_save_handler' => ['bool', 'open'=>'callable(string,string):bool', 'close'=>'callable():bool', 'read'=>'callable(string):string', 'write'=>'callable(string,string):bool', 'destroy'=>'callable(string):bool', 'gc'=>'callable(string):bool', 'create_sid='=>'callable():string', 'validate_sid='=>'callable(string):bool', 'update_timestamp='=>'callable(string):bool'],
|
||||
'session_set_save_handler\'1' => ['bool', 'open'=>'SessionHandlerInterface', 'close='=>'bool'],
|
||||
@@ -14024,16 +13995,16 @@ return [
|
||||
'sinh' => ['float', 'num'=>'float'],
|
||||
'sizeof' => ['int<0, max>', 'value'=>'Countable|array|SimpleXMLElement', 'mode='=>'int'],
|
||||
'sleep' => ['int|false', 'seconds'=>'0|positive-int'],
|
||||
'snmp2_get' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_getnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_real_walk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_set' => ['bool', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_walk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_get' => ['string|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_getnext' => ['string|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_real_walk' => ['array|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_set' => ['bool', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'type'=>'string', 'value'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_walk' => ['array|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_get' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_getnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_real_walk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_set' => ['bool', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'type'=>'array|string', 'value'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp2_walk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_get' => ['string|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_getnext' => ['string|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_real_walk' => ['array|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_set' => ['bool', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'type'=>'array|string', 'value'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp3_walk' => ['array|false', 'hostname'=>'string', 'security_name'=>'string', 'security_level'=>'string', 'auth_protocol'=>'string', 'auth_passphrase'=>'string', 'privacy_protocol'=>'string', 'privacy_passphrase'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmp_get_quick_print' => ['bool'],
|
||||
'snmp_get_valueretrieval' => ['int'],
|
||||
'snmp_read_mib' => ['bool', 'filename'=>'string'],
|
||||
@@ -14042,12 +14013,12 @@ return [
|
||||
'snmp_set_oid_output_format' => ['true', 'format'=>'int'],
|
||||
'snmp_set_quick_print' => ['bool', 'enable'=>'bool'],
|
||||
'snmp_set_valueretrieval' => ['true', 'method'=>'int'],
|
||||
'snmpget' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpgetnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmprealwalk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpset' => ['bool', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'type'=>'string|string[]', 'value'=>'string|string[]', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpwalk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpwalkoid' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpget' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpgetnext' => ['string|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmprealwalk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpset' => ['bool', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'type'=>'string|string[]', 'value'=>'string|string[]', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpwalk' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'snmpwalkoid' => ['array|false', 'hostname'=>'string', 'community'=>'string', 'object_id'=>'array|string', 'timeout='=>'int', 'retries='=>'int'],
|
||||
'socket_accept' => ['resource|false', 'socket'=>'resource'],
|
||||
'socket_bind' => ['bool', 'socket'=>'resource', 'address'=>'string', 'port='=>'int'],
|
||||
'socket_clear_error' => ['void', 'socket='=>'resource'],
|
||||
@@ -14144,7 +14115,7 @@ return [
|
||||
'sqlsrv_commit' => ['bool', 'conn'=>'resource'],
|
||||
'sqlsrv_configure' => ['bool', 'setting'=>'string', 'value'=>'mixed'],
|
||||
'sqlsrv_connect' => ['resource|false', 'serverName'=>'string', 'connectionInfo='=>'array'],
|
||||
'sqlsrv_errors' => ['?array', 'errorsOrWarnings='=>'int'],
|
||||
'sqlsrv_errors' => ['?array', 'errorsAndOrWarnings='=>'int'],
|
||||
'sqlsrv_execute' => ['bool', 'stmt'=>'resource'],
|
||||
'sqlsrv_fetch' => ['?bool', 'stmt'=>'resource', 'row='=>'int', 'offset='=>'int'],
|
||||
'sqlsrv_fetch_array' => ['array|null|false', 'stmt'=>'resource', 'fetchType='=>'int', 'row='=>'int', 'offset='=>'int'],
|
||||
@@ -14340,7 +14311,7 @@ return [
|
||||
'stream_context_create' => ['resource', 'options='=>'array', 'params='=>'array'],
|
||||
'stream_context_get_default' => ['resource', 'options='=>'array'],
|
||||
'stream_context_get_options' => ['array', 'stream_or_context'=>'resource'],
|
||||
'stream_context_get_params' => ['array', 'context'=>'resource'],
|
||||
'stream_context_get_params' => ['array{notification:string,options:array}', 'context'=>'resource'],
|
||||
'stream_context_set_default' => ['resource', 'options'=>'array'],
|
||||
'stream_context_set_option' => ['bool', 'context'=>'', 'wrapper_or_options'=>'string', 'option_name'=>'string', 'value'=>''],
|
||||
'stream_context_set_option\'1' => ['bool', 'context'=>'', 'wrapper_or_options'=>'array'],
|
||||
@@ -14370,10 +14341,10 @@ return [
|
||||
'stream_socket_accept' => ['resource|false', 'socket'=>'resource', 'timeout='=>'float', '&w_peer_name='=>'string'],
|
||||
'stream_socket_client' => ['resource|false', 'address'=>'string', '&w_error_code='=>'int', '&w_error_message='=>'string', 'timeout='=>'float', 'flags='=>'int', 'context='=>'resource'],
|
||||
'stream_socket_enable_crypto' => ['int|bool', 'stream'=>'resource', 'enable'=>'bool', 'crypto_method='=>'?int', 'session_stream='=>'resource'],
|
||||
'stream_socket_get_name' => ['string', 'socket'=>'resource', 'remote'=>'bool'],
|
||||
'stream_socket_get_name' => ['string|false', 'socket'=>'resource', 'remote'=>'bool'],
|
||||
'stream_socket_pair' => ['resource[]|false', 'domain'=>'int', 'type'=>'int', 'protocol'=>'int'],
|
||||
'stream_socket_recvfrom' => ['string', 'socket'=>'resource', 'length'=>'int', 'flags='=>'int', '&w_address='=>'string'],
|
||||
'stream_socket_sendto' => ['int', 'socket'=>'resource', 'data'=>'string', 'flags='=>'int', 'address='=>'string'],
|
||||
'stream_socket_recvfrom' => ['string|false', 'socket'=>'resource', 'length'=>'int', 'flags='=>'int', '&w_address='=>'string'],
|
||||
'stream_socket_sendto' => ['int|false', 'socket'=>'resource', 'data'=>'string', 'flags='=>'int', 'address='=>'string'],
|
||||
'stream_socket_server' => ['resource|false', 'address'=>'string', '&w_error_code='=>'int', '&w_error_message='=>'string', 'flags='=>'int', 'context='=>'resource'],
|
||||
'stream_socket_shutdown' => ['bool', 'stream'=>'resource', 'mode'=>'int'],
|
||||
'stream_supports_lock' => ['bool', 'stream'=>'resource'],
|
||||
@@ -14808,7 +14779,7 @@ return [
|
||||
'symbolObj::setPoints' => ['int', 'double'=>'array'],
|
||||
'symlink' => ['bool', 'target'=>'string', 'link'=>'string'],
|
||||
'sys_get_temp_dir' => ['string'],
|
||||
'sys_getloadavg' => ['array'],
|
||||
'sys_getloadavg' => ['array|false'],
|
||||
'syslog' => ['true', 'priority'=>'int', 'message'=>'string'],
|
||||
'system' => ['string|false', 'command'=>'string', '&w_result_code='=>'int'],
|
||||
'taint' => ['bool', '&rw_string'=>'string', '&...w_other_strings='=>'string'],
|
||||
@@ -15259,7 +15230,7 @@ return [
|
||||
'uksort' => ['true', '&rw_array'=>'array', 'callback'=>'callable(mixed,mixed):int'],
|
||||
'umask' => ['int', 'mask='=>'int'],
|
||||
'uniqid' => ['non-empty-string', 'prefix='=>'string', 'more_entropy='=>'bool'],
|
||||
'unixtojd' => ['int', 'timestamp='=>'int'],
|
||||
'unixtojd' => ['int|false', 'timestamp='=>'int'],
|
||||
'unlink' => ['bool', 'filename'=>'string', 'context='=>'resource'],
|
||||
'unpack' => ['array', 'format'=>'string', 'string'=>'string'],
|
||||
'unregister_tick_function' => ['void', 'callback'=>'callable'],
|
||||
@@ -15534,7 +15505,7 @@ return [
|
||||
'xml_parser_create' => ['resource', 'encoding='=>'string'],
|
||||
'xml_parser_create_ns' => ['resource', 'encoding='=>'string', 'separator='=>'string'],
|
||||
'xml_parser_free' => ['bool', 'parser'=>'resource'],
|
||||
'xml_parser_get_option' => ['string|false', 'parser'=>'resource', 'option'=>'int'],
|
||||
'xml_parser_get_option' => ['string|int', 'parser'=>'resource', 'option'=>'int'],
|
||||
'xml_parser_set_option' => ['bool', 'parser'=>'resource', 'option'=>'int', 'value'=>'mixed'],
|
||||
'xml_set_character_data_handler' => ['true', 'parser'=>'resource', 'handler'=>'callable'],
|
||||
'xml_set_default_handler' => ['true', 'parser'=>'resource', 'handler'=>'callable'],
|
||||
@@ -15689,7 +15660,7 @@ return [
|
||||
'zip_entry_compressedsize' => ['int', 'zip_entry'=>'resource'],
|
||||
'zip_entry_compressionmethod' => ['string', 'zip_entry'=>'resource'],
|
||||
'zip_entry_filesize' => ['int', 'zip_entry'=>'resource'],
|
||||
'zip_entry_name' => ['string', 'zip_entry'=>'resource'],
|
||||
'zip_entry_name' => ['string|false', 'zip_entry'=>'resource'],
|
||||
'zip_entry_open' => ['bool', 'zip_dp'=>'resource', 'zip_entry'=>'resource', 'mode='=>'string'],
|
||||
'zip_entry_read' => ['string|false', 'zip_entry'=>'resource', 'len='=>'int'],
|
||||
'zip_open' => ['resource|int|false', 'filename'=>'string'],
|
||||
|
||||
@@ -7,23 +7,25 @@ Psalm supports a wide range of docblock annotations.
|
||||
Psalm uses the following PHPDoc tags to understand your code:
|
||||
|
||||
- [`@var`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/var.html)
|
||||
Used for specifying the types of properties and variables@
|
||||
Used for specifying the types of properties and variables
|
||||
- [`@return`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/return.html)
|
||||
Used for specifying the return types of functions, methods and closures
|
||||
- [`@param`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/param.html)
|
||||
Used for specifying types of parameters passed to functions, methods and closures
|
||||
- [`@property`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property.html)
|
||||
Used to specify what properties can be accessed on an object that uses `__get` and `__set`
|
||||
- [`@property-read`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property-read.html)
|
||||
- [`@property-read`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property.html)
|
||||
Used to specify what properties can be read on object that uses `__get`
|
||||
- [`@property-write`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property-write.html)
|
||||
- [`@property-write`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/property.html)
|
||||
Used to specify what properties can be written on object that uses `__set`
|
||||
- [`@method`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/method.html)
|
||||
Used to specify which magic methods are available on object that uses `__call`.
|
||||
- [`@deprecated`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/deprecated.html)
|
||||
Used to mark functions, methods, classes and interfaces as being deprecated
|
||||
- [`@internal`](https://docs.phpdoc.org/latest/guide/references/phpdoc/tags/internal.html)
|
||||
used to mark classes, functions and properties that are internal to an application or library.
|
||||
Used to mark classes, functions and properties that are internal to an application or library.
|
||||
- [`@mixin`](#mixins)
|
||||
Used to tell Psalm that the current class proxies the methods and properties of the referenced class.
|
||||
|
||||
### Off-label usage of the `@var` tag
|
||||
|
||||
@@ -46,6 +48,49 @@ function bat(): string {
|
||||
return $_GET['bat'];
|
||||
}
|
||||
```
|
||||
### @mixins
|
||||
|
||||
Adding `@mixin` to a classes docblock tells Psalm that the class proxies will proxy the methods and properties of the referenced class.
|
||||
|
||||
```php
|
||||
class A
|
||||
{
|
||||
public string $a = 'A';
|
||||
|
||||
public function doA(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @mixin A
|
||||
*/
|
||||
class B
|
||||
{
|
||||
public string $b = 'B';
|
||||
|
||||
public function doB(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
(new A())->$name(...$arguments);
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
(new A())->$name;
|
||||
}
|
||||
}
|
||||
|
||||
$b = new B();
|
||||
$b->doB();
|
||||
$b->doA(); // works
|
||||
echo $b->b;
|
||||
echo $b->a; // works
|
||||
```
|
||||
|
||||
|
||||
## Psalm-specific tags
|
||||
|
||||
@@ -157,9 +202,10 @@ takesFoo(getFoo());
|
||||
|
||||
This provides the same, but for `false`. Psalm uses this internally for functions like `preg_replace`, which can return false if the given input has encoding errors, but where 99.9% of the time the function operates as expected.
|
||||
|
||||
### `@psalm-seal-properties`
|
||||
### `@psalm-seal-properties`, `@psalm-no-seal-properties`
|
||||
|
||||
If you have a magic property getter/setter, you can use `@psalm-seal-properties` to instruct Psalm to disallow getting and setting any properties not contained in a list of `@property` (or `@property-read`/`@property-write`) annotations.
|
||||
This is automatically enabled with the configuration option `sealAllProperties` and can be disabled for a class with `@psalm-no-seal-properties`
|
||||
|
||||
```php
|
||||
<?php
|
||||
@@ -181,6 +227,29 @@ $a = new A();
|
||||
$a->bar = 5; // this call fails
|
||||
```
|
||||
|
||||
### `@psalm-seal-methods`, `@psalm-no-seal-methods`
|
||||
|
||||
If you have a magic method caller, you can use `@psalm-seal-methods` to instruct Psalm to disallow calling any methods not contained in a list of `@method` annotations.
|
||||
This is automatically enabled with the configuration option `sealAllMethods` and can be disabled for a class with `@psalm-no-seal-methods`
|
||||
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* @method foo(): string
|
||||
* @psalm-seal-methods
|
||||
*/
|
||||
class A {
|
||||
public function __call(string $name, array $args) {
|
||||
if ($name === "foo") {
|
||||
return "hello";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$a = new A();
|
||||
$b = $a->bar(); // this call fails
|
||||
```
|
||||
|
||||
### `@psalm-internal`
|
||||
|
||||
Used to mark a class, property or function as internal to a given namespace. Psalm treats this slightly differently to
|
||||
@@ -446,7 +515,18 @@ $username = $_GET['username']; // prints something like "test.php:4 $username: m
|
||||
|
||||
```
|
||||
|
||||
*Note*: it throws [special low-level issue](../running_psalm/issues/Trace.md), so you have to set errorLevel to 1, override it in config or invoke Psalm with `--show-info=true`.
|
||||
*Note*: it throws [special low-level issue](../running_psalm/issues/Trace.md).
|
||||
To see it, you can set the global `errorLevel` to 1, or invoke Psalm with
|
||||
`--show-info=true`, but both these solutions will probably result in a lot of
|
||||
output. Another solution is to selectively bump the error level of the issue,
|
||||
so that you only get one more error:
|
||||
|
||||
```xml
|
||||
<!-- psalm.xml -->
|
||||
<issueHandlers>
|
||||
<Trace errorLevel="error"/>
|
||||
</issueHandlers>
|
||||
```
|
||||
|
||||
### `@psalm-check-type`
|
||||
|
||||
@@ -596,7 +676,7 @@ class Foo
|
||||
}
|
||||
```
|
||||
When Psalm encounters variable property, it treats all properties in given class as potentially referenced.
|
||||
With `@psalm-ignore-variable-property` annotation, this reference is ignored.
|
||||
With `@psalm-ignore-variable-property` annotation, this reference is ignored.
|
||||
|
||||
While `PossiblyUnusedProperty` would be emitted in both cases, using `@psalm-ignore-variable-property`
|
||||
would allow [Psalter](../manipulating_code/fixing.md) to delete `Foo::$bar`.
|
||||
@@ -642,9 +722,9 @@ function (): Generator {
|
||||
```
|
||||
This annotation supports only generic types, meaning that e.g. `@psalm-yield string` would be ignored.
|
||||
|
||||
### `@psalm-api`
|
||||
### `@api`, `@psalm-api`
|
||||
|
||||
Used to tell Psalm that a class is used, even if no references to it can be
|
||||
Used to tell Psalm that a class or method is used, even if no references to it can be
|
||||
found. Unused issues will be suppressed.
|
||||
|
||||
For example, in frameworks, controllers are often invoked "magically" without
|
||||
@@ -657,6 +737,22 @@ any explicit references to them in your code. You should mark these classes with
|
||||
class UnreferencedClass {}
|
||||
```
|
||||
|
||||
### `@psalm-inheritors`
|
||||
|
||||
Used to tell Psalm that a class can only be extended by a certain subset of classes.
|
||||
|
||||
For example,
|
||||
```php
|
||||
<?php
|
||||
/**
|
||||
* @psalm-inheritors FooClass|BarClass
|
||||
*/
|
||||
class BaseClass {}
|
||||
class FooClass extends BaseClass {}
|
||||
class BarClass extends BaseClass {}
|
||||
class BazClass extends BaseClass {} // this is an error
|
||||
```
|
||||
|
||||
## Type Syntax
|
||||
|
||||
Psalm supports PHPDoc’s [type syntax](https://docs.phpdoc.org/latest/guide/guides/types.html), and also the [proposed PHPDoc PSR type syntax](https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md#appendix-a-types).
|
||||
|
||||
@@ -203,6 +203,17 @@ $options['verbose'] = isset($options['verbose']);
|
||||
handleOptions($options);
|
||||
```
|
||||
|
||||
`...` is a shorthand for `...<array-key, mixed>` you can use other array generic types to provide more information about the open shape.
|
||||
|
||||
```php
|
||||
// This is an open array
|
||||
/** @param array{someKey: string, ...} */
|
||||
// Which is the same as
|
||||
/** @param array{someKey: string, ...<array-key, mixed>} */
|
||||
// But it can be further locked down with a shape ...<TKey, TValue>
|
||||
/** @return array{someKey: string, ...<int, bool>} */
|
||||
```
|
||||
|
||||
## Callable arrays
|
||||
|
||||
An array holding a callable, like PHP's native `call_user_func()` and friends supports it:
|
||||
|
||||
@@ -46,7 +46,7 @@ Atomic types are the basic building block of all type information used in Psalm.
|
||||
* [`key-of<T>`](utility_types.md#key-oft)
|
||||
* [`value-of<T>`](utility_types.md#value-oft)
|
||||
* [`properties-of<T>`](utility_types.md#properties-oft)
|
||||
* [`class-string-map<T as Foo, T>`](utility_types.md#class-string-mapt-as-foo-t)
|
||||
* [`class-string-map<T of Foo, T>`](utility_types.md#class-string-mapt-as-foo-t)
|
||||
* [`T[K]`](utility_types.md#tk)
|
||||
* [Type aliases](utility_types.md#type-aliases)
|
||||
* [Variable templates](utility_types.md#variable-templates)
|
||||
|
||||
@@ -148,7 +148,7 @@ $b = asArray(new B);
|
||||
/** @psalm-trace $b */; // array{foo: string, bar: int, baz: float}
|
||||
```
|
||||
|
||||
## class-string-map<T as Foo, T>
|
||||
## class-string-map<T of Foo, T>
|
||||
|
||||
Used to indicate an array where each value is equal an instance of the class string contained in the key:
|
||||
|
||||
@@ -166,11 +166,11 @@ class Foo {}
|
||||
class Bar extends Foo {}
|
||||
|
||||
class A {
|
||||
/** @var class-string-map<T as Foo, T> */
|
||||
/** @var class-string-map<T of Foo, T> */
|
||||
private static array $map = [];
|
||||
|
||||
/**
|
||||
* @template U as Foo
|
||||
* @template U of Foo
|
||||
* @param class-string<U> $class
|
||||
* @return U
|
||||
*/
|
||||
@@ -191,7 +191,7 @@ $bar = A::get(Bar::class);
|
||||
/** @psalm-trace $bar */; // Bar
|
||||
```
|
||||
|
||||
If we had used an `array<class-string<Foo>, Foo>` instead of a `class-string-map<T as Foo, T>` in the above example, we would've gotten some false positive `InvalidReturnStatement` issues, caused by the lack of a type assertion inside the `isset`.
|
||||
If we had used an `array<class-string<Foo>, Foo>` instead of a `class-string-map<T of Foo, T>` in the above example, we would've gotten some false positive `InvalidReturnStatement` issues, caused by the lack of a type assertion inside the `isset`.
|
||||
On the other hand, when using `class-string-map`, Psalm assumes that the value obtained by using a key `class-string<T>` is always equal to `T`.
|
||||
|
||||
Unbounded templates can also be used for unrelated classes:
|
||||
@@ -250,8 +250,8 @@ Used to get the value corresponding to the specified key:
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @template T as array
|
||||
* @template TKey as string
|
||||
* @template T of array
|
||||
* @template TKey of string
|
||||
* @param T $arr
|
||||
* @param TKey $k
|
||||
* @return T[TKey]
|
||||
@@ -325,9 +325,9 @@ Variable templates allow directly using variables instead of template types, for
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @template TA as string
|
||||
* @template TB as string
|
||||
* @template TChoose as bool
|
||||
* @template TA of string
|
||||
* @template TB of string
|
||||
* @template TChoose of bool
|
||||
* @param TA $a
|
||||
* @param TB $b
|
||||
* @param TChoose $choose
|
||||
|
||||
@@ -90,6 +90,15 @@ Whether or not to use types as defined in docblocks. Defaults to `true`.
|
||||
```
|
||||
If not using all docblock types, you can still use docblock property types. Defaults to `false` (though only relevant if `useDocblockTypes` is `false`).
|
||||
|
||||
#### docblockPropertyTypesSealProperties
|
||||
|
||||
```xml
|
||||
<psalm
|
||||
docblockPropertyTypesSealProperties="[bool]"
|
||||
>
|
||||
```
|
||||
Whether using @property in class docblocks should imply @psalm-seal-properties. Defaults to `true`.
|
||||
|
||||
#### usePhpDocMethodsWithoutMagicCall
|
||||
|
||||
```xml
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
- [InaccessibleClassConstant](issues/InaccessibleClassConstant.md)
|
||||
- [InaccessibleMethod](issues/InaccessibleMethod.md)
|
||||
- [InaccessibleProperty](issues/InaccessibleProperty.md)
|
||||
- [InheritorViolation](issues/InheritorViolation.md)
|
||||
- [InterfaceInstantiation](issues/InterfaceInstantiation.md)
|
||||
- [InternalClass](issues/InternalClass.md)
|
||||
- [InternalMethod](issues/InternalMethod.md)
|
||||
@@ -284,6 +285,7 @@
|
||||
- [UnresolvableInclude](issues/UnresolvableInclude.md)
|
||||
- [UnsafeGenericInstantiation](issues/UnsafeGenericInstantiation.md)
|
||||
- [UnsafeInstantiation](issues/UnsafeInstantiation.md)
|
||||
- [UnsupportedPropertyReferenceUsage](issues/UnsupportedPropertyReferenceUsage.md)
|
||||
- [UnsupportedReferenceUsage](issues/UnsupportedReferenceUsage.md)
|
||||
- [UnusedBaselineEntry](issues/UnusedBaselineEntry.md)
|
||||
- [UnusedClass](issues/UnusedClass.md)
|
||||
|
||||
17
vendor/vimeo/psalm/docs/running_psalm/issues/InheritorViolation.md
vendored
Normal file
17
vendor/vimeo/psalm/docs/running_psalm/issues/InheritorViolation.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
# InheritorViolation
|
||||
|
||||
Emitted when a class/interface using `@psalm-inheritors` is extended/implemented
|
||||
by a class that does not fulfil it's requirements.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @psalm-inheritors FooClass|BarClass
|
||||
*/
|
||||
class BaseClass {}
|
||||
class BazClass extends BaseClass {}
|
||||
// InheritorViolation is emitted, as BaseClass can only be extended
|
||||
// by FooClass|BarClass, which is not the case
|
||||
$a = new BazClass();
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
# InvalidExtendClass
|
||||
|
||||
Emitted when attempting to extend a final class or a class annotated with `@final`.
|
||||
Emitted when attempting to extend a final class, a class annotated with `@final` or a class using @psalm-inheritors and not in the inheritor list
|
||||
|
||||
```php
|
||||
<?php
|
||||
@@ -15,4 +15,11 @@ class B extends A {}
|
||||
class DoctrineA {}
|
||||
|
||||
class DoctrineB extends DoctrineA {}
|
||||
```
|
||||
|
||||
/**
|
||||
* @psalm-inheritors A|B
|
||||
*/
|
||||
class C {}
|
||||
|
||||
class D extends C {}
|
||||
```
|
||||
@@ -35,6 +35,7 @@ function printName(string $name) {
|
||||
- Sanitize user-input by using functions such as `htmlentities` or use an allowlist.
|
||||
- Set all cookies to `HTTPOnly`.
|
||||
- Consider using Content Security Policy (CSP), to limit the risk of XSS vulnerabilities.
|
||||
- If user input itself is HTML, see [Sanitizing HTML User Input](../../security_analysis/avoiding_false_positives.md#sanitizing-html-user-input)
|
||||
|
||||
## Further resources
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ Passing `');alert('injection');//` as a `GET` param here would cause the `alert`
|
||||
- Sanitize user input by using functions such as `htmlentities` with the `ENT_QUOTES` flag or use an allowlist.
|
||||
- Set all cookies to `HTTPOnly`.
|
||||
- Consider using Content Security Policy (CSP), to limit the risk of XSS vulnerabilities.
|
||||
- If user input itself is HTML, see [Sanitizing HTML User Input](../../security_analysis/avoiding_false_positives.md#sanitizing-html-user-input)
|
||||
|
||||
## Further resources
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Trace
|
||||
|
||||
Not really an issue. Just reports type of the variable.
|
||||
Not really an issue. Just reports the type of a variable when using
|
||||
[`@psalm-trace`](../annotating_code/supported_annotations.md#psalm-trace).
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
40
vendor/vimeo/psalm/docs/running_psalm/issues/UnsupportedPropertyReferenceUsage.md
vendored
Normal file
40
vendor/vimeo/psalm/docs/running_psalm/issues/UnsupportedPropertyReferenceUsage.md
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# UnsupportedPropertyReferenceUsage
|
||||
|
||||
Psalm cannot guarantee the soundness of code that uses references to properties.
|
||||
|
||||
### Examples of Uncaught Errors
|
||||
|
||||
* Instance property assigned wrong type:
|
||||
```php
|
||||
<?php
|
||||
class A {
|
||||
public int $b = 0;
|
||||
}
|
||||
$a = new A();
|
||||
$b = &$a->b;
|
||||
$b = ''; // Fatal error
|
||||
```
|
||||
|
||||
* Static property assigned wrong type:
|
||||
```php
|
||||
<?php
|
||||
class A {
|
||||
public static int $b = 0;
|
||||
}
|
||||
$b = &A::$b;
|
||||
$b = ''; // Fatal error
|
||||
```
|
||||
|
||||
* Readonly property reassigned:
|
||||
```php
|
||||
<?php
|
||||
class A {
|
||||
public function __construct(
|
||||
public readonly int $b,
|
||||
) {
|
||||
}
|
||||
}
|
||||
$a = new A(0);
|
||||
$b = &$a->b;
|
||||
$b = 1; // Fatal error
|
||||
```
|
||||
@@ -26,7 +26,7 @@ function echoVar(string $str) : void {
|
||||
echoVar($_GET["text"]);
|
||||
```
|
||||
|
||||
## Conditional escaping tainted input
|
||||
## Conditionally escaping tainted input
|
||||
|
||||
A slightly modified version of the previous example is using a condition to determine whether the return value
|
||||
is considered secure. Only in case function argument `$escape` is true, the corresponding annotation
|
||||
@@ -50,6 +50,23 @@ echo processVar($_GET['text'], false); // detects tainted HTML
|
||||
echo processVar($_GET['text'], true); // considered secure
|
||||
```
|
||||
|
||||
## Sanitizing HTML user input
|
||||
|
||||
Whenever possible, applications should be designed to accept & store user input as discrete text fields, rather than blocks of HTML. This allows user input to be fully escaped via `htmlspecialchars` or `htmlentities`. In cases where HTML user input is required (e.g. rich text editors like [TinyMCE](https://www.tiny.cloud/)), a library designed specifically to filter out risky HTML is highly recommended. For example, [HTML Purifier](http://htmlpurifier.org/docs) could be used as follows:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @psalm-taint-escape html
|
||||
* @psalm-taint-escape has_quotes
|
||||
*/
|
||||
function sanitizeHTML($html){
|
||||
$purifier = new HTMLPurifier();
|
||||
return $purifier->purify($html);
|
||||
}
|
||||
```
|
||||
|
||||
## Specializing taints in functions
|
||||
|
||||
For functions, methods and classes you can use the `@psalm-taint-specialize` annotation.
|
||||
|
||||
@@ -169,6 +169,7 @@ class CodeLocation
|
||||
|
||||
$codebase = $project_analyzer->getCodebase();
|
||||
|
||||
/** @psalm-suppress ImpureMethodCall */
|
||||
$file_contents = $codebase->getFileContents($this->file_path);
|
||||
|
||||
$file_length = strlen($file_contents);
|
||||
|
||||
458
vendor/vimeo/psalm/src/Psalm/Codebase.php
vendored
458
vendor/vimeo/psalm/src/Psalm/Codebase.php
vendored
@@ -37,6 +37,8 @@ use Psalm\Internal\Codebase\Scanner;
|
||||
use Psalm\Internal\Codebase\TaintFlowGraph;
|
||||
use Psalm\Internal\DataFlow\TaintSink;
|
||||
use Psalm\Internal\DataFlow\TaintSource;
|
||||
use Psalm\Internal\LanguageServer\PHPMarkdownContent;
|
||||
use Psalm\Internal\LanguageServer\Reference;
|
||||
use Psalm\Internal\MethodIdentifier;
|
||||
use Psalm\Internal\Provider\ClassLikeStorageProvider;
|
||||
use Psalm\Internal\Provider\FileProvider;
|
||||
@@ -67,8 +69,10 @@ use ReflectionType;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function array_combine;
|
||||
use function array_merge;
|
||||
use function array_pop;
|
||||
use function array_reverse;
|
||||
use function array_values;
|
||||
use function count;
|
||||
use function dirname;
|
||||
use function error_log;
|
||||
@@ -82,6 +86,7 @@ use function krsort;
|
||||
use function ksort;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function str_replace;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function strrpos;
|
||||
@@ -390,15 +395,19 @@ final class Codebase
|
||||
/**
|
||||
* @param array<string> $candidate_files
|
||||
*/
|
||||
public function reloadFiles(ProjectAnalyzer $project_analyzer, array $candidate_files): void
|
||||
public function reloadFiles(ProjectAnalyzer $project_analyzer, array $candidate_files, bool $force = false): void
|
||||
{
|
||||
$this->loadAnalyzer();
|
||||
|
||||
if ($force) {
|
||||
FileReferenceProvider::clearCache();
|
||||
}
|
||||
|
||||
$this->file_reference_provider->loadReferenceCache(false);
|
||||
|
||||
FunctionLikeAnalyzer::clearCache();
|
||||
|
||||
if (!$this->statements_provider->parser_cache_provider) {
|
||||
if ($force || !$this->statements_provider->parser_cache_provider) {
|
||||
$diff_files = $candidate_files;
|
||||
} else {
|
||||
$diff_files = [];
|
||||
@@ -500,7 +509,6 @@ final class Codebase
|
||||
}
|
||||
}
|
||||
|
||||
/** @psalm-mutation-free */
|
||||
public function getFileContents(string $file_path): string
|
||||
{
|
||||
return $this->file_provider->getContents($file_path);
|
||||
@@ -593,6 +601,7 @@ final class Codebase
|
||||
*/
|
||||
public function findReferencesToProperty(string $property_id): array
|
||||
{
|
||||
/** @psalm-suppress PossiblyUndefinedIntArrayOffset */
|
||||
[$fq_class_name, $property_name] = explode('::', $property_id);
|
||||
|
||||
return $this->file_reference_provider->getClassPropertyLocations(
|
||||
@@ -970,7 +979,225 @@ final class Codebase
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{ type: string, description?: string|null}|null
|
||||
* Get Markup content from Reference
|
||||
*/
|
||||
public function getMarkupContentForSymbolByReference(
|
||||
Reference $reference
|
||||
): ?PHPMarkdownContent {
|
||||
//Direct Assignment
|
||||
if (is_numeric($reference->symbol[0])) {
|
||||
return new PHPMarkdownContent(
|
||||
preg_replace(
|
||||
'/^[^:]*:/',
|
||||
'',
|
||||
$reference->symbol,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//Class
|
||||
if (strpos($reference->symbol, '::')) {
|
||||
//Class Method
|
||||
if (strpos($reference->symbol, '()')) {
|
||||
$symbol = substr($reference->symbol, 0, -2);
|
||||
|
||||
/** @psalm-suppress ArgumentTypeCoercion */
|
||||
$method_id = new MethodIdentifier(...explode('::', $symbol));
|
||||
|
||||
$declaring_method_id = $this->methods->getDeclaringMethodId(
|
||||
$method_id,
|
||||
);
|
||||
|
||||
if (!$declaring_method_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$storage = $this->methods->getStorage($declaring_method_id);
|
||||
|
||||
return new PHPMarkdownContent(
|
||||
$storage->getHoverMarkdown(),
|
||||
"{$storage->defining_fqcln}::{$storage->cased_name}",
|
||||
$storage->description,
|
||||
);
|
||||
}
|
||||
|
||||
/** @psalm-suppress PossiblyUndefinedIntArrayOffset */
|
||||
[, $symbol_name] = explode('::', $reference->symbol);
|
||||
|
||||
//Class Property
|
||||
if (strpos($reference->symbol, '$') !== false) {
|
||||
$property_id = preg_replace('/^\\\\/', '', $reference->symbol);
|
||||
/** @psalm-suppress PossiblyUndefinedIntArrayOffset */
|
||||
[$fq_class_name, $property_name] = explode('::$', $property_id);
|
||||
$class_storage = $this->classlikes->getStorageFor($fq_class_name);
|
||||
|
||||
//Get Real Properties
|
||||
if (isset($class_storage->declaring_property_ids[$property_name])) {
|
||||
$declaring_property_class = $class_storage->declaring_property_ids[$property_name];
|
||||
$declaring_class_storage = $this->classlike_storage_provider->get($declaring_property_class);
|
||||
|
||||
if (isset($declaring_class_storage->properties[$property_name])) {
|
||||
$storage = $declaring_class_storage->properties[$property_name];
|
||||
return new PHPMarkdownContent(
|
||||
"{$storage->getInfo()} {$symbol_name}",
|
||||
$reference->symbol,
|
||||
$storage->description,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//Get Docblock properties
|
||||
if (isset($class_storage->pseudo_property_set_types['$'.$property_name])) {
|
||||
return new PHPMarkdownContent(
|
||||
'public '.
|
||||
(string) $class_storage->pseudo_property_set_types['$'.$property_name].' $'.$property_name,
|
||||
$reference->symbol,
|
||||
);
|
||||
}
|
||||
|
||||
//Get Docblock properties
|
||||
if (isset($class_storage->pseudo_property_get_types['$'.$property_name])) {
|
||||
return new PHPMarkdownContent(
|
||||
'public '.
|
||||
(string) $class_storage->pseudo_property_get_types['$'.$property_name].' $'.$property_name,
|
||||
$reference->symbol,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @psalm-suppress PossiblyUndefinedIntArrayOffset */
|
||||
[$fq_classlike_name, $const_name] = explode(
|
||||
'::',
|
||||
$reference->symbol,
|
||||
);
|
||||
|
||||
$class_constants = $this->classlikes->getConstantsForClass(
|
||||
$fq_classlike_name,
|
||||
ReflectionProperty::IS_PRIVATE,
|
||||
);
|
||||
|
||||
if (!isset($class_constants[$const_name])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Class Constant
|
||||
return new PHPMarkdownContent(
|
||||
$class_constants[$const_name]->getHoverMarkdown($const_name),
|
||||
$fq_classlike_name . '::' . $const_name,
|
||||
$class_constants[$const_name]->description,
|
||||
);
|
||||
}
|
||||
|
||||
//Procedural Function
|
||||
if (strpos($reference->symbol, '()')) {
|
||||
$function_id = strtolower(substr($reference->symbol, 0, -2));
|
||||
$file_storage = $this->file_storage_provider->get(
|
||||
$reference->file_path,
|
||||
);
|
||||
|
||||
if (isset($file_storage->functions[$function_id])) {
|
||||
$function_storage = $file_storage->functions[$function_id];
|
||||
|
||||
return new PHPMarkdownContent(
|
||||
$function_storage->getHoverMarkdown(),
|
||||
$function_id,
|
||||
$function_storage->description,
|
||||
);
|
||||
}
|
||||
|
||||
if (!$function_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$function = $this->functions->getStorage(null, $function_id);
|
||||
|
||||
return new PHPMarkdownContent(
|
||||
$function->getHoverMarkdown(),
|
||||
$function_id,
|
||||
$function->description,
|
||||
);
|
||||
}
|
||||
|
||||
//Procedural Variable
|
||||
if (strpos($reference->symbol, '$') === 0) {
|
||||
$type = VariableFetchAnalyzer::getGlobalType($reference->symbol, $this->analysis_php_version_id);
|
||||
if (!$type->isMixed()) {
|
||||
return new PHPMarkdownContent(
|
||||
(string) $type,
|
||||
$reference->symbol,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$storage = $this->classlike_storage_provider->get(
|
||||
$reference->symbol,
|
||||
);
|
||||
return new PHPMarkdownContent(
|
||||
($storage->abstract ? 'abstract ' : '') .
|
||||
'class ' .
|
||||
$storage->name,
|
||||
$storage->name,
|
||||
$storage->description,
|
||||
);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
//continue on as normal
|
||||
}
|
||||
|
||||
if (strpos($reference->symbol, '\\')) {
|
||||
$const_name_parts = explode('\\', $reference->symbol);
|
||||
$const_name = array_pop($const_name_parts);
|
||||
$namespace_name = implode('\\', $const_name_parts);
|
||||
|
||||
$namespace_constants = NamespaceAnalyzer::getConstantsForNamespace(
|
||||
$namespace_name,
|
||||
ReflectionProperty::IS_PUBLIC,
|
||||
);
|
||||
//Namespace Constant
|
||||
if (isset($namespace_constants[$const_name])) {
|
||||
$type = $namespace_constants[$const_name];
|
||||
return new PHPMarkdownContent(
|
||||
$reference->symbol . ' ' . $type,
|
||||
$reference->symbol,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$file_storage = $this->file_storage_provider->get(
|
||||
$reference->file_path,
|
||||
);
|
||||
// ?
|
||||
if (isset($file_storage->constants[$reference->symbol])) {
|
||||
return new PHPMarkdownContent(
|
||||
'const ' .
|
||||
$reference->symbol .
|
||||
' ' .
|
||||
$file_storage->constants[$reference->symbol],
|
||||
$reference->symbol,
|
||||
);
|
||||
}
|
||||
$type = ConstFetchAnalyzer::getGlobalConstType(
|
||||
$this,
|
||||
$reference->symbol,
|
||||
$reference->symbol,
|
||||
);
|
||||
|
||||
//Global Constant
|
||||
if ($type) {
|
||||
return new PHPMarkdownContent(
|
||||
'const ' . $reference->symbol . ' ' . $type,
|
||||
$reference->symbol,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new PHPMarkdownContent($reference->symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress PossiblyUnusedMethod
|
||||
* @deprecated will be removed in Psalm 6. use {@see Codebase::getSymbolLocationByReference()} instead
|
||||
*/
|
||||
public function getSymbolInformation(string $file_path, string $symbol): ?array
|
||||
{
|
||||
@@ -995,7 +1222,7 @@ final class Codebase
|
||||
$storage = $this->methods->getStorage($declaring_method_id);
|
||||
|
||||
return [
|
||||
'type' => '<?php ' . $storage->getSignature(true),
|
||||
'type' => '<?php ' . $storage->getCompletionSignature(),
|
||||
'description' => $storage->description,
|
||||
];
|
||||
}
|
||||
@@ -1036,7 +1263,7 @@ final class Codebase
|
||||
$function_storage = $file_storage->functions[$function_id];
|
||||
|
||||
return [
|
||||
'type' => '<?php ' . $function_storage->getSignature(true),
|
||||
'type' => '<?php ' . $function_storage->getCompletionSignature(),
|
||||
'description' => $function_storage->description,
|
||||
];
|
||||
}
|
||||
@@ -1047,7 +1274,7 @@ final class Codebase
|
||||
|
||||
$function = $this->functions->getStorage(null, $function_id);
|
||||
return [
|
||||
'type' => '<?php ' . $function->getSignature(true),
|
||||
'type' => '<?php ' . $function->getCompletionSignature(),
|
||||
'description' => $function->description,
|
||||
];
|
||||
}
|
||||
@@ -1100,6 +1327,10 @@ final class Codebase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress PossiblyUnusedMethod
|
||||
* @deprecated will be removed in Psalm 6. use {@see Codebase::getSymbolLocationByReference()} instead
|
||||
*/
|
||||
public function getSymbolLocation(string $file_path, string $symbol): ?CodeLocation
|
||||
{
|
||||
if (is_numeric($symbol[0])) {
|
||||
@@ -1182,11 +1413,127 @@ final class Codebase
|
||||
}
|
||||
}
|
||||
|
||||
public function getSymbolLocationByReference(Reference $reference): ?CodeLocation
|
||||
{
|
||||
if (is_numeric($reference->symbol[0])) {
|
||||
$symbol = preg_replace('/:.*/', '', $reference->symbol);
|
||||
$symbol_parts = explode('-', $symbol);
|
||||
|
||||
if (!isset($symbol_parts[0]) || !isset($symbol_parts[1])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$file_contents = $this->getFileContents($reference->file_path);
|
||||
|
||||
return new Raw(
|
||||
$file_contents,
|
||||
$reference->file_path,
|
||||
$this->config->shortenFileName($reference->file_path),
|
||||
(int) $symbol_parts[0],
|
||||
(int) $symbol_parts[1],
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
if (strpos($reference->symbol, '::')) {
|
||||
if (strpos($reference->symbol, '()')) {
|
||||
$symbol = substr($reference->symbol, 0, -2);
|
||||
|
||||
/** @psalm-suppress ArgumentTypeCoercion */
|
||||
$method_id = new MethodIdentifier(
|
||||
...explode('::', $symbol),
|
||||
);
|
||||
|
||||
$declaring_method_id = $this->methods->getDeclaringMethodId(
|
||||
$method_id,
|
||||
);
|
||||
|
||||
if (!$declaring_method_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$storage = $this->methods->getStorage($declaring_method_id);
|
||||
|
||||
return $storage->location;
|
||||
}
|
||||
|
||||
if (strpos($reference->symbol, '$') !== false) {
|
||||
$storage = $this->properties->getStorage(
|
||||
$reference->symbol,
|
||||
);
|
||||
|
||||
return $storage->location;
|
||||
}
|
||||
|
||||
/** @psalm-suppress PossiblyUndefinedIntArrayOffset */
|
||||
[$fq_classlike_name, $const_name] = explode(
|
||||
'::',
|
||||
$reference->symbol,
|
||||
);
|
||||
|
||||
$class_constants = $this->classlikes->getConstantsForClass(
|
||||
$fq_classlike_name,
|
||||
ReflectionProperty::IS_PRIVATE,
|
||||
);
|
||||
|
||||
if (!isset($class_constants[$const_name])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $class_constants[$const_name]->location;
|
||||
}
|
||||
|
||||
if (strpos($reference->symbol, '()')) {
|
||||
$file_storage = $this->file_storage_provider->get(
|
||||
$reference->file_path,
|
||||
);
|
||||
|
||||
$function_id = strtolower(substr($reference->symbol, 0, -2));
|
||||
|
||||
if (isset($file_storage->functions[$function_id])) {
|
||||
return $file_storage->functions[$function_id]->location;
|
||||
}
|
||||
|
||||
if (!$function_id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->functions->getStorage(null, $function_id)
|
||||
->location;
|
||||
}
|
||||
|
||||
return $this->classlike_storage_provider->get(
|
||||
$reference->symbol,
|
||||
)->location;
|
||||
} catch (UnexpectedValueException $e) {
|
||||
error_log($e->getMessage());
|
||||
|
||||
return null;
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress PossiblyUnusedMethod
|
||||
* @return array{0: string, 1: Range}|null
|
||||
*/
|
||||
public function getReferenceAtPosition(string $file_path, Position $position): ?array
|
||||
{
|
||||
$ref = $this->getReferenceAtPositionAsReference($file_path, $position);
|
||||
if ($ref === null) {
|
||||
return null;
|
||||
}
|
||||
return [$ref->symbol, $ref->range];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Reference from Position
|
||||
*/
|
||||
public function getReferenceAtPositionAsReference(
|
||||
string $file_path,
|
||||
Position $position
|
||||
): ?Reference {
|
||||
$is_open = $this->file_provider->isOpen($file_path);
|
||||
|
||||
if (!$is_open) {
|
||||
@@ -1197,33 +1544,37 @@ final class Codebase
|
||||
|
||||
$offset = $position->toOffset($file_contents);
|
||||
|
||||
[$reference_map, $type_map] = $this->analyzer->getMapsForFile($file_path);
|
||||
|
||||
$reference = null;
|
||||
|
||||
if (!$reference_map && !$type_map) {
|
||||
return null;
|
||||
}
|
||||
$reference_maps = $this->analyzer->getMapsForFile($file_path);
|
||||
|
||||
$reference_start_pos = null;
|
||||
$reference_end_pos = null;
|
||||
$symbol = null;
|
||||
|
||||
ksort($reference_map);
|
||||
foreach ($reference_maps as $reference_map) {
|
||||
ksort($reference_map);
|
||||
|
||||
foreach ($reference_map as $start_pos => [$end_pos, $possible_reference]) {
|
||||
if ($offset < $start_pos) {
|
||||
foreach ($reference_map as $start_pos => [$end_pos, $possible_reference]) {
|
||||
if ($offset < $start_pos) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($offset > $end_pos) {
|
||||
continue;
|
||||
}
|
||||
$reference_start_pos = $start_pos;
|
||||
$reference_end_pos = $end_pos;
|
||||
$symbol = $possible_reference;
|
||||
}
|
||||
|
||||
if ($symbol !== null &&
|
||||
$reference_start_pos !== null &&
|
||||
$reference_end_pos !== null
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($offset > $end_pos) {
|
||||
continue;
|
||||
}
|
||||
$reference_start_pos = $start_pos;
|
||||
$reference_end_pos = $end_pos;
|
||||
$reference = $possible_reference;
|
||||
}
|
||||
|
||||
if ($reference === null || $reference_start_pos === null || $reference_end_pos === null) {
|
||||
if ($symbol === null || $reference_start_pos === null || $reference_end_pos === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1232,7 +1583,7 @@ final class Codebase
|
||||
self::getPositionFromOffset($reference_end_pos, $file_contents),
|
||||
);
|
||||
|
||||
return [$reference, $range];
|
||||
return new Reference($file_path, $symbol, $range);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1399,6 +1750,7 @@ final class Codebase
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @psalm-suppress PossiblyUndefinedIntArrayOffset */
|
||||
$num_whitespace_bytes = preg_match('/\G\s+/', $file_contents, $matches, 0, $end_pos_excluding_whitespace)
|
||||
? strlen($matches[0])
|
||||
: 0;
|
||||
@@ -1487,8 +1839,11 @@ final class Codebase
|
||||
/**
|
||||
* @return list<CompletionItem>
|
||||
*/
|
||||
public function getCompletionItemsForClassishThing(string $type_string, string $gap): array
|
||||
{
|
||||
public function getCompletionItemsForClassishThing(
|
||||
string $type_string,
|
||||
string $gap,
|
||||
bool $snippets_supported = false
|
||||
): array {
|
||||
$completion_items = [];
|
||||
|
||||
$type = Type::parseString($type_string);
|
||||
@@ -1505,11 +1860,11 @@ final class Codebase
|
||||
$completion_item = new CompletionItem(
|
||||
$method_storage->cased_name,
|
||||
CompletionItemKind::METHOD,
|
||||
(string)$method_storage,
|
||||
$method_storage->getCompletionSignature(),
|
||||
$method_storage->description,
|
||||
(string)$method_storage->visibility,
|
||||
$method_storage->cased_name,
|
||||
$method_storage->cased_name . (count($method_storage->params) !== 0 ? '($0)' : '()'),
|
||||
$method_storage->cased_name,
|
||||
null,
|
||||
null,
|
||||
new Command('Trigger parameter hints', 'editor.action.triggerParameterHints'),
|
||||
@@ -1517,12 +1872,47 @@ final class Codebase
|
||||
2,
|
||||
);
|
||||
|
||||
$completion_item->insertTextFormat = InsertTextFormat::SNIPPET;
|
||||
if ($snippets_supported && count($method_storage->params) > 0) {
|
||||
$completion_item->insertText .= '($0)';
|
||||
$completion_item->insertTextFormat =
|
||||
InsertTextFormat::SNIPPET;
|
||||
} else {
|
||||
$completion_item->insertText .= '()';
|
||||
}
|
||||
|
||||
$completion_items[] = $completion_item;
|
||||
}
|
||||
}
|
||||
|
||||
$pseudo_property_types = [];
|
||||
foreach ($class_storage->pseudo_property_get_types as $property_name => $type) {
|
||||
$pseudo_property_types[$property_name] = new CompletionItem(
|
||||
str_replace('$', '', $property_name),
|
||||
CompletionItemKind::PROPERTY,
|
||||
$type->__toString(),
|
||||
null,
|
||||
'1', //sort text
|
||||
str_replace('$', '', $property_name),
|
||||
($gap === '::' ? '$' : '') .
|
||||
str_replace('$', '', $property_name),
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($class_storage->pseudo_property_set_types as $property_name => $type) {
|
||||
$pseudo_property_types[$property_name] = new CompletionItem(
|
||||
str_replace('$', '', $property_name),
|
||||
CompletionItemKind::PROPERTY,
|
||||
$type->__toString(),
|
||||
null,
|
||||
'1',
|
||||
str_replace('$', '', $property_name),
|
||||
($gap === '::' ? '$' : '') .
|
||||
str_replace('$', '', $property_name),
|
||||
);
|
||||
}
|
||||
|
||||
$completion_items = array_merge($completion_items, array_values($pseudo_property_types));
|
||||
|
||||
foreach ($class_storage->declaring_property_ids as $property_name => $declaring_class) {
|
||||
$property_storage = $this->properties->getStorage(
|
||||
$declaring_class . '::$' . $property_name,
|
||||
@@ -1715,7 +2105,7 @@ final class Codebase
|
||||
$completion_items[] = new CompletionItem(
|
||||
$function_name,
|
||||
CompletionItemKind::FUNCTION,
|
||||
$function->getSignature(false),
|
||||
$function->getCompletionSignature(),
|
||||
$function->description,
|
||||
null,
|
||||
$function_name,
|
||||
@@ -1832,9 +2222,9 @@ final class Codebase
|
||||
);
|
||||
}
|
||||
|
||||
public function addTemporaryFileChanges(string $file_path, string $new_content): void
|
||||
public function addTemporaryFileChanges(string $file_path, string $new_content, ?int $version = null): void
|
||||
{
|
||||
$this->file_provider->addTemporaryFileChanges($file_path, $new_content);
|
||||
$this->file_provider->addTemporaryFileChanges($file_path, $new_content, $version);
|
||||
}
|
||||
|
||||
public function removeTemporaryFileChanges(string $file_path): void
|
||||
|
||||
11
vendor/vimeo/psalm/src/Psalm/Config.php
vendored
11
vendor/vimeo/psalm/src/Psalm/Config.php
vendored
@@ -194,6 +194,13 @@ class Config
|
||||
*/
|
||||
public $use_docblock_property_types = false;
|
||||
|
||||
/**
|
||||
* Whether using property annotations in docblocks should implicitly seal properties
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $docblock_property_types_seal_properties = true;
|
||||
|
||||
/**
|
||||
* Whether or not to throw an exception on first error
|
||||
*
|
||||
@@ -1049,6 +1056,7 @@ class Config
|
||||
$booleanAttributes = [
|
||||
'useDocblockTypes' => 'use_docblock_types',
|
||||
'useDocblockPropertyTypes' => 'use_docblock_property_types',
|
||||
'docblockPropertyTypesSealProperties' => 'docblock_property_types_seal_properties',
|
||||
'throwExceptionOnError' => 'throw_exception',
|
||||
'hideExternalErrors' => 'hide_external_errors',
|
||||
'hideAllErrorsExceptPassedFiles' => 'hide_all_errors_except_passed_files',
|
||||
@@ -1727,7 +1735,8 @@ class Config
|
||||
|
||||
public function reportIssueInFile(string $issue_type, string $file_path): bool
|
||||
{
|
||||
if (($this->show_mixed_issues === false || $this->level > 2)
|
||||
if ((($this->level < 3 && $this->show_mixed_issues === false)
|
||||
|| ($this->level > 2 && $this->show_mixed_issues !== true))
|
||||
&& in_array($issue_type, self::MIXED_ISSUES, true)
|
||||
) {
|
||||
return false;
|
||||
|
||||
@@ -122,6 +122,7 @@ class FileFilter
|
||||
$declare_strict_types = (bool) ($directory['useStrictTypes'] ?? false);
|
||||
|
||||
if ($directory_path[0] === '/' && DIRECTORY_SEPARATOR === '/') {
|
||||
/** @var non-empty-string */
|
||||
$prospective_directory_path = $directory_path;
|
||||
} else {
|
||||
$prospective_directory_path = $base_dir . DIRECTORY_SEPARATOR . $directory_path;
|
||||
@@ -238,6 +239,7 @@ class FileFilter
|
||||
$file_path = (string) ($file['name'] ?? '');
|
||||
|
||||
if ($file_path[0] === '/' && DIRECTORY_SEPARATOR === '/') {
|
||||
/** @var non-empty-string */
|
||||
$prospective_file_path = $file_path;
|
||||
} else {
|
||||
$prospective_file_path = $base_dir . DIRECTORY_SEPARATOR . $file_path;
|
||||
|
||||
3
vendor/vimeo/psalm/src/Psalm/DocComment.php
vendored
3
vendor/vimeo/psalm/src/Psalm/DocComment.php
vendored
@@ -24,6 +24,7 @@ final class DocComment
|
||||
'assert', 'assert-if-true', 'assert-if-false', 'suppress',
|
||||
'ignore-nullable-return', 'override-property-visibility',
|
||||
'override-method-visibility', 'seal-properties', 'seal-methods',
|
||||
'no-seal-properties', 'no-seal-methods',
|
||||
'ignore-falsable-return', 'variadic', 'pure',
|
||||
'ignore-variable-method', 'ignore-variable-property', 'internal',
|
||||
'taint-sink', 'taint-source', 'assert-untainted', 'scope-this',
|
||||
@@ -33,7 +34,7 @@ final class DocComment
|
||||
'taint-unescape', 'self-out', 'consistent-constructor', 'stub-override',
|
||||
'require-extends', 'require-implements', 'param-out', 'ignore-var',
|
||||
'consistent-templates', 'if-this-is', 'this-out', 'check-type', 'check-type-exact',
|
||||
'api',
|
||||
'api', 'inheritors',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -118,7 +118,7 @@ final class ErrorBaseline
|
||||
|
||||
foreach ($codeSamples as $codeSample) {
|
||||
$files[$fileName][$issueType]['o'] += 1;
|
||||
$files[$fileName][$issueType]['s'][] = trim($codeSample->textContent);
|
||||
$files[$fileName][$issueType]['s'][] = str_replace("\r\n", "\n", trim($codeSample->textContent));
|
||||
}
|
||||
|
||||
// TODO: Remove in Psalm 6
|
||||
|
||||
@@ -362,16 +362,6 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->leftover_stmts) {
|
||||
(new StatementsAnalyzer(
|
||||
$this,
|
||||
new NodeDataProvider(),
|
||||
))->analyze(
|
||||
$this->leftover_stmts,
|
||||
$class_context,
|
||||
);
|
||||
}
|
||||
|
||||
if (!$storage->abstract) {
|
||||
foreach ($storage->declaring_method_ids as $declaring_method_id) {
|
||||
$method_storage = $codebase->methods->getStorage($declaring_method_id);
|
||||
@@ -712,7 +702,7 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
new OverriddenPropertyAccess(
|
||||
'Property ' . $fq_class_name . '::$' . $property_name
|
||||
. ' has different access level than '
|
||||
. $storage->name . '::$' . $property_name,
|
||||
. $guide_class_name . '::$' . $property_name,
|
||||
$property_storage->location,
|
||||
),
|
||||
);
|
||||
@@ -1781,8 +1771,6 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
$method_context = clone $class_context;
|
||||
|
||||
foreach ($method_context->vars_in_scope as $context_var_id => $context_type) {
|
||||
$method_context->vars_in_scope[$context_var_id] = $context_type;
|
||||
|
||||
if ($context_type->from_property && $stmt->name->name !== '__construct') {
|
||||
$method_context->vars_in_scope[$context_var_id] =
|
||||
$method_context->vars_in_scope[$context_var_id]->setProperties(['initialized' => true]);
|
||||
|
||||
@@ -14,6 +14,7 @@ use Psalm\Internal\Type\Comparator\UnionTypeComparator;
|
||||
use Psalm\Internal\Type\TemplateResult;
|
||||
use Psalm\Internal\Type\TemplateStandinTypeReplacer;
|
||||
use Psalm\Issue\InaccessibleProperty;
|
||||
use Psalm\Issue\InheritorViolation;
|
||||
use Psalm\Issue\InvalidClass;
|
||||
use Psalm\Issue\InvalidTemplateParam;
|
||||
use Psalm\Issue\MissingDependency;
|
||||
@@ -28,6 +29,7 @@ use Psalm\Plugin\EventHandler\Event\AfterClassLikeExistenceCheckEvent;
|
||||
use Psalm\StatementsSource;
|
||||
use Psalm\Storage\ClassLikeStorage;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TNamedObject;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
use Psalm\Type\Union;
|
||||
use UnexpectedValueException;
|
||||
@@ -92,11 +94,6 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer
|
||||
*/
|
||||
protected ?string $parent_fq_class_name = null;
|
||||
|
||||
/**
|
||||
* @var PhpParser\Node\Stmt[]
|
||||
*/
|
||||
protected array $leftover_stmts = [];
|
||||
|
||||
protected ClassLikeStorage $storage;
|
||||
|
||||
public function __construct(PhpParser\Node\Stmt\ClassLike $class, SourceAnalyzer $source, string $fq_class_name)
|
||||
@@ -336,6 +333,23 @@ abstract class ClassLikeAnalyzer extends SourceAnalyzer
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$classUnion = new Union([new TNamedObject($fq_class_name)]);
|
||||
foreach ($class_storage->parent_classes + $class_storage->direct_class_interfaces as $parent_class) {
|
||||
$parent_storage = $codebase->classlikes->getStorageFor($parent_class);
|
||||
if ($parent_storage && $parent_storage->inheritors) {
|
||||
if (!UnionTypeComparator::isContainedBy($codebase, $classUnion, $parent_storage->inheritors)) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new InheritorViolation(
|
||||
'Class ' . $fq_class_name . ' is not an allowed inheritor of parent class ' . $parent_class,
|
||||
$code_location,
|
||||
),
|
||||
$suppressed_issues,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($class_storage->invalid_dependencies as $dependency_class_name => $_) {
|
||||
// if the implemented/extended class is stubbed, it may not yet have
|
||||
// been hydrated
|
||||
|
||||
@@ -72,6 +72,7 @@ use function count;
|
||||
use function end;
|
||||
use function in_array;
|
||||
use function is_string;
|
||||
use function krsort;
|
||||
use function mb_strpos;
|
||||
use function md5;
|
||||
use function microtime;
|
||||
@@ -80,6 +81,8 @@ use function strpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
|
||||
use const SORT_NUMERIC;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @template-covariant TFunction as Closure|Function_|ClassMethod|ArrowFunction
|
||||
@@ -721,7 +724,10 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
||||
if ($expected_exception === $possibly_thrown_exception
|
||||
|| (
|
||||
$codebase->classOrInterfaceExists($possibly_thrown_exception)
|
||||
&& $codebase->classExtendsOrImplements($possibly_thrown_exception, $expected_exception)
|
||||
&& (
|
||||
$codebase->interfaceExtends($possibly_thrown_exception, $expected_exception)
|
||||
|| $codebase->classExtendsOrImplements($possibly_thrown_exception, $expected_exception)
|
||||
)
|
||||
)
|
||||
) {
|
||||
$is_expected = true;
|
||||
@@ -870,96 +876,55 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
||||
): void {
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
$unused_params = [];
|
||||
$unused_params = $this->detectUnusedParameters($statements_analyzer, $storage, $context);
|
||||
|
||||
foreach ($statements_analyzer->getUnusedVarLocations() as [$var_name, $original_location]) {
|
||||
if (!array_key_exists(substr($var_name, 1), $storage->param_lookup)) {
|
||||
continue;
|
||||
}
|
||||
if (!$storage instanceof MethodStorage
|
||||
|| !$storage->cased_name
|
||||
|| $storage->visibility === ClassLikeAnalyzer::VISIBILITY_PRIVATE
|
||||
) {
|
||||
$last_unused_argument_position = $this->detectPreviousUnusedArgumentPosition(
|
||||
$storage,
|
||||
count($storage->params) - 1,
|
||||
);
|
||||
|
||||
if (strpos($var_name, '$_') === 0 || (strpos($var_name, '$unused') === 0 && $var_name !== '$unused')) {
|
||||
continue;
|
||||
}
|
||||
// Sort parameters in reverse order so that we can start from the end of parameters
|
||||
krsort($unused_params, SORT_NUMERIC);
|
||||
|
||||
$position = array_search(substr($var_name, 1), array_keys($storage->param_lookup), true);
|
||||
foreach ($unused_params as $unused_param_position => $unused_param_code_location) {
|
||||
$unused_param_var_name = $storage->params[$unused_param_position]->name;
|
||||
$unused_param_message = 'Param ' . $unused_param_var_name . ' is never referenced in this method';
|
||||
|
||||
if ($position === false) {
|
||||
throw new UnexpectedValueException('$position should not be false here');
|
||||
}
|
||||
// Remove the key as we already report the issue
|
||||
unset($unused_params[$unused_param_position]);
|
||||
|
||||
if ($storage->params[$position]->promoted_property) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$did_match_param = false;
|
||||
|
||||
foreach ($this->function->params as $param) {
|
||||
if ($param->var->getAttribute('endFilePos') === $original_location->raw_file_end) {
|
||||
$did_match_param = true;
|
||||
// Do not report unused required parameters
|
||||
if ($unused_param_position !== $last_unused_argument_position) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$did_match_param) {
|
||||
continue;
|
||||
}
|
||||
$last_unused_argument_position = $this->detectPreviousUnusedArgumentPosition(
|
||||
$storage,
|
||||
$unused_param_position - 1,
|
||||
);
|
||||
|
||||
$assignment_node = DataFlowNode::getForAssignment($var_name, $original_location);
|
||||
|
||||
if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph
|
||||
&& $statements_analyzer->data_flow_graph->isVariableUsed($assignment_node)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$storage instanceof MethodStorage
|
||||
|| !$storage->cased_name
|
||||
|| $storage->visibility === ClassLikeAnalyzer::VISIBILITY_PRIVATE
|
||||
) {
|
||||
if ($this instanceof ClosureAnalyzer) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new UnusedClosureParam(
|
||||
'Param ' . $var_name . ' is never referenced in this method',
|
||||
$original_location,
|
||||
$unused_param_message,
|
||||
$unused_param_code_location,
|
||||
),
|
||||
$this->getSuppressedIssues(),
|
||||
);
|
||||
} else {
|
||||
IssueBuffer::maybeAdd(
|
||||
new UnusedParam(
|
||||
'Param ' . $var_name . ' is never referenced in this method',
|
||||
$original_location,
|
||||
),
|
||||
$this->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$fq_class_name = (string)$context->self;
|
||||
|
||||
$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
$method_name_lc = strtolower($storage->cased_name);
|
||||
|
||||
if ($storage->abstract) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($class_storage->overridden_method_ids[$method_name_lc])) {
|
||||
$parent_method_id = end($class_storage->overridden_method_ids[$method_name_lc]);
|
||||
|
||||
if ($parent_method_id) {
|
||||
$parent_method_storage = $codebase->methods->getStorage($parent_method_id);
|
||||
|
||||
// if the parent method has a param at that position and isn't abstract
|
||||
if (!$parent_method_storage->abstract
|
||||
&& isset($parent_method_storage->params[$position])
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$unused_params[$position] = $original_location;
|
||||
IssueBuffer::maybeAdd(
|
||||
new UnusedParam(
|
||||
$unused_param_message,
|
||||
$unused_param_code_location,
|
||||
),
|
||||
$this->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2076,4 +2041,120 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer
|
||||
$overridden_method_ids,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int,CodeLocation>
|
||||
*/
|
||||
private function detectUnusedParameters(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
FunctionLikeStorage $storage,
|
||||
Context $context
|
||||
): array {
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
$unused_params = [];
|
||||
|
||||
foreach ($statements_analyzer->getUnusedVarLocations() as [$var_name, $original_location]) {
|
||||
if (!array_key_exists(substr($var_name, 1), $storage->param_lookup)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isIgnoredForUnusedParam($var_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$position = array_search(substr($var_name, 1), array_keys($storage->param_lookup), true);
|
||||
|
||||
if ($position === false) {
|
||||
throw new UnexpectedValueException('$position should not be false here');
|
||||
}
|
||||
|
||||
if ($storage->params[$position]->promoted_property) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$did_match_param = false;
|
||||
|
||||
foreach ($this->function->params as $param) {
|
||||
if ($param->var->getAttribute('endFilePos') === $original_location->raw_file_end) {
|
||||
$did_match_param = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$did_match_param) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$assignment_node = DataFlowNode::getForAssignment($var_name, $original_location);
|
||||
|
||||
if ($statements_analyzer->data_flow_graph instanceof VariableUseGraph
|
||||
&& $statements_analyzer->data_flow_graph->isVariableUsed($assignment_node)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$storage instanceof MethodStorage
|
||||
|| !$storage->cased_name
|
||||
|| $storage->visibility === ClassLikeAnalyzer::VISIBILITY_PRIVATE
|
||||
) {
|
||||
$unused_params[$position] = $original_location;
|
||||
continue;
|
||||
}
|
||||
|
||||
$fq_class_name = (string)$context->self;
|
||||
|
||||
$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
$method_name_lc = strtolower($storage->cased_name);
|
||||
|
||||
if ($storage->abstract) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($class_storage->overridden_method_ids[$method_name_lc])) {
|
||||
$parent_method_id = end($class_storage->overridden_method_ids[$method_name_lc]);
|
||||
|
||||
if ($parent_method_id) {
|
||||
$parent_method_storage = $codebase->methods->getStorage($parent_method_id);
|
||||
|
||||
// if the parent method has a param at that position and isn't abstract
|
||||
if (!$parent_method_storage->abstract
|
||||
&& isset($parent_method_storage->params[$position])
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$unused_params[$position] = $original_location;
|
||||
}
|
||||
|
||||
return $unused_params;
|
||||
}
|
||||
|
||||
private function detectPreviousUnusedArgumentPosition(FunctionLikeStorage $function, int $position): int
|
||||
{
|
||||
$params = $function->params;
|
||||
krsort($params, SORT_NUMERIC);
|
||||
|
||||
foreach ($params as $index => $param) {
|
||||
if ($index > $position) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isIgnoredForUnusedParam($param->name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $index;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function isIgnoredForUnusedParam(string $var_name): bool
|
||||
{
|
||||
return strpos($var_name, '$_') === 0 || (strpos($var_name, '$unused') === 0 && $var_name !== '$unused');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use UnexpectedValueException;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function implode;
|
||||
use function is_string;
|
||||
use function preg_replace;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
@@ -244,7 +245,7 @@ class NamespaceAnalyzer extends SourceAnalyzer
|
||||
while (($pos = strpos($identifier, "\\")) !== false) {
|
||||
if ($pos > 0) {
|
||||
$part = substr($identifier, 0, $pos);
|
||||
assert($part !== "");
|
||||
assert(is_string($part) && $part !== "");
|
||||
$parts[] = $part;
|
||||
}
|
||||
$parts[] = "\\";
|
||||
@@ -253,13 +254,13 @@ class NamespaceAnalyzer extends SourceAnalyzer
|
||||
if (($pos = strpos($identifier, "::")) !== false) {
|
||||
if ($pos > 0) {
|
||||
$part = substr($identifier, 0, $pos);
|
||||
assert($part !== "");
|
||||
assert(is_string($part) && $part !== "");
|
||||
$parts[] = $part;
|
||||
}
|
||||
$parts[] = "::";
|
||||
$identifier = substr($identifier, $pos + 2);
|
||||
}
|
||||
if ($identifier !== "") {
|
||||
if ($identifier !== "" && $identifier !== false) {
|
||||
$parts[] = $identifier;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace Psalm\Internal\Analyzer;
|
||||
|
||||
use Amp\Loop;
|
||||
use Fidry\CpuCoreCounter\CpuCoreCounter;
|
||||
use Fidry\CpuCoreCounter\NumberOfCpuCoreNotFound;
|
||||
use InvalidArgumentException;
|
||||
@@ -15,8 +14,6 @@ use Psalm\FileManipulation;
|
||||
use Psalm\Internal\Codebase\TaintFlowGraph;
|
||||
use Psalm\Internal\FileManipulation\FileManipulationBuffer;
|
||||
use Psalm\Internal\LanguageServer\LanguageServer;
|
||||
use Psalm\Internal\LanguageServer\ProtocolStreamReader;
|
||||
use Psalm\Internal\LanguageServer\ProtocolStreamWriter;
|
||||
use Psalm\Internal\MethodIdentifier;
|
||||
use Psalm\Internal\Provider\ClassLikeStorageProvider;
|
||||
use Psalm\Internal\Provider\FileProvider;
|
||||
@@ -65,7 +62,6 @@ use function array_map;
|
||||
use function array_merge;
|
||||
use function array_shift;
|
||||
use function clearstatcache;
|
||||
use function cli_set_process_title;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function dirname;
|
||||
@@ -82,14 +78,9 @@ use function is_file;
|
||||
use function microtime;
|
||||
use function mkdir;
|
||||
use function number_format;
|
||||
use function pcntl_fork;
|
||||
use function preg_match;
|
||||
use function rename;
|
||||
use function sprintf;
|
||||
use function stream_set_blocking;
|
||||
use function stream_socket_accept;
|
||||
use function stream_socket_client;
|
||||
use function stream_socket_server;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
@@ -102,8 +93,6 @@ use const PHP_OS;
|
||||
use const PHP_VERSION;
|
||||
use const PSALM_VERSION;
|
||||
use const STDERR;
|
||||
use const STDIN;
|
||||
use const STDOUT;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -211,16 +200,6 @@ class ProjectAnalyzer
|
||||
UnnecessaryVarAnnotation::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* When this is true, the language server will send the diagnostic code with a help link.
|
||||
*/
|
||||
public bool $language_server_use_extended_diagnostic_codes = false;
|
||||
|
||||
/**
|
||||
* If this is true then the language server will send log messages to the client with additional information.
|
||||
*/
|
||||
public bool $language_server_verbose = false;
|
||||
|
||||
/**
|
||||
* @param array<ReportOptions> $generated_report_options
|
||||
*/
|
||||
@@ -230,12 +209,21 @@ class ProjectAnalyzer
|
||||
?ReportOptions $stdout_report_options = null,
|
||||
array $generated_report_options = [],
|
||||
int $threads = 1,
|
||||
?Progress $progress = null
|
||||
?Progress $progress = null,
|
||||
?Codebase $codebase = null
|
||||
) {
|
||||
if ($progress === null) {
|
||||
$progress = new VoidProgress();
|
||||
}
|
||||
|
||||
if ($codebase === null) {
|
||||
$codebase = new Codebase(
|
||||
$config,
|
||||
$providers,
|
||||
$progress,
|
||||
);
|
||||
}
|
||||
|
||||
$this->parser_cache_provider = $providers->parser_cache_provider;
|
||||
$this->project_cache_provider = $providers->project_cache_provider;
|
||||
$this->file_provider = $providers->file_provider;
|
||||
@@ -248,11 +236,7 @@ class ProjectAnalyzer
|
||||
|
||||
$this->clearCacheDirectoryIfConfigOrComposerLockfileChanged();
|
||||
|
||||
$this->codebase = new Codebase(
|
||||
$config,
|
||||
$providers,
|
||||
$progress,
|
||||
);
|
||||
$this->codebase = $codebase;
|
||||
|
||||
$this->stdout_report_options = $stdout_report_options;
|
||||
$this->generated_report_options = $generated_report_options;
|
||||
@@ -394,10 +378,12 @@ class ProjectAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
public function server(?string $address = '127.0.0.1:12345', bool $socket_server_mode = false): void
|
||||
public function serverMode(LanguageServer $server): void
|
||||
{
|
||||
$server->logInfo("Initializing: Visiting Autoload Files...");
|
||||
$this->visitAutoloadFiles();
|
||||
$this->codebase->diff_methods = true;
|
||||
$server->logInfo("Initializing: Loading Reference Cache...");
|
||||
$this->file_reference_provider->loadReferenceCache();
|
||||
$this->codebase->enterServerMode();
|
||||
|
||||
@@ -418,103 +404,12 @@ class ProjectAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
$server->logInfo("Initializing: Initialize Plugins...");
|
||||
$this->config->initializePlugins($this);
|
||||
|
||||
foreach ($this->config->getProjectDirectories() as $dir_name) {
|
||||
$this->checkDirWithConfig($dir_name, $this->config);
|
||||
}
|
||||
|
||||
@cli_set_process_title('Psalm ' . PSALM_VERSION . ' - PHP Language Server');
|
||||
|
||||
if (!$socket_server_mode && $address) {
|
||||
// Connect to a TCP server
|
||||
$socket = stream_socket_client('tcp://' . $address, $errno, $errstr);
|
||||
if ($socket === false) {
|
||||
fwrite(STDERR, "Could not connect to language client. Error $errno\n$errstr");
|
||||
exit(1);
|
||||
}
|
||||
stream_set_blocking($socket, false);
|
||||
new LanguageServer(
|
||||
new ProtocolStreamReader($socket),
|
||||
new ProtocolStreamWriter($socket),
|
||||
$this,
|
||||
);
|
||||
Loop::run();
|
||||
} elseif ($socket_server_mode && $address) {
|
||||
// Run a TCP Server
|
||||
$tcpServer = stream_socket_server('tcp://' . $address, $errno, $errstr);
|
||||
if ($tcpServer === false) {
|
||||
fwrite(STDERR, "Could not listen on $address. Error $errno\n$errstr");
|
||||
exit(1);
|
||||
}
|
||||
fwrite(STDOUT, "Server listening on $address\n");
|
||||
|
||||
$fork_available = true;
|
||||
if (!extension_loaded('pcntl')) {
|
||||
fwrite(STDERR, "PCNTL is not available. Only a single connection will be accepted\n");
|
||||
$fork_available = false;
|
||||
}
|
||||
|
||||
$disabled_functions = array_map('trim', explode(',', ini_get('disable_functions')));
|
||||
if (in_array('pcntl_fork', $disabled_functions)) {
|
||||
fwrite(
|
||||
STDERR,
|
||||
"pcntl_fork() is disabled by php configuration (disable_functions directive)."
|
||||
. " Only a single connection will be accepted\n",
|
||||
);
|
||||
$fork_available = false;
|
||||
}
|
||||
|
||||
while ($socket = stream_socket_accept($tcpServer, -1)) {
|
||||
fwrite(STDOUT, "Connection accepted\n");
|
||||
stream_set_blocking($socket, false);
|
||||
if ($fork_available) {
|
||||
// If PCNTL is available, fork a child process for the connection
|
||||
// An exit notification will only terminate the child process
|
||||
$pid = pcntl_fork();
|
||||
if ($pid === -1) {
|
||||
fwrite(STDERR, "Could not fork\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ($pid === 0) {
|
||||
// Child process
|
||||
$reader = new ProtocolStreamReader($socket);
|
||||
$reader->on(
|
||||
'close',
|
||||
static function (): void {
|
||||
fwrite(STDOUT, "Connection closed\n");
|
||||
},
|
||||
);
|
||||
new LanguageServer(
|
||||
$reader,
|
||||
new ProtocolStreamWriter($socket),
|
||||
$this,
|
||||
);
|
||||
// Just for safety
|
||||
exit(0);
|
||||
}
|
||||
} else {
|
||||
// If PCNTL is not available, we only accept one connection.
|
||||
// An exit notification will terminate the server
|
||||
new LanguageServer(
|
||||
new ProtocolStreamReader($socket),
|
||||
new ProtocolStreamWriter($socket),
|
||||
$this,
|
||||
);
|
||||
Loop::run();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Use STDIO
|
||||
stream_set_blocking(STDIN, false);
|
||||
new LanguageServer(
|
||||
new ProtocolStreamReader(STDIN),
|
||||
new ProtocolStreamWriter(STDOUT),
|
||||
$this,
|
||||
);
|
||||
Loop::run();
|
||||
}
|
||||
}
|
||||
|
||||
/** @psalm-mutation-free */
|
||||
@@ -1244,6 +1139,11 @@ class ProjectAnalyzer
|
||||
return $this->file_provider->fileExists($file_path);
|
||||
}
|
||||
|
||||
public function isDirectory(string $file_path): bool
|
||||
{
|
||||
return $this->file_provider->isDirectory($file_path);
|
||||
}
|
||||
|
||||
public function alterCodeAfterCompletion(
|
||||
bool $dry_run = false,
|
||||
bool $safe_types = false
|
||||
|
||||
@@ -42,6 +42,7 @@ use Psalm\Type;
|
||||
use Psalm\Type\Atomic;
|
||||
use Psalm\Type\Atomic\Scalar;
|
||||
use Psalm\Type\Atomic\TArray;
|
||||
use Psalm\Type\Atomic\TCallableObject;
|
||||
use Psalm\Type\Atomic\TFalse;
|
||||
use Psalm\Type\Atomic\TGenericObject;
|
||||
use Psalm\Type\Atomic\TIterable;
|
||||
@@ -190,7 +191,7 @@ class ForeachAnalyzer
|
||||
&& $type_location
|
||||
&& isset($context->vars_in_scope[$var_comment->var_id])
|
||||
&& $context->vars_in_scope[$var_comment->var_id]->getId() === $comment_type->getId()
|
||||
&& !$comment_type->isMixed()
|
||||
&& !$comment_type->isMixed(true)
|
||||
) {
|
||||
$project_analyzer = $statements_analyzer->getProjectAnalyzer();
|
||||
|
||||
@@ -266,10 +267,6 @@ class ForeachAnalyzer
|
||||
|
||||
$foreach_context = clone $context;
|
||||
|
||||
foreach ($foreach_context->vars_in_scope as $context_var_id => $context_type) {
|
||||
$foreach_context->vars_in_scope[$context_var_id] = $context_type;
|
||||
}
|
||||
|
||||
if ($var_id && $foreach_context->hasVariable($var_id)) {
|
||||
// refine the type of the array variable we iterate over
|
||||
// if we entered loop body, the array cannot be empty
|
||||
@@ -750,6 +747,7 @@ class ForeachAnalyzer
|
||||
foreach ($iterator_atomic_types as $iterator_atomic_type) {
|
||||
if ($iterator_atomic_type instanceof TTemplateParam
|
||||
|| $iterator_atomic_type instanceof TObjectWithProperties
|
||||
|| $iterator_atomic_type instanceof TCallableObject
|
||||
) {
|
||||
throw new UnexpectedValueException('Shouldn’t get a generic param here');
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ class ElseAnalyzer
|
||||
$original_context,
|
||||
$new_assigned_var_ids,
|
||||
$new_possibly_assigned_var_ids,
|
||||
[],
|
||||
$if_scope->if_cond_changed_var_ids,
|
||||
true,
|
||||
);
|
||||
|
||||
|
||||
@@ -108,11 +108,6 @@ class LoopAnalyzer
|
||||
|
||||
if ($assignment_depth === 0 || $does_always_break) {
|
||||
$continue_context = clone $loop_context;
|
||||
|
||||
foreach ($continue_context->vars_in_scope as $context_var_id => $context_type) {
|
||||
$continue_context->vars_in_scope[$context_var_id] = $context_type;
|
||||
}
|
||||
|
||||
$continue_context->loop_scope = $loop_scope;
|
||||
|
||||
foreach ($pre_conditions as $condition_offset => $pre_condition) {
|
||||
|
||||
@@ -333,19 +333,32 @@ class ArrayAnalyzer
|
||||
} elseif ($key_type->isSingleIntLiteral()) {
|
||||
$item_key_value = $key_type->getSingleIntLiteral()->value;
|
||||
|
||||
if ($item_key_value >= $array_creation_info->int_offset) {
|
||||
if ($item_key_value === $array_creation_info->int_offset) {
|
||||
if ($item_key_value <= PHP_INT_MAX
|
||||
&& $item_key_value > $array_creation_info->int_offset
|
||||
) {
|
||||
if ($item_key_value - 1 === $array_creation_info->int_offset) {
|
||||
$item_is_list_item = true;
|
||||
}
|
||||
$array_creation_info->int_offset = $item_key_value + 1;
|
||||
$array_creation_info->int_offset = $item_key_value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$key_type = Type::getArrayKey();
|
||||
}
|
||||
} else {
|
||||
if ($array_creation_info->int_offset === PHP_INT_MAX) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidArrayOffset(
|
||||
'Cannot add an item with an offset beyond PHP_INT_MAX',
|
||||
new CodeLocation($statements_analyzer->getSource(), $item),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$item_is_list_item = true;
|
||||
$item_key_value = $array_creation_info->int_offset++;
|
||||
$item_key_value = ++$array_creation_info->int_offset;
|
||||
|
||||
$key_atomic_type = new TLiteralInt($item_key_value);
|
||||
$array_creation_info->item_key_atomic_types[] = $key_atomic_type;
|
||||
$key_type = new Union([$key_atomic_type]);
|
||||
@@ -538,7 +551,17 @@ class ArrayAnalyzer
|
||||
$array_creation_info->item_key_atomic_types[] = Type::getAtomicStringFromLiteral($new_offset);
|
||||
$array_creation_info->all_list = false;
|
||||
} else {
|
||||
$new_offset = $array_creation_info->int_offset++;
|
||||
if ($array_creation_info->int_offset === PHP_INT_MAX) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidArrayOffset(
|
||||
'Cannot add an item with an offset beyond PHP_INT_MAX',
|
||||
new CodeLocation($statements_analyzer->getSource(), $item->value),
|
||||
),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
);
|
||||
continue 2;
|
||||
}
|
||||
$new_offset = ++$array_creation_info->int_offset;
|
||||
$array_creation_info->item_key_atomic_types[] = new TLiteralInt($new_offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,12 @@ class ArrayCreationInfo
|
||||
*/
|
||||
public array $array_keys = [];
|
||||
|
||||
public int $int_offset = 0;
|
||||
/**
|
||||
* Holds the integer offset of the *last* element added
|
||||
*
|
||||
* -1 may mean no elements have been added yet, but can also mean there's an element with offset -1
|
||||
*/
|
||||
public int $int_offset = -1;
|
||||
|
||||
public bool $all_list = true;
|
||||
|
||||
|
||||
@@ -1087,7 +1087,7 @@ class InstancePropertyAssignmentAnalyzer
|
||||
* If we have an explicit list of all allowed magic properties on the class, and we're
|
||||
* not in that list, fall through
|
||||
*/
|
||||
if (!$var_id || !$class_storage->sealed_properties) {
|
||||
if (!$var_id || !$class_storage->hasSealedProperties($codebase->config)) {
|
||||
if (!$context->collect_initializations && !$context->collect_mutations) {
|
||||
self::taintProperty(
|
||||
$statements_analyzer,
|
||||
|
||||
@@ -56,6 +56,7 @@ use Psalm\Issue\PossiblyUndefinedIntArrayOffset;
|
||||
use Psalm\Issue\ReferenceConstraintViolation;
|
||||
use Psalm\Issue\ReferenceReusedFromConfusingScope;
|
||||
use Psalm\Issue\UnnecessaryVarAnnotation;
|
||||
use Psalm\Issue\UnsupportedPropertyReferenceUsage;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Node\Expr\BinaryOp\VirtualBitwiseAnd;
|
||||
use Psalm\Node\Expr\BinaryOp\VirtualBitwiseOr;
|
||||
@@ -270,7 +271,7 @@ class AssignmentAnalyzer
|
||||
&& $extended_var_id
|
||||
&& (!$not_ignored_docblock_var_ids || isset($not_ignored_docblock_var_ids[$extended_var_id]))
|
||||
&& $temp_assign_value_type->getId() === $comment_type->getId()
|
||||
&& !$comment_type->isMixed()
|
||||
&& !$comment_type->isMixed(true)
|
||||
) {
|
||||
if ($codebase->alter_code
|
||||
&& isset($statements_analyzer->getProjectAnalyzer()->getIssuesToFix()['UnnecessaryVarAnnotation'])
|
||||
@@ -980,10 +981,18 @@ class AssignmentAnalyzer
|
||||
$context->references_to_external_scope[$lhs_var_id] = true;
|
||||
}
|
||||
if (strpos($rhs_var_id, '->') !== false) {
|
||||
IssueBuffer::maybeAdd(new UnsupportedPropertyReferenceUsage(
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt),
|
||||
));
|
||||
// Reference to object property, we always consider object properties to be an external scope for references
|
||||
// TODO handle differently so it's detected as unused if the object is unused?
|
||||
$context->references_to_external_scope[$lhs_var_id] = true;
|
||||
}
|
||||
if (strpos($rhs_var_id, '::') !== false) {
|
||||
IssueBuffer::maybeAdd(new UnsupportedPropertyReferenceUsage(
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt),
|
||||
));
|
||||
}
|
||||
|
||||
$lhs_location = new CodeLocation($statements_analyzer->getSource(), $stmt->var);
|
||||
if (!$stmt->var instanceof ArrayDimFetch && !$stmt->var instanceof PropertyFetch) {
|
||||
|
||||
@@ -71,7 +71,9 @@ use function reset;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
use function substr_count;
|
||||
|
||||
use const DIRECTORY_SEPARATOR;
|
||||
use const PREG_SPLIT_NO_EMPTY;
|
||||
|
||||
/**
|
||||
@@ -174,7 +176,9 @@ class ArgumentAnalyzer
|
||||
$prev_ord = $ord;
|
||||
}
|
||||
|
||||
if (count($values) < 12 || ($gt_count / count($values)) < 0.8) {
|
||||
if (substr_count($arg_value_type->getSingleStringLiteral()->value, DIRECTORY_SEPARATOR) <= 2
|
||||
&& (count($values) < 12 || ($gt_count / count($values)) < 0.8)
|
||||
) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidLiteralArgument(
|
||||
'Argument ' . ($argument_offset + 1) . ' of ' . $cased_method_id
|
||||
|
||||
@@ -20,7 +20,6 @@ use Psalm\Internal\Codebase\TaintFlowGraph;
|
||||
use Psalm\Internal\DataFlow\TaintSink;
|
||||
use Psalm\Internal\MethodIdentifier;
|
||||
use Psalm\Internal\Stubs\Generator\StubsGenerator;
|
||||
use Psalm\Internal\Type\Comparator\CallableTypeComparator;
|
||||
use Psalm\Internal\Type\Comparator\UnionTypeComparator;
|
||||
use Psalm\Internal\Type\TemplateInferredTypeReplacer;
|
||||
use Psalm\Internal\Type\TemplateResult;
|
||||
@@ -197,18 +196,16 @@ class ArgumentsAnalyzer
|
||||
}
|
||||
|
||||
$high_order_template_result = null;
|
||||
$high_order_callable_info = $param
|
||||
? HighOrderFunctionArgHandler::getCallableArgInfo($context, $arg->value, $statements_analyzer, $param)
|
||||
: null;
|
||||
|
||||
if (($arg->value instanceof PhpParser\Node\Expr\FuncCall
|
||||
|| $arg->value instanceof PhpParser\Node\Expr\MethodCall
|
||||
|| $arg->value instanceof PhpParser\Node\Expr\StaticCall)
|
||||
&& $param
|
||||
&& $function_storage = self::getHighOrderFuncStorage($context, $statements_analyzer, $arg->value)
|
||||
) {
|
||||
$high_order_template_result = self::handleHighOrderFuncCallArg(
|
||||
if ($param && $high_order_callable_info) {
|
||||
$high_order_template_result = HighOrderFunctionArgHandler::remapLowerBounds(
|
||||
$statements_analyzer,
|
||||
$template_result ?? new TemplateResult([], []),
|
||||
$function_storage,
|
||||
$param,
|
||||
$high_order_callable_info,
|
||||
$param->type ?? Type::getMixed(),
|
||||
);
|
||||
} elseif (($arg->value instanceof PhpParser\Node\Expr\Closure
|
||||
|| $arg->value instanceof PhpParser\Node\Expr\ArrowFunction)
|
||||
@@ -228,7 +225,6 @@ class ArgumentsAnalyzer
|
||||
}
|
||||
|
||||
$was_inside_call = $context->inside_call;
|
||||
|
||||
$context->inside_call = true;
|
||||
|
||||
if (ExpressionAnalyzer::analyze(
|
||||
@@ -247,6 +243,16 @@ class ArgumentsAnalyzer
|
||||
|
||||
$context->inside_call = $was_inside_call;
|
||||
|
||||
if ($high_order_callable_info && $high_order_template_result) {
|
||||
HighOrderFunctionArgHandler::enhanceCallableArgType(
|
||||
$context,
|
||||
$arg->value,
|
||||
$statements_analyzer,
|
||||
$high_order_callable_info,
|
||||
$high_order_template_result,
|
||||
);
|
||||
}
|
||||
|
||||
if (($argument_offset === 0 && $method_id === 'array_filter' && count($args) === 2)
|
||||
|| ($argument_offset > 0 && $method_id === 'array_map' && count($args) >= 2)
|
||||
) {
|
||||
@@ -345,184 +351,6 @@ class ArgumentsAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
private static function getHighOrderFuncStorage(
|
||||
Context $context,
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
PhpParser\Node\Expr\CallLike $function_like_call
|
||||
): ?FunctionLikeStorage {
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
try {
|
||||
if ($function_like_call instanceof PhpParser\Node\Expr\FuncCall &&
|
||||
!$function_like_call->isFirstClassCallable()
|
||||
) {
|
||||
$function_id = strtolower((string) $function_like_call->name->getAttribute('resolvedName'));
|
||||
|
||||
if (empty($function_id)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($codebase->functions->dynamic_storage_provider->has($function_id)) {
|
||||
return $codebase->functions->dynamic_storage_provider->getFunctionStorage(
|
||||
$function_like_call,
|
||||
$statements_analyzer,
|
||||
$function_id,
|
||||
$context,
|
||||
new CodeLocation($statements_analyzer, $function_like_call),
|
||||
);
|
||||
}
|
||||
|
||||
return $codebase->functions->getStorage($statements_analyzer, $function_id);
|
||||
}
|
||||
|
||||
if ($function_like_call instanceof PhpParser\Node\Expr\MethodCall &&
|
||||
$function_like_call->var instanceof PhpParser\Node\Expr\Variable &&
|
||||
$function_like_call->name instanceof PhpParser\Node\Identifier &&
|
||||
is_string($function_like_call->var->name) &&
|
||||
isset($context->vars_in_scope['$' . $function_like_call->var->name])
|
||||
) {
|
||||
$lhs_type = $context->vars_in_scope['$' . $function_like_call->var->name]->getSingleAtomic();
|
||||
|
||||
if (!$lhs_type instanceof Type\Atomic\TNamedObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$method_id = new MethodIdentifier(
|
||||
$lhs_type->value,
|
||||
strtolower((string)$function_like_call->name),
|
||||
);
|
||||
|
||||
return $codebase->methods->getStorage($method_id);
|
||||
}
|
||||
|
||||
if ($function_like_call instanceof PhpParser\Node\Expr\StaticCall &&
|
||||
$function_like_call->name instanceof PhpParser\Node\Identifier
|
||||
) {
|
||||
$method_id = new MethodIdentifier(
|
||||
(string)$function_like_call->class->getAttribute('resolvedName'),
|
||||
strtolower($function_like_call->name->name),
|
||||
);
|
||||
|
||||
return $codebase->methods->getStorage($method_id);
|
||||
}
|
||||
} catch (UnexpectedValueException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles TemplateResult for high-order functions ($func_call)
|
||||
* by previous template args ($inferred_template_result).
|
||||
*
|
||||
* It's need for proper template replacement:
|
||||
*
|
||||
* ```
|
||||
* * template T
|
||||
* * return Closure(T): T
|
||||
* function id(): Closure { ... }
|
||||
*
|
||||
* * template A
|
||||
* * template B
|
||||
* *
|
||||
* * param list<A> $_items
|
||||
* * param callable(A): B $_ab
|
||||
* * return list<B>
|
||||
* function map(array $items, callable $ab): array { ... }
|
||||
*
|
||||
* // list<int>
|
||||
* $numbers = [1, 2, 3];
|
||||
*
|
||||
* $result = map($numbers, id());
|
||||
* // $result is list<int> because template T of id() was inferred by previous arg.
|
||||
* ```
|
||||
*/
|
||||
private static function handleHighOrderFuncCallArg(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
TemplateResult $inferred_template_result,
|
||||
FunctionLikeStorage $storage,
|
||||
FunctionLikeParameter $actual_func_param
|
||||
): ?TemplateResult {
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
$input_hof_atomic = $storage->return_type && $storage->return_type->isSingle()
|
||||
? $storage->return_type->getSingleAtomic()
|
||||
: null;
|
||||
|
||||
// Try upcast invokable to callable type.
|
||||
if ($input_hof_atomic instanceof Type\Atomic\TNamedObject &&
|
||||
$input_hof_atomic->value !== 'Closure' &&
|
||||
$codebase->classExists($input_hof_atomic->value)
|
||||
) {
|
||||
$callable_from_invokable = CallableTypeComparator::getCallableFromAtomic(
|
||||
$codebase,
|
||||
$input_hof_atomic,
|
||||
);
|
||||
|
||||
if ($callable_from_invokable) {
|
||||
$invoke_id = new MethodIdentifier($input_hof_atomic->value, '__invoke');
|
||||
$declaring_invoke_id = $codebase->methods->getDeclaringMethodId($invoke_id);
|
||||
|
||||
$storage = $codebase->methods->getStorage($declaring_invoke_id ?? $invoke_id);
|
||||
$input_hof_atomic = $callable_from_invokable;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$input_hof_atomic instanceof TClosure && !$input_hof_atomic instanceof TCallable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$container_hof_atomic = $actual_func_param->type && $actual_func_param->type->isSingle()
|
||||
? $actual_func_param->type->getSingleAtomic()
|
||||
: null;
|
||||
|
||||
if (!$container_hof_atomic instanceof TClosure && !$container_hof_atomic instanceof TCallable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$replaced_container_hof_atomic = new Union([$container_hof_atomic]);
|
||||
|
||||
// Replaces all input args in container function.
|
||||
//
|
||||
// For example:
|
||||
// The map function expects callable(A):B as second param
|
||||
// We know that previous arg type is list<int> where the int is the A template.
|
||||
// Then we can replace callable(A): B to callable(int):B using $inferred_template_result.
|
||||
$replaced_container_hof_atomic = TemplateInferredTypeReplacer::replace(
|
||||
$replaced_container_hof_atomic,
|
||||
$inferred_template_result,
|
||||
$codebase,
|
||||
);
|
||||
|
||||
/** @var TClosure|TCallable $container_hof_atomic */
|
||||
$container_hof_atomic = $replaced_container_hof_atomic->getSingleAtomic();
|
||||
$high_order_template_result = new TemplateResult($storage->template_types ?: [], []);
|
||||
|
||||
// We can replace each templated param for the input function.
|
||||
// Example:
|
||||
// map($numbers, id());
|
||||
// We know that map expects callable(int):B because the $numbers is list<int>.
|
||||
// We know that id() returns callable(T):T.
|
||||
// Then we can replace templated params sequentially using the expected callable(int):B.
|
||||
foreach ($input_hof_atomic->params ?? [] as $offset => $actual_func_param) {
|
||||
if ($actual_func_param->type &&
|
||||
$actual_func_param->type->getTemplateTypes() &&
|
||||
isset($container_hof_atomic->params[$offset])
|
||||
) {
|
||||
TemplateStandinTypeReplacer::fillTemplateResult(
|
||||
$actual_func_param->type,
|
||||
$high_order_template_result,
|
||||
$codebase,
|
||||
null,
|
||||
$container_hof_atomic->params[$offset]->type,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $high_order_template_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, PhpParser\Node\Arg> $args
|
||||
*/
|
||||
@@ -930,7 +758,7 @@ class ArgumentsAnalyzer
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidNamedArgument(
|
||||
'Parameter $' . $key_type->value . ' does not exist on function '
|
||||
. ($cased_method_id ?: $method_id),
|
||||
. ($cased_method_id ?: $method_id),
|
||||
new CodeLocation($statements_analyzer, $arg),
|
||||
(string)$method_id,
|
||||
),
|
||||
@@ -970,7 +798,7 @@ class ArgumentsAnalyzer
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidNamedArgument(
|
||||
'Parameter $' . $arg->name->name . ' does not exist on function '
|
||||
. ($cased_method_id ?: $method_id),
|
||||
. ($cased_method_id ?: $method_id),
|
||||
new CodeLocation($statements_analyzer, $arg->name),
|
||||
(string) $method_id,
|
||||
),
|
||||
|
||||
@@ -14,6 +14,7 @@ use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
|
||||
use Psalm\Internal\Analyzer\StatementsAnalyzer;
|
||||
use Psalm\Internal\Codebase\InternalCallMapHandler;
|
||||
use Psalm\Internal\MethodIdentifier;
|
||||
use Psalm\Internal\Type\ArrayType;
|
||||
use Psalm\Internal\Type\Comparator\TypeComparisonResult;
|
||||
use Psalm\Internal\Type\Comparator\UnionTypeComparator;
|
||||
use Psalm\Internal\Type\TemplateResult;
|
||||
@@ -41,12 +42,14 @@ use Psalm\Type\Union;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function array_filter;
|
||||
use function array_merge;
|
||||
use function array_pop;
|
||||
use function array_shift;
|
||||
use function array_unshift;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function is_numeric;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
@@ -346,6 +349,40 @@ class ArrayFunctionArgumentsAnalyzer
|
||||
return false;
|
||||
}
|
||||
|
||||
$array_type = null;
|
||||
$array_size = null;
|
||||
|
||||
if (($array_arg_type = $statements_analyzer->node_data->getType($array_arg))
|
||||
&& $array_arg_type->hasArray()
|
||||
) {
|
||||
/**
|
||||
* @var TArray|TKeyedArray
|
||||
*/
|
||||
$array_type = $array_arg_type->getArray();
|
||||
if ($generic_array_type = ArrayType::infer($array_type)) {
|
||||
$array_size = $generic_array_type->count;
|
||||
}
|
||||
|
||||
if ($array_type instanceof TKeyedArray) {
|
||||
if ($array_type->is_list && isset($args[3])) {
|
||||
$array_type = Type::getNonEmptyListAtomic($array_type->getGenericValueType());
|
||||
} else {
|
||||
$array_type = $array_type->getGenericArrayType();
|
||||
}
|
||||
}
|
||||
|
||||
if ($array_type instanceof TArray
|
||||
&& $array_type->type_params[0]->hasInt()
|
||||
&& !$array_type->type_params[0]->hasString()
|
||||
) {
|
||||
if ($array_type instanceof TNonEmptyArray && isset($args[3])) {
|
||||
$array_type = Type::getNonEmptyListAtomic($array_type->type_params[1]);
|
||||
} else {
|
||||
$array_type = Type::getListAtomic($array_type->type_params[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$offset_arg = $args[1]->value;
|
||||
|
||||
if (ExpressionAnalyzer::analyze(
|
||||
@@ -356,7 +393,47 @@ class ArrayFunctionArgumentsAnalyzer
|
||||
return false;
|
||||
}
|
||||
|
||||
$offset_arg_is_zero = false;
|
||||
|
||||
if (($offset_arg_type = $statements_analyzer->node_data->getType($offset_arg))
|
||||
&& $offset_arg_type->hasLiteralValue() && $offset_arg_type->isSingleLiteral()
|
||||
) {
|
||||
$offset_literal_value = $offset_arg_type->getSingleLiteral()->value;
|
||||
$offset_arg_is_zero = is_numeric($offset_literal_value) && ((int) $offset_literal_value)===0;
|
||||
}
|
||||
|
||||
if (!isset($args[2])) {
|
||||
if ($offset_arg_is_zero) {
|
||||
$array_type = Type::getEmptyArray();
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
$array_type,
|
||||
$array_type,
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
} elseif ($array_type) {
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
new Union([$array_type]),
|
||||
new Union([$array_type]),
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
$default_array_type = Type::getArray();
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
$default_array_type,
|
||||
$default_array_type,
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -370,7 +447,69 @@ class ArrayFunctionArgumentsAnalyzer
|
||||
return false;
|
||||
}
|
||||
|
||||
$cover_whole_arr = false;
|
||||
if ($offset_arg_is_zero && is_numeric($array_size)) {
|
||||
if (($length_arg_type = $statements_analyzer->node_data->getType($length_arg))
|
||||
&& $length_arg_type->hasLiteralValue()
|
||||
) {
|
||||
$length_min = null;
|
||||
if ($length_arg_type->isSingleLiteral()) {
|
||||
$length_literal = $length_arg_type->getSingleLiteral();
|
||||
if ($length_literal->isNumericType()) {
|
||||
$length_min = (int) $length_literal->value;
|
||||
}
|
||||
} else {
|
||||
$literals = array_merge(
|
||||
$length_arg_type->getLiteralStrings(),
|
||||
$length_arg_type->getLiteralInts(),
|
||||
$length_arg_type->getLiteralFloats(),
|
||||
);
|
||||
foreach ($literals as $literal) {
|
||||
if ($literal->isNumericType()
|
||||
&& ($literal_val = (int) $literal->value)
|
||||
&& ((isset($length_min) && $length_min> $literal_val) || !isset($length_min))) {
|
||||
$length_min = $literal_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
$cover_whole_arr = isset($length_min) && $length_min>= $array_size;
|
||||
} elseif ($length_arg_type&& $length_arg_type->isNull()) {
|
||||
$cover_whole_arr = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($args[3])) {
|
||||
if ($cover_whole_arr) {
|
||||
$array_type = Type::getEmptyArray();
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
$array_type,
|
||||
$array_type,
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
} elseif ($array_type) {
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
new Union([$array_type]),
|
||||
new Union([$array_type]),
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
$default_array_type = Type::getArray();
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
$default_array_type,
|
||||
$default_array_type,
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -400,40 +539,31 @@ class ArrayFunctionArgumentsAnalyzer
|
||||
$statements_analyzer->node_data->setType($replacement_arg, $replacement_arg_type);
|
||||
}
|
||||
|
||||
if (($array_arg_type = $statements_analyzer->node_data->getType($array_arg))
|
||||
&& $array_arg_type->hasArray()
|
||||
if ($array_type
|
||||
&& $replacement_arg_type
|
||||
&& $replacement_arg_type->hasArray()
|
||||
) {
|
||||
/**
|
||||
* @var TArray|TKeyedArray
|
||||
*/
|
||||
$array_type = $array_arg_type->getArray();
|
||||
|
||||
if ($array_type instanceof TKeyedArray) {
|
||||
if ($array_type->is_list) {
|
||||
$array_type = Type::getNonEmptyListAtomic($array_type->getGenericValueType());
|
||||
} else {
|
||||
$array_type = $array_type->getGenericArrayType();
|
||||
}
|
||||
}
|
||||
|
||||
if ($array_type instanceof TArray
|
||||
&& $array_type->type_params[0]->hasInt()
|
||||
&& !$array_type->type_params[0]->hasString()
|
||||
) {
|
||||
if ($array_type instanceof TNonEmptyArray) {
|
||||
$array_type = Type::getNonEmptyListAtomic($array_type->type_params[1]);
|
||||
} else {
|
||||
$array_type = Type::getListAtomic($array_type->type_params[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @var TArray|TKeyedArray
|
||||
*/
|
||||
$replacement_array_type = $replacement_arg_type->getArray();
|
||||
|
||||
if (($replacement_array_type_generic = ArrayType::infer($replacement_array_type))
|
||||
&& $replacement_array_type_generic->count === 0
|
||||
&& $cover_whole_arr) {
|
||||
$empty_array_type = Type::getEmptyArray();
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
$empty_array_type,
|
||||
$empty_array_type,
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($replacement_array_type instanceof TKeyedArray) {
|
||||
$was_list = $replacement_array_type->is_list;
|
||||
|
||||
@@ -462,16 +592,26 @@ class ArrayFunctionArgumentsAnalyzer
|
||||
return null;
|
||||
}
|
||||
|
||||
$array_type = Type::getArray();
|
||||
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
$array_type,
|
||||
$array_type,
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
if ($array_type) {
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
new Union([$array_type]),
|
||||
new Union([$array_type]),
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
$default_array_type = Type::getArray();
|
||||
AssignmentAnalyzer::assignByRefParam(
|
||||
$statements_analyzer,
|
||||
$array_arg,
|
||||
$default_array_type,
|
||||
$default_array_type,
|
||||
$context,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -723,8 +723,17 @@ class FunctionCallAnalyzer extends CallAnalyzer
|
||||
),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
);
|
||||
} elseif ($var_type_part instanceof TCallableObject
|
||||
|| $var_type_part instanceof TCallableString
|
||||
} elseif ($var_type_part instanceof TCallableObject) {
|
||||
$has_valid_function_call_type = true;
|
||||
self::analyzeInvokeCall(
|
||||
$statements_analyzer,
|
||||
$stmt,
|
||||
$real_stmt,
|
||||
$function_name,
|
||||
$context,
|
||||
$var_type_part,
|
||||
);
|
||||
} elseif ($var_type_part instanceof TCallableString
|
||||
|| ($var_type_part instanceof TNamedObject && $var_type_part->value === 'Closure')
|
||||
|| ($var_type_part instanceof TObjectWithProperties && isset($var_type_part->methods['__invoke']))
|
||||
) {
|
||||
|
||||
@@ -482,15 +482,25 @@ class FunctionCallReturnTypeFetcher
|
||||
|
||||
return $call_map_return_type;
|
||||
case 'mb_strtolower':
|
||||
$string_arg_type = $statements_analyzer->node_data->getType($call_args[0]->value);
|
||||
if ($string_arg_type !== null && $string_arg_type->isNonEmptyString()) {
|
||||
$returnType = Type::getNonEmptyLowercaseString();
|
||||
} else {
|
||||
$returnType = Type::getLowercaseString();
|
||||
}
|
||||
if (count($call_args) < 2) {
|
||||
return Type::getLowercaseString();
|
||||
return $returnType;
|
||||
} else {
|
||||
$second_arg_type = $statements_analyzer->node_data->getType($call_args[1]->value);
|
||||
if ($second_arg_type && $second_arg_type->isNull()) {
|
||||
return Type::getLowercaseString();
|
||||
return $returnType;
|
||||
}
|
||||
}
|
||||
return Type::getString();
|
||||
if ($string_arg_type !== null && $string_arg_type->isNonEmptyString()) {
|
||||
return Type::getNonEmptyString();
|
||||
} else {
|
||||
return Type::getString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psalm\Internal\Analyzer\Statements\Expression\Call;
|
||||
|
||||
use PhpParser;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\Context;
|
||||
use Psalm\Internal\Analyzer\StatementsAnalyzer;
|
||||
use Psalm\Internal\MethodIdentifier;
|
||||
use Psalm\Internal\Type\TemplateInferredTypeReplacer;
|
||||
use Psalm\Internal\Type\TemplateResult;
|
||||
use Psalm\Internal\Type\TemplateStandinTypeReplacer;
|
||||
use Psalm\Internal\Type\TypeExpander;
|
||||
use Psalm\Storage\FunctionLikeParameter;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TCallable;
|
||||
use Psalm\Type\Atomic\TClosure;
|
||||
use Psalm\Type\Union;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function is_string;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class HighOrderFunctionArgHandler
|
||||
{
|
||||
/**
|
||||
* Compiles TemplateResult for high-order function
|
||||
* by previous template args ($inferred_template_result).
|
||||
*
|
||||
* It's need for proper template replacement:
|
||||
*
|
||||
* ```
|
||||
* * template T
|
||||
* * return Closure(T): T
|
||||
* function id(): Closure { ... }
|
||||
*
|
||||
* * template A
|
||||
* * template B
|
||||
* *
|
||||
* * param list<A> $_items
|
||||
* * param callable(A): B $_ab
|
||||
* * return list<B>
|
||||
* function map(array $items, callable $ab): array { ... }
|
||||
*
|
||||
* // list<int>
|
||||
* $numbers = [1, 2, 3];
|
||||
*
|
||||
* $result = map($numbers, id());
|
||||
* // $result is list<int> because template T of id() was inferred by previous arg.
|
||||
* ```
|
||||
*/
|
||||
public static function remapLowerBounds(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
TemplateResult $inferred_template_result,
|
||||
HighOrderFunctionArgInfo $input_function,
|
||||
Union $container_function_type
|
||||
): TemplateResult {
|
||||
// Try to infer container callable by $inferred_template_result
|
||||
$container_type = TemplateInferredTypeReplacer::replace(
|
||||
$container_function_type,
|
||||
$inferred_template_result,
|
||||
$statements_analyzer->getCodebase(),
|
||||
);
|
||||
|
||||
$input_function_type = $input_function->getFunctionType();
|
||||
$input_function_template_result = $input_function->getTemplates();
|
||||
|
||||
// Traverse side by side 'container' params and 'input' params.
|
||||
// This maps 'input' templates to 'container' templates.
|
||||
//
|
||||
// Example:
|
||||
// 'input' => Closure(C:Bar, D:Bar): array{C:Bar, D:Bar}
|
||||
// 'container' => Closure(int, string): array{int, string}
|
||||
//
|
||||
// $remapped_lower_bounds will be: [
|
||||
// 'C' => ['Bar' => [int]],
|
||||
// 'D' => ['Bar' => [string]]
|
||||
// ].
|
||||
foreach ($input_function_type->getAtomicTypes() as $input_atomic) {
|
||||
if (!$input_atomic instanceof TClosure && !$input_atomic instanceof TCallable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($container_type->getAtomicTypes() as $container_atomic) {
|
||||
if (!$container_atomic instanceof TClosure && !$container_atomic instanceof TCallable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($input_atomic->params ?? [] as $offset => $input_param) {
|
||||
if (!isset($container_atomic->params[$offset])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TemplateStandinTypeReplacer::fillTemplateResult(
|
||||
$input_param->type ?? Type::getMixed(),
|
||||
$input_function_template_result,
|
||||
$statements_analyzer->getCodebase(),
|
||||
$statements_analyzer,
|
||||
$container_atomic->params[$offset]->type,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $input_function_template_result;
|
||||
}
|
||||
|
||||
public static function enhanceCallableArgType(
|
||||
Context $context,
|
||||
PhpParser\Node\Expr $arg_expr,
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
HighOrderFunctionArgInfo $high_order_callable_info,
|
||||
TemplateResult $high_order_template_result
|
||||
): void {
|
||||
// Psalm can infer simple callable/closure.
|
||||
// But can't infer first-class-callable or high-order function.
|
||||
if ($high_order_callable_info->getType() === HighOrderFunctionArgInfo::TYPE_CALLABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fully_inferred_callable_type = TemplateInferredTypeReplacer::replace(
|
||||
$high_order_callable_info->getFunctionType(),
|
||||
$high_order_template_result,
|
||||
$statements_analyzer->getCodebase(),
|
||||
);
|
||||
|
||||
// Some templates may not have been replaced.
|
||||
// They expansion makes error message better.
|
||||
$expanded = TypeExpander::expandUnion(
|
||||
$statements_analyzer->getCodebase(),
|
||||
$fully_inferred_callable_type,
|
||||
$context->self,
|
||||
$context->self,
|
||||
$context->parent,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
);
|
||||
|
||||
$statements_analyzer->node_data->setType($arg_expr, $expanded);
|
||||
}
|
||||
|
||||
public static function getCallableArgInfo(
|
||||
Context $context,
|
||||
PhpParser\Node\Expr $input_arg_expr,
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
FunctionLikeParameter $container_param
|
||||
): ?HighOrderFunctionArgInfo {
|
||||
if (!self::isSupported($container_param)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
try {
|
||||
if ($input_arg_expr instanceof PhpParser\Node\Expr\FuncCall) {
|
||||
$function_id = strtolower((string) $input_arg_expr->name->getAttribute('resolvedName'));
|
||||
|
||||
if (empty($function_id)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$dynamic_storage = !$input_arg_expr->isFirstClassCallable()
|
||||
? $codebase->functions->dynamic_storage_provider->getFunctionStorage(
|
||||
$input_arg_expr,
|
||||
$statements_analyzer,
|
||||
$function_id,
|
||||
$context,
|
||||
new CodeLocation($statements_analyzer, $input_arg_expr),
|
||||
)
|
||||
: null;
|
||||
|
||||
return new HighOrderFunctionArgInfo(
|
||||
$input_arg_expr->isFirstClassCallable()
|
||||
? HighOrderFunctionArgInfo::TYPE_FIRST_CLASS_CALLABLE
|
||||
: HighOrderFunctionArgInfo::TYPE_CALLABLE,
|
||||
$dynamic_storage ?? $codebase->functions->getStorage($statements_analyzer, $function_id),
|
||||
);
|
||||
}
|
||||
|
||||
if ($input_arg_expr instanceof PhpParser\Node\Expr\MethodCall &&
|
||||
$input_arg_expr->var instanceof PhpParser\Node\Expr\Variable &&
|
||||
$input_arg_expr->name instanceof PhpParser\Node\Identifier &&
|
||||
is_string($input_arg_expr->var->name) &&
|
||||
isset($context->vars_in_scope['$' . $input_arg_expr->var->name])
|
||||
) {
|
||||
$lhs_type = $context->vars_in_scope['$' . $input_arg_expr->var->name]->getSingleAtomic();
|
||||
|
||||
if (!$lhs_type instanceof Type\Atomic\TNamedObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$method_id = new MethodIdentifier(
|
||||
$lhs_type->value,
|
||||
strtolower((string)$input_arg_expr->name),
|
||||
);
|
||||
|
||||
return new HighOrderFunctionArgInfo(
|
||||
$input_arg_expr->isFirstClassCallable()
|
||||
? HighOrderFunctionArgInfo::TYPE_FIRST_CLASS_CALLABLE
|
||||
: HighOrderFunctionArgInfo::TYPE_CALLABLE,
|
||||
$codebase->methods->getStorage($method_id),
|
||||
);
|
||||
}
|
||||
|
||||
if ($input_arg_expr instanceof PhpParser\Node\Expr\StaticCall &&
|
||||
$input_arg_expr->name instanceof PhpParser\Node\Identifier
|
||||
) {
|
||||
$method_id = new MethodIdentifier(
|
||||
(string)$input_arg_expr->class->getAttribute('resolvedName'),
|
||||
strtolower($input_arg_expr->name->toString()),
|
||||
);
|
||||
|
||||
return new HighOrderFunctionArgInfo(
|
||||
$input_arg_expr->isFirstClassCallable()
|
||||
? HighOrderFunctionArgInfo::TYPE_FIRST_CLASS_CALLABLE
|
||||
: HighOrderFunctionArgInfo::TYPE_CALLABLE,
|
||||
$codebase->methods->getStorage($method_id),
|
||||
);
|
||||
}
|
||||
|
||||
if ($input_arg_expr instanceof PhpParser\Node\Scalar\String_) {
|
||||
return self::fromLiteralString(Type::getString($input_arg_expr->value), $statements_analyzer);
|
||||
}
|
||||
|
||||
if ($input_arg_expr instanceof PhpParser\Node\Expr\ConstFetch) {
|
||||
$constant = $context->constants[$input_arg_expr->name->toString()] ?? null;
|
||||
|
||||
return null !== $constant
|
||||
? self::fromLiteralString($constant, $statements_analyzer)
|
||||
: null;
|
||||
}
|
||||
|
||||
if ($input_arg_expr instanceof PhpParser\Node\Expr\ClassConstFetch &&
|
||||
$input_arg_expr->name instanceof PhpParser\Node\Identifier
|
||||
) {
|
||||
$storage = $codebase->classlikes
|
||||
->getStorageFor((string)$input_arg_expr->class->getAttribute('resolvedName'));
|
||||
|
||||
$constant = null !== $storage
|
||||
? $storage->constants[$input_arg_expr->name->toString()] ?? null
|
||||
: null;
|
||||
|
||||
return null !== $constant && null !== $constant->type
|
||||
? self::fromLiteralString($constant->type, $statements_analyzer)
|
||||
: null;
|
||||
}
|
||||
|
||||
if ($input_arg_expr instanceof PhpParser\Node\Expr\New_ &&
|
||||
$input_arg_expr->class instanceof PhpParser\Node\Name
|
||||
) {
|
||||
$class_storage = $codebase->classlikes
|
||||
->getStorageFor((string) $input_arg_expr->class->getAttribute('resolvedName'));
|
||||
|
||||
$invoke_storage = $class_storage && isset($class_storage->methods['__invoke'])
|
||||
? $class_storage->methods['__invoke']
|
||||
: null;
|
||||
|
||||
if (!$invoke_storage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new HighOrderFunctionArgInfo(
|
||||
HighOrderFunctionArgInfo::TYPE_CLASS_CALLABLE,
|
||||
$invoke_storage,
|
||||
$class_storage,
|
||||
);
|
||||
}
|
||||
} catch (UnexpectedValueException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function isSupported(FunctionLikeParameter $container_param): bool
|
||||
{
|
||||
if (!$container_param->type || !$container_param->type->hasCallableType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($container_param->type->getAtomicTypes() as $a) {
|
||||
if (($a instanceof TClosure || $a instanceof TCallable) && !$a->params) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($a instanceof Type\Atomic\TCallableArray ||
|
||||
$a instanceof Type\Atomic\TCallableString ||
|
||||
$a instanceof Type\Atomic\TCallableKeyedArray
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function fromLiteralString(
|
||||
Union $constant,
|
||||
StatementsAnalyzer $statements_analyzer
|
||||
): ?HighOrderFunctionArgInfo {
|
||||
$literal = $constant->isSingle() ? $constant->getSingleAtomic() : null;
|
||||
|
||||
if (!$literal instanceof Type\Atomic\TLiteralString || empty($literal->value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
return new HighOrderFunctionArgInfo(
|
||||
HighOrderFunctionArgInfo::TYPE_STRING_CALLABLE,
|
||||
strpos($literal->value, '::') !== false
|
||||
? $codebase->methods->getStorage(MethodIdentifier::wrap($literal->value))
|
||||
: $codebase->functions->getStorage($statements_analyzer, strtolower($literal->value)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psalm\Internal\Analyzer\Statements\Expression\Call;
|
||||
|
||||
use Psalm\Internal\Type\TemplateResult;
|
||||
use Psalm\Storage\ClassLikeStorage;
|
||||
use Psalm\Storage\FunctionLikeStorage;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TCallable;
|
||||
use Psalm\Type\Atomic\TClosure;
|
||||
use Psalm\Type\Union;
|
||||
|
||||
use function array_merge;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class HighOrderFunctionArgInfo
|
||||
{
|
||||
public const TYPE_FIRST_CLASS_CALLABLE = 'first-class-callable';
|
||||
public const TYPE_CLASS_CALLABLE = 'class-callable';
|
||||
public const TYPE_STRING_CALLABLE = 'string-callable';
|
||||
public const TYPE_CALLABLE = 'callable';
|
||||
|
||||
/** @psalm-var HighOrderFunctionArgInfo::TYPE_* */
|
||||
private string $type;
|
||||
private FunctionLikeStorage $function_storage;
|
||||
private ?ClassLikeStorage $class_storage;
|
||||
|
||||
/**
|
||||
* @psalm-param HighOrderFunctionArgInfo::TYPE_* $type
|
||||
*/
|
||||
public function __construct(
|
||||
string $type,
|
||||
FunctionLikeStorage $function_storage,
|
||||
ClassLikeStorage $class_storage = null
|
||||
) {
|
||||
$this->type = $type;
|
||||
$this->function_storage = $function_storage;
|
||||
$this->class_storage = $class_storage;
|
||||
}
|
||||
|
||||
public function getTemplates(): TemplateResult
|
||||
{
|
||||
$templates = $this->class_storage
|
||||
? array_merge(
|
||||
$this->function_storage->template_types ?? [],
|
||||
$this->class_storage->template_types ?? [],
|
||||
)
|
||||
: $this->function_storage->template_types ?? [];
|
||||
|
||||
return new TemplateResult($templates, []);
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getFunctionType(): Union
|
||||
{
|
||||
switch ($this->type) {
|
||||
case self::TYPE_FIRST_CLASS_CALLABLE:
|
||||
return new Union([
|
||||
new TClosure(
|
||||
'Closure',
|
||||
$this->function_storage->params,
|
||||
$this->function_storage->return_type,
|
||||
$this->function_storage->pure,
|
||||
),
|
||||
]);
|
||||
|
||||
case self::TYPE_STRING_CALLABLE:
|
||||
case self::TYPE_CLASS_CALLABLE:
|
||||
return new Union([
|
||||
new TCallable(
|
||||
'callable',
|
||||
$this->function_storage->params,
|
||||
$this->function_storage->return_type,
|
||||
$this->function_storage->pure,
|
||||
),
|
||||
]);
|
||||
|
||||
default:
|
||||
return $this->function_storage->return_type ?? Type::getMixed();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,8 @@ use Psalm\StatementsSource;
|
||||
use Psalm\Storage\ClassLikeStorage;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic;
|
||||
use Psalm\Type\Atomic\TCallable;
|
||||
use Psalm\Type\Atomic\TCallableObject;
|
||||
use Psalm\Type\Atomic\TClosure;
|
||||
use Psalm\Type\Atomic\TEmptyMixed;
|
||||
use Psalm\Type\Atomic\TFalse;
|
||||
@@ -104,6 +106,18 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
||||
|
||||
$source = $statements_analyzer->getSource();
|
||||
|
||||
if ($lhs_type_part instanceof TCallableObject) {
|
||||
self::handleCallableObject(
|
||||
$statements_analyzer,
|
||||
$stmt,
|
||||
$context,
|
||||
$lhs_type_part->callable,
|
||||
$result,
|
||||
$inferred_template_result,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$lhs_type_part instanceof TNamedObject) {
|
||||
self::handleInvalidClass(
|
||||
$statements_analyzer,
|
||||
@@ -891,4 +905,55 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
||||
$fq_class_name,
|
||||
];
|
||||
}
|
||||
|
||||
private static function handleCallableObject(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
PhpParser\Node\Expr\MethodCall $stmt,
|
||||
Context $context,
|
||||
?TCallable $lhs_type_part_callable,
|
||||
AtomicMethodCallAnalysisResult $result,
|
||||
?TemplateResult $inferred_template_result = null
|
||||
): void {
|
||||
$method_id = 'object::__invoke';
|
||||
$result->existent_method_ids[] = $method_id;
|
||||
$result->has_valid_method_call_type = true;
|
||||
|
||||
if ($lhs_type_part_callable !== null) {
|
||||
$result->return_type = $lhs_type_part_callable->return_type ?? Type::getMixed();
|
||||
$callableArgumentCount = count($lhs_type_part_callable->params ?? []);
|
||||
$providedArgumentsCount = count($stmt->getArgs());
|
||||
|
||||
if ($callableArgumentCount > $providedArgumentsCount) {
|
||||
$result->too_few_arguments = true;
|
||||
$result->too_few_arguments_method_ids[] = new MethodIdentifier('callable-object', '__invoke');
|
||||
} elseif ($providedArgumentsCount > $callableArgumentCount) {
|
||||
$result->too_many_arguments = true;
|
||||
$result->too_many_arguments_method_ids[] = new MethodIdentifier('callable-object', '__invoke');
|
||||
}
|
||||
|
||||
$template_result = $inferred_template_result ?? new TemplateResult([], []);
|
||||
|
||||
ArgumentsAnalyzer::analyze(
|
||||
$statements_analyzer,
|
||||
$stmt->getArgs(),
|
||||
$lhs_type_part_callable->params,
|
||||
$method_id,
|
||||
false,
|
||||
$context,
|
||||
$template_result,
|
||||
);
|
||||
|
||||
ArgumentsAnalyzer::checkArgumentsMatch(
|
||||
$statements_analyzer,
|
||||
$stmt->getArgs(),
|
||||
$method_id,
|
||||
$lhs_type_part_callable->params ?? [],
|
||||
null,
|
||||
null,
|
||||
$template_result,
|
||||
new CodeLocation($statements_analyzer->getSource(), $stmt),
|
||||
$context,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,13 @@ use Psalm\Type\Atomic\TTemplateParam;
|
||||
use Psalm\Type\Union;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
use function count;
|
||||
use function explode;
|
||||
use function in_array;
|
||||
use function is_string;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
@@ -225,6 +228,9 @@ class ExistingAtomicMethodCallAnalyzer extends CallAnalyzer
|
||||
if ($inferred_template_result) {
|
||||
$template_result->lower_bounds += $inferred_template_result->lower_bounds;
|
||||
}
|
||||
if ($method_storage && $method_storage->template_types) {
|
||||
$template_result->template_types += $method_storage->template_types;
|
||||
}
|
||||
|
||||
if ($codebase->store_node_types
|
||||
&& !$stmt->isFirstClassCallable()
|
||||
@@ -422,30 +428,48 @@ class ExistingAtomicMethodCallAnalyzer extends CallAnalyzer
|
||||
}
|
||||
|
||||
if ($method_storage->if_true_assertions) {
|
||||
$possibilities = array_map(
|
||||
static fn(Possibilities $assertion): Possibilities => $assertion->getUntemplatedCopy(
|
||||
$template_result,
|
||||
$lhs_var_id,
|
||||
$codebase,
|
||||
),
|
||||
$method_storage->if_true_assertions,
|
||||
);
|
||||
if ($lhs_var_id === null) {
|
||||
$possibilities = array_filter(
|
||||
$possibilities,
|
||||
static fn(Possibilities $assertion): bool => !(is_string($assertion->var_id)
|
||||
&& strpos($assertion->var_id, '$this->') === 0
|
||||
)
|
||||
);
|
||||
}
|
||||
$statements_analyzer->node_data->setIfTrueAssertions(
|
||||
$stmt,
|
||||
array_map(
|
||||
static fn(Possibilities $assertion): Possibilities => $assertion->getUntemplatedCopy(
|
||||
$template_result,
|
||||
$lhs_var_id,
|
||||
$codebase,
|
||||
),
|
||||
$method_storage->if_true_assertions,
|
||||
),
|
||||
$possibilities,
|
||||
);
|
||||
}
|
||||
|
||||
if ($method_storage->if_false_assertions) {
|
||||
$possibilities = array_map(
|
||||
static fn(Possibilities $assertion): Possibilities => $assertion->getUntemplatedCopy(
|
||||
$template_result,
|
||||
$lhs_var_id,
|
||||
$codebase,
|
||||
),
|
||||
$method_storage->if_false_assertions,
|
||||
);
|
||||
if ($lhs_var_id === null) {
|
||||
$possibilities = array_filter(
|
||||
$possibilities,
|
||||
static fn(Possibilities $assertion): bool => !(is_string($assertion->var_id)
|
||||
&& strpos($assertion->var_id, '$this->') === 0
|
||||
)
|
||||
);
|
||||
}
|
||||
$statements_analyzer->node_data->setIfFalseAssertions(
|
||||
$stmt,
|
||||
array_map(
|
||||
static fn(Possibilities $assertion): Possibilities => $assertion->getUntemplatedCopy(
|
||||
$template_result,
|
||||
$lhs_var_id,
|
||||
$codebase,
|
||||
),
|
||||
$method_storage->if_false_assertions,
|
||||
),
|
||||
$possibilities,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -546,7 +570,7 @@ class ExistingAtomicMethodCallAnalyzer extends CallAnalyzer
|
||||
case '__set':
|
||||
// If `@psalm-seal-properties` is set, the property must be defined with
|
||||
// a `@property` annotation
|
||||
if (($class_storage->sealed_properties || $codebase->config->seal_all_properties)
|
||||
if (($class_storage->hasSealedProperties($codebase->config))
|
||||
&& !isset($class_storage->pseudo_property_set_types['$' . $prop_name])
|
||||
) {
|
||||
IssueBuffer::maybeAdd(
|
||||
@@ -644,7 +668,7 @@ class ExistingAtomicMethodCallAnalyzer extends CallAnalyzer
|
||||
case '__get':
|
||||
// If `@psalm-seal-properties` is set, the property must be defined with
|
||||
// a `@property` annotation
|
||||
if (($class_storage->sealed_properties || $codebase->config->seal_all_properties)
|
||||
if (($class_storage->hasSealedProperties($codebase->config))
|
||||
&& !isset($class_storage->pseudo_property_get_types['$' . $prop_name])
|
||||
) {
|
||||
IssueBuffer::maybeAdd(
|
||||
|
||||
@@ -190,7 +190,7 @@ class MissingMethodCallHandler
|
||||
$context,
|
||||
);
|
||||
|
||||
if ($class_storage->sealed_methods || $config->seal_all_methods) {
|
||||
if ($class_storage->hasSealedMethods($config)) {
|
||||
$result->non_existent_magic_method_ids[] = $method_id->__toString();
|
||||
|
||||
return null;
|
||||
|
||||
@@ -52,12 +52,11 @@ use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
use Psalm\Type\Atomic\TTemplateParamClass;
|
||||
use Psalm\Type\Atomic\TUnknownClassString;
|
||||
use Psalm\Type\TaintKind;
|
||||
use Psalm\Type\Union;
|
||||
|
||||
use function array_map;
|
||||
use function array_merge;
|
||||
use function array_shift;
|
||||
use function array_values;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
@@ -74,7 +73,8 @@ class NewAnalyzer extends CallAnalyzer
|
||||
public static function analyze(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
PhpParser\Node\Expr\New_ $stmt,
|
||||
Context $context
|
||||
Context $context,
|
||||
TemplateResult $template_result = null
|
||||
): bool {
|
||||
$fq_class_name = null;
|
||||
|
||||
@@ -256,6 +256,7 @@ class NewAnalyzer extends CallAnalyzer
|
||||
$fq_class_name,
|
||||
$from_static,
|
||||
$can_extend,
|
||||
$template_result,
|
||||
);
|
||||
} else {
|
||||
ArgumentsAnalyzer::analyze(
|
||||
@@ -291,7 +292,8 @@ class NewAnalyzer extends CallAnalyzer
|
||||
Context $context,
|
||||
string $fq_class_name,
|
||||
bool $from_static,
|
||||
bool $can_extend
|
||||
bool $can_extend,
|
||||
TemplateResult $template_result = null
|
||||
): void {
|
||||
$storage = $codebase->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
@@ -392,7 +394,7 @@ class NewAnalyzer extends CallAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
$template_result = new TemplateResult([], []);
|
||||
$template_result ??= new TemplateResult([], []);
|
||||
|
||||
if (self::checkMethodArgs(
|
||||
$method_id,
|
||||
@@ -699,15 +701,58 @@ class NewAnalyzer extends CallAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
$new_type = null;
|
||||
$new_type = self::getNewType(
|
||||
$statements_analyzer,
|
||||
$codebase,
|
||||
$context,
|
||||
$stmt,
|
||||
$stmt_class_type,
|
||||
$config,
|
||||
$can_extend,
|
||||
);
|
||||
|
||||
$stmt_class_types = $stmt_class_type->getAtomicTypes();
|
||||
if (!$has_single_class) {
|
||||
if ($new_type) {
|
||||
$statements_analyzer->node_data->setType($stmt, $new_type);
|
||||
}
|
||||
|
||||
while ($stmt_class_types) {
|
||||
$lhs_type_part = array_shift($stmt_class_types);
|
||||
ArgumentsAnalyzer::analyze(
|
||||
$statements_analyzer,
|
||||
$stmt->getArgs(),
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
$context,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
private static function getNewType(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
Codebase $codebase,
|
||||
Context $context,
|
||||
PhpParser\Node\Expr\New_ $stmt,
|
||||
Union $stmt_class_type,
|
||||
Config $config,
|
||||
bool &$can_extend
|
||||
): ?Union {
|
||||
$new_types = [];
|
||||
|
||||
foreach ($stmt_class_type->getAtomicTypes() as $lhs_type_part) {
|
||||
if ($lhs_type_part instanceof TTemplateParam) {
|
||||
$stmt_class_types = array_merge($stmt_class_types, $lhs_type_part->as->getAtomicTypes());
|
||||
$as = self::getNewType(
|
||||
$statements_analyzer,
|
||||
$codebase,
|
||||
$context,
|
||||
$stmt,
|
||||
$lhs_type_part->as,
|
||||
$config,
|
||||
$can_extend,
|
||||
);
|
||||
if ($as) {
|
||||
$new_types []= new Union([$lhs_type_part->replaceAs($as)]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -731,7 +776,7 @@ class NewAnalyzer extends CallAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
$new_type = Type::combineUnionTypes($new_type, new Union([$new_type_part]));
|
||||
$new_types []= new Union([$new_type_part]);
|
||||
|
||||
if ($lhs_type_part->as_type
|
||||
&& $codebase->classlikes->classExists($lhs_type_part->as_type->value)
|
||||
@@ -777,9 +822,10 @@ class NewAnalyzer extends CallAnalyzer
|
||||
) {
|
||||
if (!$statements_analyzer->node_data->getType($stmt)) {
|
||||
if ($lhs_type_part instanceof TClassString) {
|
||||
$generated_type = $lhs_type_part->as_type
|
||||
? $lhs_type_part->as_type
|
||||
: new TObject();
|
||||
$generated_type = $lhs_type_part->as_type ?? new TObject();
|
||||
if ($lhs_type_part instanceof TUnknownClassString) {
|
||||
$generated_type = $lhs_type_part->as_unknown_type ?? $generated_type;
|
||||
}
|
||||
|
||||
if ($lhs_type_part->as_type
|
||||
&& $codebase->classlikes->classExists($lhs_type_part->as_type->value)
|
||||
@@ -834,7 +880,7 @@ class NewAnalyzer extends CallAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
$new_type = Type::combineUnionTypes($new_type, new Union([$generated_type]));
|
||||
$new_types []= new Union([$generated_type]);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -871,7 +917,7 @@ class NewAnalyzer extends CallAnalyzer
|
||||
) {
|
||||
// do nothing
|
||||
} elseif ($lhs_type_part instanceof TNamedObject) {
|
||||
$new_type = Type::combineUnionTypes($new_type, new Union([$lhs_type_part]));
|
||||
$new_types []= new Union([$lhs_type_part]);
|
||||
continue;
|
||||
} else {
|
||||
IssueBuffer::maybeAdd(
|
||||
@@ -884,24 +930,12 @@ class NewAnalyzer extends CallAnalyzer
|
||||
);
|
||||
}
|
||||
|
||||
$new_type = Type::combineUnionTypes($new_type, Type::getObject());
|
||||
$new_types []= Type::getObject();
|
||||
}
|
||||
|
||||
if (!$has_single_class) {
|
||||
if ($new_type) {
|
||||
$statements_analyzer->node_data->setType($stmt, $new_type);
|
||||
}
|
||||
|
||||
ArgumentsAnalyzer::analyze(
|
||||
$statements_analyzer,
|
||||
$stmt->getArgs(),
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
$context,
|
||||
);
|
||||
|
||||
return;
|
||||
if ($new_types) {
|
||||
return Type::combineUnionTypeArray($new_types, $codebase);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Psalm\Internal\Analyzer\Statements\Expression\Call\StaticMethod;
|
||||
|
||||
use PhpParser;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\Codebase;
|
||||
use Psalm\Config;
|
||||
@@ -465,7 +466,7 @@ class ExistingAtomicStaticCallAnalyzer
|
||||
private static function getMethodReturnType(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
Codebase $codebase,
|
||||
PhpParser\Node\Expr\StaticCall $stmt,
|
||||
StaticCall $stmt,
|
||||
MethodIdentifier $method_id,
|
||||
array $args,
|
||||
TemplateResult $template_result,
|
||||
@@ -493,40 +494,14 @@ class ExistingAtomicStaticCallAnalyzer
|
||||
[$template_type->param_name]
|
||||
[$template_type->defining_class],
|
||||
)) {
|
||||
if ($template_type->param_name === 'TFunctionArgCount') {
|
||||
$template_result->lower_bounds[$template_type->param_name] = [
|
||||
'fn-' . strtolower((string)$method_id) => [
|
||||
new TemplateBound(
|
||||
Type::getInt(false, count($stmt->getArgs())),
|
||||
),
|
||||
],
|
||||
];
|
||||
} elseif ($template_type->param_name === 'TPhpMajorVersion') {
|
||||
$template_result->lower_bounds[$template_type->param_name] = [
|
||||
'fn-' . strtolower((string)$method_id) => [
|
||||
new TemplateBound(
|
||||
Type::getInt(false, $codebase->getMajorAnalysisPhpVersion()),
|
||||
),
|
||||
],
|
||||
];
|
||||
} elseif ($template_type->param_name === 'TPhpVersionId') {
|
||||
$template_result->lower_bounds[$template_type->param_name] = [
|
||||
'fn-' . strtolower((string) $method_id) => [
|
||||
new TemplateBound(
|
||||
Type::getInt(
|
||||
false,
|
||||
$codebase->analysis_php_version_id,
|
||||
),
|
||||
),
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$template_result->lower_bounds[$template_type->param_name] = [
|
||||
($template_type->defining_class) => [
|
||||
new TemplateBound(Type::getNever()),
|
||||
],
|
||||
];
|
||||
}
|
||||
$template_result->lower_bounds[$template_type->param_name]
|
||||
= self::resolveTemplateResultLowerBound(
|
||||
$codebase,
|
||||
$stmt,
|
||||
$class_storage,
|
||||
$method_id,
|
||||
$template_type,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -632,4 +607,68 @@ class ExistingAtomicStaticCallAnalyzer
|
||||
$visitor->traverse($type);
|
||||
return $visitor->matches();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return non-empty-array<string,non-empty-list<TemplateBound>>
|
||||
*/
|
||||
private static function resolveTemplateResultLowerBound(
|
||||
Codebase $codebase,
|
||||
StaticCall $stmt,
|
||||
ClassLikeStorage $class_storage,
|
||||
MethodIdentifier $method_id,
|
||||
TTemplateParam $template_type
|
||||
): array {
|
||||
if ($template_type->param_name === 'TFunctionArgCount') {
|
||||
return [
|
||||
'fn-' . strtolower((string)$method_id) => [
|
||||
new TemplateBound(
|
||||
Type::getInt(false, count($stmt->getArgs())),
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
if ($template_type->param_name === 'TPhpMajorVersion') {
|
||||
return [
|
||||
'fn-' . strtolower((string)$method_id) => [
|
||||
new TemplateBound(
|
||||
Type::getInt(false, $codebase->getMajorAnalysisPhpVersion()),
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
if ($template_type->param_name === 'TPhpVersionId') {
|
||||
return [
|
||||
'fn-' . strtolower((string) $method_id) => [
|
||||
new TemplateBound(
|
||||
Type::getInt(
|
||||
false,
|
||||
$codebase->analysis_php_version_id,
|
||||
),
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
if (isset(
|
||||
$class_storage->template_extended_params[$template_type->defining_class][$template_type->param_name],
|
||||
)) {
|
||||
$extended_param_type = $class_storage->template_extended_params[
|
||||
$template_type->defining_class
|
||||
][$template_type->param_name];
|
||||
|
||||
return [
|
||||
($template_type->defining_class) => [
|
||||
new TemplateBound($extended_param_type),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
($template_type->defining_class) => [
|
||||
new TemplateBound(Type::getNever()),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ use Psalm\Storage\Assertion\Truthy;
|
||||
use Psalm\Storage\ClassLikeStorage;
|
||||
use Psalm\Storage\Possibilities;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TCallableObject;
|
||||
use Psalm\Type\Atomic\TNamedObject;
|
||||
use Psalm\Type\Atomic\TObjectWithProperties;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
@@ -579,6 +580,7 @@ class CallAnalyzer
|
||||
foreach ($type_part->extra_types as $extra_type) {
|
||||
if ($extra_type instanceof TTemplateParam
|
||||
|| $extra_type instanceof TObjectWithProperties
|
||||
|| $extra_type instanceof TCallableObject
|
||||
) {
|
||||
throw new UnexpectedValueException('Shouldn’t get a generic param here');
|
||||
}
|
||||
|
||||
@@ -844,6 +844,7 @@ class ClassConstAnalyzer
|
||||
assert($parent_classlike_storage !== null);
|
||||
if (!isset($parent_classlike_storage->parent_interfaces[strtolower($interface)])
|
||||
&& !isset($interface_storage->parent_interfaces[strtolower($parent_classlike_storage->name)])
|
||||
&& $interface_const_storage !== $parent_const_storage
|
||||
) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new AmbiguousConstantInheritance(
|
||||
|
||||
@@ -26,7 +26,10 @@ class EvalAnalyzer
|
||||
PhpParser\Node\Expr\Eval_ $stmt,
|
||||
Context $context
|
||||
): void {
|
||||
$was_inside_call = $context->inside_call;
|
||||
$context->inside_call = true;
|
||||
ExpressionAnalyzer::analyze($statements_analyzer, $stmt->expr, $context);
|
||||
$context->inside_call = $was_inside_call;
|
||||
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
|
||||
@@ -115,17 +115,31 @@ class AtomicPropertyFetchAnalyzer
|
||||
return;
|
||||
}
|
||||
|
||||
$has_valid_fetch_type = true;
|
||||
if ($lhs_type_part instanceof TObjectWithProperties) {
|
||||
if (!isset($lhs_type_part->properties[$prop_name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$has_valid_fetch_type = true;
|
||||
|
||||
if ($lhs_type_part instanceof TObjectWithProperties
|
||||
&& isset($lhs_type_part->properties[$prop_name])
|
||||
) {
|
||||
$stmt_type = $statements_analyzer->node_data->getType($stmt);
|
||||
|
||||
$statements_analyzer->node_data->setType(
|
||||
$stmt,
|
||||
Type::combineUnionTypes(
|
||||
$lhs_type_part->properties[$prop_name],
|
||||
TypeExpander::expandUnion(
|
||||
$statements_analyzer->getCodebase(),
|
||||
$lhs_type_part->properties[$prop_name],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
$stmt_type,
|
||||
),
|
||||
);
|
||||
@@ -133,12 +147,22 @@ class AtomicPropertyFetchAnalyzer
|
||||
return;
|
||||
}
|
||||
|
||||
$intersection_types = [];
|
||||
if (!$lhs_type_part instanceof TObject) {
|
||||
$intersection_types = $lhs_type_part->getIntersectionTypes();
|
||||
}
|
||||
|
||||
// stdClass and SimpleXMLElement are special cases where we cannot infer the return types
|
||||
// but we don't want to throw an error
|
||||
// Hack has a similar issue: https://github.com/facebook/hhvm/issues/5164
|
||||
if ($lhs_type_part instanceof TObject
|
||||
|| in_array(strtolower($lhs_type_part->value), Config::getInstance()->getUniversalObjectCrates(), true)
|
||||
|| (
|
||||
in_array(strtolower($lhs_type_part->value), Config::getInstance()->getUniversalObjectCrates(), true)
|
||||
&& $intersection_types === []
|
||||
)
|
||||
) {
|
||||
$has_valid_fetch_type = true;
|
||||
|
||||
$statements_analyzer->node_data->setType($stmt, Type::getMixed());
|
||||
|
||||
return;
|
||||
@@ -149,8 +173,6 @@ class AtomicPropertyFetchAnalyzer
|
||||
return;
|
||||
}
|
||||
|
||||
$intersection_types = $lhs_type_part->getIntersectionTypes() ?: [];
|
||||
|
||||
$fq_class_name = $lhs_type_part->value;
|
||||
|
||||
$override_property_visibility = false;
|
||||
@@ -193,6 +215,7 @@ class AtomicPropertyFetchAnalyzer
|
||||
|
||||
if ($class_storage->is_enum || in_array('UnitEnum', $codebase->getParentInterfaces($fq_class_name))) {
|
||||
if ($prop_name === 'value' && !$class_storage->is_enum) {
|
||||
$has_valid_fetch_type = true;
|
||||
$statements_analyzer->node_data->setType(
|
||||
$stmt,
|
||||
new Union([
|
||||
@@ -201,8 +224,10 @@ class AtomicPropertyFetchAnalyzer
|
||||
]),
|
||||
);
|
||||
} elseif ($prop_name === 'value' && $class_storage->enum_type !== null && $class_storage->enum_cases) {
|
||||
$has_valid_fetch_type = true;
|
||||
self::handleEnumValue($statements_analyzer, $stmt, $stmt_var_type, $class_storage);
|
||||
} elseif ($prop_name === 'name') {
|
||||
$has_valid_fetch_type = true;
|
||||
self::handleEnumName($statements_analyzer, $stmt, $lhs_type_part);
|
||||
} else {
|
||||
self::handleNonExistentProperty(
|
||||
@@ -220,6 +245,7 @@ class AtomicPropertyFetchAnalyzer
|
||||
$stmt_var_id,
|
||||
$has_magic_getter,
|
||||
$var_id,
|
||||
$has_valid_fetch_type,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -237,39 +263,60 @@ class AtomicPropertyFetchAnalyzer
|
||||
// add method before changing fq_class_name
|
||||
$get_method_id = new MethodIdentifier($fq_class_name, '__get');
|
||||
|
||||
if (!$naive_property_exists
|
||||
&& $class_storage->namedMixins
|
||||
) {
|
||||
foreach ($class_storage->namedMixins as $mixin) {
|
||||
$new_property_id = $mixin->value . '::$' . $prop_name;
|
||||
if (!$naive_property_exists) {
|
||||
if ($class_storage->namedMixins) {
|
||||
foreach ($class_storage->namedMixins as $mixin) {
|
||||
$new_property_id = $mixin->value . '::$' . $prop_name;
|
||||
|
||||
try {
|
||||
$new_class_storage = $codebase->classlike_storage_provider->get($mixin->value);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$new_class_storage = null;
|
||||
}
|
||||
|
||||
if ($new_class_storage
|
||||
&& ($codebase->properties->propertyExists(
|
||||
$new_property_id,
|
||||
!$in_assignment,
|
||||
$statements_analyzer,
|
||||
$context,
|
||||
$codebase->collect_locations
|
||||
? new CodeLocation($statements_analyzer->getSource(), $stmt)
|
||||
: null,
|
||||
)
|
||||
|| isset($new_class_storage->pseudo_property_get_types['$' . $prop_name]))
|
||||
) {
|
||||
$fq_class_name = $mixin->value;
|
||||
$lhs_type_part = $mixin;
|
||||
$class_storage = $new_class_storage;
|
||||
|
||||
if (!isset($new_class_storage->pseudo_property_get_types['$' . $prop_name])) {
|
||||
$naive_property_exists = true;
|
||||
try {
|
||||
$new_class_storage = $codebase->classlike_storage_provider->get($mixin->value);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$new_class_storage = null;
|
||||
}
|
||||
|
||||
$property_id = $new_property_id;
|
||||
if ($new_class_storage
|
||||
&& ($codebase->properties->propertyExists(
|
||||
$new_property_id,
|
||||
!$in_assignment,
|
||||
$statements_analyzer,
|
||||
$context,
|
||||
$codebase->collect_locations
|
||||
? new CodeLocation($statements_analyzer->getSource(), $stmt)
|
||||
: null,
|
||||
)
|
||||
|| isset($new_class_storage->pseudo_property_get_types['$' . $prop_name]))
|
||||
) {
|
||||
$fq_class_name = $mixin->value;
|
||||
$lhs_type_part = $mixin;
|
||||
$class_storage = $new_class_storage;
|
||||
|
||||
if (!isset($new_class_storage->pseudo_property_get_types['$' . $prop_name])) {
|
||||
$naive_property_exists = true;
|
||||
}
|
||||
|
||||
$property_id = $new_property_id;
|
||||
}
|
||||
}
|
||||
} elseif ($intersection_types !== [] && !$class_storage->final) {
|
||||
foreach ($intersection_types as $intersection_type) {
|
||||
self::analyze(
|
||||
$statements_analyzer,
|
||||
$stmt,
|
||||
$context,
|
||||
$in_assignment,
|
||||
$var_id,
|
||||
$stmt_var_id,
|
||||
$stmt_var_type,
|
||||
$intersection_type,
|
||||
$prop_name,
|
||||
$has_valid_fetch_type,
|
||||
$invalid_fetch_types,
|
||||
$is_static_access,
|
||||
);
|
||||
|
||||
if ($has_valid_fetch_type) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,6 +397,7 @@ class AtomicPropertyFetchAnalyzer
|
||||
$stmt_var_id,
|
||||
$has_magic_getter,
|
||||
$var_id,
|
||||
$has_valid_fetch_type,
|
||||
);
|
||||
|
||||
return;
|
||||
@@ -485,6 +533,8 @@ class AtomicPropertyFetchAnalyzer
|
||||
}
|
||||
|
||||
$stmt_type = $statements_analyzer->node_data->getType($stmt);
|
||||
|
||||
$has_valid_fetch_type = true;
|
||||
$statements_analyzer->node_data->setType(
|
||||
$stmt,
|
||||
Type::combineUnionTypes($class_property_type, $stmt_type),
|
||||
@@ -663,7 +713,7 @@ class AtomicPropertyFetchAnalyzer
|
||||
* If we have an explicit list of all allowed magic properties on the class, and we're
|
||||
* not in that list, fall through
|
||||
*/
|
||||
if (!($class_storage->sealed_properties || $codebase->config->seal_all_properties)
|
||||
if (!($class_storage->hasSealedProperties($codebase->config))
|
||||
&& !$override_property_visibility
|
||||
) {
|
||||
return false;
|
||||
@@ -1144,9 +1194,11 @@ class AtomicPropertyFetchAnalyzer
|
||||
bool $in_assignment,
|
||||
?string $stmt_var_id,
|
||||
bool $has_magic_getter,
|
||||
?string $var_id
|
||||
?string $var_id,
|
||||
bool &$has_valid_fetch_type
|
||||
): void {
|
||||
if ($config->use_phpdoc_property_without_magic_or_parent
|
||||
if (($config->use_phpdoc_property_without_magic_or_parent
|
||||
|| $class_storage->hasAttributeIncludingParents('AllowDynamicProperties', $codebase))
|
||||
&& isset($class_storage->pseudo_property_get_types['$' . $prop_name])
|
||||
) {
|
||||
$stmt_type = $class_storage->pseudo_property_get_types['$' . $prop_name];
|
||||
@@ -1178,6 +1230,7 @@ class AtomicPropertyFetchAnalyzer
|
||||
$context,
|
||||
);
|
||||
|
||||
$has_valid_fetch_type = true;
|
||||
$statements_analyzer->node_data->setType($stmt, $stmt_type);
|
||||
|
||||
return;
|
||||
|
||||
@@ -158,7 +158,8 @@ class IncludeAnalyzer
|
||||
|
||||
$current_file_analyzer = $statements_analyzer->getFileAnalyzer();
|
||||
|
||||
if ($current_file_analyzer->project_analyzer->fileExists($path_to_file)) {
|
||||
if ($current_file_analyzer->project_analyzer->fileExists($path_to_file)
|
||||
&& !$current_file_analyzer->project_analyzer->isDirectory($path_to_file)) {
|
||||
if ($statements_analyzer->hasParentFilePath($path_to_file)
|
||||
|| !$codebase->file_storage_provider->has($path_to_file)
|
||||
|| ($statements_analyzer->hasAlreadyRequiredFilePath($path_to_file)
|
||||
@@ -395,6 +396,18 @@ class IncludeAnalyzer
|
||||
return $file_name;
|
||||
}
|
||||
|
||||
if ((substr($file_name, 0, 2) === '.' . DIRECTORY_SEPARATOR)
|
||||
|| (substr($file_name, 0, 3) === '..' . DIRECTORY_SEPARATOR)
|
||||
) {
|
||||
$file = $current_directory . DIRECTORY_SEPARATOR . $file_name;
|
||||
|
||||
if (file_exists($file)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$paths = PATH_SEPARATOR === ':'
|
||||
? preg_split('#(?<!phar):#', get_include_path())
|
||||
: explode(PATH_SEPARATOR, get_include_path());
|
||||
|
||||
@@ -110,10 +110,16 @@ class MatchAnalyzer
|
||||
$stmt->cond->getAttributes(),
|
||||
);
|
||||
}
|
||||
} elseif ($stmt->cond instanceof PhpParser\Node\Expr\FuncCall
|
||||
|| $stmt->cond instanceof PhpParser\Node\Expr\MethodCall
|
||||
|| $stmt->cond instanceof PhpParser\Node\Expr\StaticCall
|
||||
} elseif ($stmt->cond instanceof PhpParser\Node\Expr\ClassConstFetch
|
||||
&& $stmt->cond->name instanceof PhpParser\Node\Identifier
|
||||
&& $stmt->cond->name->toString() === 'class'
|
||||
) {
|
||||
// do nothing
|
||||
} elseif ($stmt->cond instanceof PhpParser\Node\Expr\ConstFetch
|
||||
&& $stmt->cond->name->toString() === 'true'
|
||||
) {
|
||||
// do nothing
|
||||
} else {
|
||||
$switch_var_id = '$__tmp_switch__' . (int) $stmt->cond->getAttribute('startFilePos');
|
||||
|
||||
$condition_type = $statements_analyzer->node_data->getType($stmt->cond) ?? Type::getMixed();
|
||||
@@ -128,18 +134,27 @@ class MatchAnalyzer
|
||||
}
|
||||
|
||||
$arms = $stmt->arms;
|
||||
$flattened_arms = [];
|
||||
$last_arm = null;
|
||||
|
||||
foreach ($arms as $i => $arm) {
|
||||
// move default to the end
|
||||
foreach ($arms as $arm) {
|
||||
if ($arm->conds === null) {
|
||||
unset($arms[$i]);
|
||||
$arms[] = $arm;
|
||||
$last_arm = $arm;
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($arm->conds as $cond) {
|
||||
$flattened_arms[] = new PhpParser\Node\MatchArm(
|
||||
[$cond],
|
||||
$arm->body,
|
||||
$arm->getAttributes(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$arms = $flattened_arms;
|
||||
$arms = array_reverse($arms);
|
||||
|
||||
$last_arm = array_shift($arms);
|
||||
$last_arm ??= array_shift($arms);
|
||||
|
||||
if (!$last_arm) {
|
||||
IssueBuffer::maybeAdd(
|
||||
|
||||
@@ -666,17 +666,22 @@ class SimpleTypeInferer
|
||||
} elseif ($key_type->isSingleIntLiteral()) {
|
||||
$item_key_value = $key_type->getSingleIntLiteral()->value;
|
||||
|
||||
if ($item_key_value >= $array_creation_info->int_offset) {
|
||||
if ($item_key_value === $array_creation_info->int_offset) {
|
||||
if ($item_key_value <= PHP_INT_MAX
|
||||
&& $item_key_value > $array_creation_info->int_offset
|
||||
) {
|
||||
if ($item_key_value - 1 === $array_creation_info->int_offset) {
|
||||
$item_is_list_item = true;
|
||||
}
|
||||
$array_creation_info->int_offset = $item_key_value + 1;
|
||||
$array_creation_info->int_offset = $item_key_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($array_creation_info->int_offset === PHP_INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
$item_is_list_item = true;
|
||||
$item_key_value = $array_creation_info->int_offset++;
|
||||
$item_key_value = ++$array_creation_info->int_offset;
|
||||
$array_creation_info->item_key_atomic_types[] = new TLiteralInt($item_key_value);
|
||||
}
|
||||
|
||||
@@ -760,7 +765,10 @@ class SimpleTypeInferer
|
||||
$new_offset = $key;
|
||||
$array_creation_info->item_key_atomic_types[] = Type::getAtomicStringFromLiteral($new_offset);
|
||||
} else {
|
||||
$new_offset = $array_creation_info->int_offset++;
|
||||
if ($array_creation_info->int_offset === PHP_INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
$new_offset = ++$array_creation_info->int_offset;
|
||||
$array_creation_info->item_key_atomic_types[] = new TLiteralInt($new_offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ use Psalm\Issue\UnrecognizedExpression;
|
||||
use Psalm\Issue\UnsupportedReferenceUsage;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Plugin\EventHandler\Event\AfterExpressionAnalysisEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\BeforeExpressionAnalysisEvent;
|
||||
use Psalm\Storage\FunctionLikeParameter;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\TaintKind;
|
||||
@@ -80,6 +81,10 @@ class ExpressionAnalyzer
|
||||
?TemplateResult $template_result = null,
|
||||
bool $assigned_to_reference = false
|
||||
): bool {
|
||||
if (self::dispatchBeforeExpressionAnalysis($stmt, $context, $statements_analyzer) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
if (self::handleExpression(
|
||||
@@ -126,24 +131,10 @@ class ExpressionAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
$event = new AfterExpressionAnalysisEvent(
|
||||
$stmt,
|
||||
$context,
|
||||
$statements_analyzer,
|
||||
$codebase,
|
||||
[],
|
||||
);
|
||||
|
||||
if ($codebase->config->eventDispatcher->dispatchAfterExpressionAnalysis($event) === false) {
|
||||
if (self::dispatchAfterExpressionAnalysis($stmt, $context, $statements_analyzer) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file_manipulations = $event->getFileReplacements();
|
||||
|
||||
if ($file_manipulations) {
|
||||
FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -280,7 +271,7 @@ class ExpressionAnalyzer
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Expr\New_) {
|
||||
return NewAnalyzer::analyze($statements_analyzer, $stmt, $context);
|
||||
return NewAnalyzer::analyze($statements_analyzer, $stmt, $context, $template_result);
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Expr\Array_) {
|
||||
@@ -554,4 +545,60 @@ class ExpressionAnalyzer
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static function dispatchBeforeExpressionAnalysis(
|
||||
PhpParser\Node\Expr $expr,
|
||||
Context $context,
|
||||
StatementsAnalyzer $statements_analyzer
|
||||
): ?bool {
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
$event = new BeforeExpressionAnalysisEvent(
|
||||
$expr,
|
||||
$context,
|
||||
$statements_analyzer,
|
||||
$codebase,
|
||||
[],
|
||||
);
|
||||
|
||||
if ($codebase->config->eventDispatcher->dispatchBeforeExpressionAnalysis($event) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file_manipulations = $event->getFileReplacements();
|
||||
|
||||
if ($file_manipulations !== []) {
|
||||
FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function dispatchAfterExpressionAnalysis(
|
||||
PhpParser\Node\Expr $expr,
|
||||
Context $context,
|
||||
StatementsAnalyzer $statements_analyzer
|
||||
): ?bool {
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
|
||||
$event = new AfterExpressionAnalysisEvent(
|
||||
$expr,
|
||||
$context,
|
||||
$statements_analyzer,
|
||||
$codebase,
|
||||
[],
|
||||
);
|
||||
|
||||
if ($codebase->config->eventDispatcher->dispatchAfterExpressionAnalysis($event) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file_manipulations = $event->getFileReplacements();
|
||||
|
||||
if ($file_manipulations !== []) {
|
||||
FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,6 +496,7 @@ class StatementsAnalyzer extends SourceAnalyzer
|
||||
&& !($stmt instanceof PhpParser\Node\Stmt\Interface_)
|
||||
&& !($stmt instanceof PhpParser\Node\Stmt\Trait_)
|
||||
&& !($stmt instanceof PhpParser\Node\Stmt\HaltCompiler)
|
||||
&& !($stmt instanceof PhpParser\Node\Stmt\Declare_)
|
||||
) {
|
||||
if ($codebase->find_unused_variables) {
|
||||
IssueBuffer::maybeAdd(
|
||||
|
||||
@@ -2,20 +2,14 @@
|
||||
|
||||
namespace Psalm\Internal\Cli;
|
||||
|
||||
use LanguageServerProtocol\MessageType;
|
||||
use Psalm\Config;
|
||||
use Psalm\Internal\Analyzer\ProjectAnalyzer;
|
||||
use Psalm\Internal\CliUtils;
|
||||
use Psalm\Internal\Composer;
|
||||
use Psalm\Internal\ErrorHandler;
|
||||
use Psalm\Internal\Fork\PsalmRestarter;
|
||||
use Psalm\Internal\IncludeCollector;
|
||||
use Psalm\Internal\Provider\ClassLikeStorageCacheProvider;
|
||||
use Psalm\Internal\Provider\FileProvider;
|
||||
use Psalm\Internal\Provider\FileReferenceCacheProvider;
|
||||
use Psalm\Internal\Provider\FileStorageCacheProvider;
|
||||
use Psalm\Internal\Provider\ParserCacheProvider;
|
||||
use Psalm\Internal\Provider\ProjectCacheProvider;
|
||||
use Psalm\Internal\Provider\Providers;
|
||||
use Psalm\Internal\LanguageServer\ClientConfiguration;
|
||||
use Psalm\Internal\LanguageServer\LanguageServer as LanguageServerLanguageServer;
|
||||
use Psalm\Report;
|
||||
|
||||
use function array_key_exists;
|
||||
@@ -52,16 +46,21 @@ require_once __DIR__ . '/../ErrorHandler.php';
|
||||
require_once __DIR__ . '/../CliUtils.php';
|
||||
require_once __DIR__ . '/../Composer.php';
|
||||
require_once __DIR__ . '/../IncludeCollector.php';
|
||||
require_once __DIR__ . '/../LanguageServer/ClientConfiguration.php';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class LanguageServer
|
||||
{
|
||||
/** @param array<int,string> $argv */
|
||||
/**
|
||||
* @param array<int,string> $argv
|
||||
* @psalm-suppress ComplexMethod
|
||||
*/
|
||||
public static function run(array $argv): void
|
||||
{
|
||||
CliUtils::checkRuntimeRequirements();
|
||||
$clientConfiguration = new ClientConfiguration();
|
||||
gc_disable();
|
||||
ErrorHandler::install($argv);
|
||||
$valid_short_options = [
|
||||
@@ -72,7 +71,6 @@ final class LanguageServer
|
||||
];
|
||||
|
||||
$valid_long_options = [
|
||||
'clear-cache',
|
||||
'config:',
|
||||
'find-dead-code',
|
||||
'help',
|
||||
@@ -82,7 +80,17 @@ final class LanguageServer
|
||||
'tcp:',
|
||||
'tcp-server',
|
||||
'disable-on-change::',
|
||||
'use-baseline:',
|
||||
'enable-autocomplete::',
|
||||
'enable-code-actions::',
|
||||
'enable-provide-diagnostics::',
|
||||
'enable-provide-hover::',
|
||||
'enable-provide-signature-help::',
|
||||
'enable-provide-definition::',
|
||||
'show-diagnostic-warnings::',
|
||||
'in-memory::',
|
||||
'disable-xdebug::',
|
||||
'on-change-debounce-ms::',
|
||||
'use-extended-diagnostic-codes',
|
||||
'verbose',
|
||||
];
|
||||
@@ -164,12 +172,12 @@ final class LanguageServer
|
||||
--find-dead-code
|
||||
Look for dead code
|
||||
|
||||
--clear-cache
|
||||
Clears all cache files that the language server uses for this specific project
|
||||
|
||||
--use-ini-defaults
|
||||
Use PHP-provided ini defaults for memory and error display
|
||||
|
||||
--use-baseline=PATH
|
||||
Allows you to use a baseline other than the default baseline provided in your config
|
||||
|
||||
--tcp=url
|
||||
Use TCP mode (by default Psalm uses STDIO)
|
||||
|
||||
@@ -180,12 +188,39 @@ final class LanguageServer
|
||||
If added, the language server will not respond to onChange events.
|
||||
You can also specify a line count over which Psalm will not run on-change events.
|
||||
|
||||
--enable-code-actions[=BOOL]
|
||||
Enables or disables code actions. Default is true.
|
||||
|
||||
--enable-provide-diagnostics[=BOOL]
|
||||
Enables or disables providing diagnostics. Default is true.
|
||||
|
||||
--enable-autocomplete[=BOOL]
|
||||
Enables or disables autocomplete on methods and properties. Default is true.
|
||||
|
||||
--use-extended-diagnostic-codes
|
||||
--enable-provide-hover[=BOOL]
|
||||
Enables or disables providing hover. Default is true.
|
||||
|
||||
--enable-provide-signature-help[=BOOL]
|
||||
Enables or disables providing signature help. Default is true.
|
||||
|
||||
--enable-provide-definition[=BOOL]
|
||||
Enables or disables providing definition. Default is true.
|
||||
|
||||
--show-diagnostic-warnings[=BOOL]
|
||||
Enables or disables showing diagnostic warnings. Default is true.
|
||||
|
||||
--use-extended-diagnostic-codes (DEPRECATED)
|
||||
Enables sending help uri links with the code in diagnostic messages.
|
||||
|
||||
--on-change-debounce-ms=[INT]
|
||||
The number of milliseconds to debounce onChange events.
|
||||
|
||||
--disable-xdebug[=BOOL]
|
||||
Disable xdebug for performance reasons. Enable for debugging
|
||||
|
||||
--in-memory[=BOOL]
|
||||
Use in-memory mode. Default is false. Experimental.
|
||||
|
||||
--verbose
|
||||
Will send log messages to the client with information.
|
||||
|
||||
@@ -245,8 +280,14 @@ final class LanguageServer
|
||||
'blackfire',
|
||||
]);
|
||||
|
||||
// If Xdebug is enabled, restart without it
|
||||
$ini_handler->check();
|
||||
$disableXdebug = !isset($options['disable-xdebug'])
|
||||
|| !is_string($options['disable-xdebug'])
|
||||
|| strtolower($options['disable-xdebug']) !== 'false';
|
||||
|
||||
// If Xdebug is enabled, restart without it based on cli
|
||||
if ($disableXdebug) {
|
||||
$ini_handler->check();
|
||||
}
|
||||
|
||||
setlocale(LC_CTYPE, 'C');
|
||||
|
||||
@@ -259,8 +300,6 @@ final class LanguageServer
|
||||
}
|
||||
}
|
||||
|
||||
$find_unused_code = isset($options['find-dead-code']) ? 'auto' : null;
|
||||
|
||||
$config = CliUtils::initializeConfig(
|
||||
$path_to_config,
|
||||
$current_dir,
|
||||
@@ -276,58 +315,85 @@ final class LanguageServer
|
||||
|
||||
$config->setServerMode();
|
||||
|
||||
if (isset($options['clear-cache'])) {
|
||||
$inMemory = isset($options['in-memory']) &&
|
||||
is_string($options['in-memory']) &&
|
||||
strtolower($options['in-memory']) === 'true';
|
||||
|
||||
if ($inMemory) {
|
||||
$config->cache_directory = null;
|
||||
} else {
|
||||
$cache_directory = $config->getCacheDirectory();
|
||||
|
||||
if ($cache_directory !== null) {
|
||||
Config::removeCacheDirectory($cache_directory);
|
||||
}
|
||||
echo 'Cache directory deleted' . PHP_EOL;
|
||||
exit;
|
||||
}
|
||||
|
||||
$providers = new Providers(
|
||||
new FileProvider,
|
||||
new ParserCacheProvider($config),
|
||||
new FileStorageCacheProvider($config),
|
||||
new ClassLikeStorageCacheProvider($config),
|
||||
new FileReferenceCacheProvider($config),
|
||||
new ProjectCacheProvider(Composer::getLockFilePath($current_dir)),
|
||||
);
|
||||
|
||||
$project_analyzer = new ProjectAnalyzer(
|
||||
$config,
|
||||
$providers,
|
||||
);
|
||||
|
||||
if ($config->find_unused_variables) {
|
||||
$project_analyzer->getCodebase()->reportUnusedVariables();
|
||||
}
|
||||
|
||||
if ($config->find_unused_code) {
|
||||
$find_unused_code = 'auto';
|
||||
if (isset($options['use-baseline']) && is_string($options['use-baseline'])) {
|
||||
$clientConfiguration->baseline = $options['use-baseline'];
|
||||
}
|
||||
|
||||
if (isset($options['disable-on-change']) && is_numeric($options['disable-on-change'])) {
|
||||
$project_analyzer->onchange_line_limit = (int) $options['disable-on-change'];
|
||||
$clientConfiguration->onchangeLineLimit = (int) $options['disable-on-change'];
|
||||
}
|
||||
|
||||
$project_analyzer->provide_completion = !isset($options['enable-autocomplete'])
|
||||
if (isset($options['on-change-debounce-ms']) && is_numeric($options['on-change-debounce-ms'])) {
|
||||
$clientConfiguration->onChangeDebounceMs = (int) $options['on-change-debounce-ms'];
|
||||
}
|
||||
|
||||
$clientConfiguration->provideDefinition = !isset($options['enable-provide-definition'])
|
||||
|| !is_string($options['enable-provide-definition'])
|
||||
|| strtolower($options['enable-provide-definition']) !== 'false';
|
||||
|
||||
$clientConfiguration->provideSignatureHelp = !isset($options['enable-provide-signature-help'])
|
||||
|| !is_string($options['enable-provide-signature-help'])
|
||||
|| strtolower($options['enable-provide-signature-help']) !== 'false';
|
||||
|
||||
$clientConfiguration->provideHover = !isset($options['enable-provide-hover'])
|
||||
|| !is_string($options['enable-provide-hover'])
|
||||
|| strtolower($options['enable-provide-hover']) !== 'false';
|
||||
|
||||
$clientConfiguration->provideDiagnostics = !isset($options['enable-provide-diagnostics'])
|
||||
|| !is_string($options['enable-provide-diagnostics'])
|
||||
|| strtolower($options['enable-provide-diagnostics']) !== 'false';
|
||||
|
||||
$clientConfiguration->provideCodeActions = !isset($options['enable-code-actions'])
|
||||
|| !is_string($options['enable-code-actions'])
|
||||
|| strtolower($options['enable-code-actions']) !== 'false';
|
||||
|
||||
$clientConfiguration->provideCompletion = !isset($options['enable-autocomplete'])
|
||||
|| !is_string($options['enable-autocomplete'])
|
||||
|| strtolower($options['enable-autocomplete']) !== 'false';
|
||||
|
||||
if ($find_unused_code) {
|
||||
$project_analyzer->getCodebase()->reportUnusedCode($find_unused_code);
|
||||
}
|
||||
$clientConfiguration->hideWarnings = !(
|
||||
!isset($options['show-diagnostic-warnings'])
|
||||
|| !is_string($options['show-diagnostic-warnings'])
|
||||
|| strtolower($options['show-diagnostic-warnings']) !== 'false'
|
||||
);
|
||||
|
||||
if (isset($options['use-extended-diagnostic-codes'])) {
|
||||
$project_analyzer->language_server_use_extended_diagnostic_codes = true;
|
||||
/**
|
||||
* if ($config->find_unused_variables) {
|
||||
* $project_analyzer->getCodebase()->reportUnusedVariables();
|
||||
* }
|
||||
*/
|
||||
|
||||
$find_unused_code = isset($options['find-dead-code']) ? 'auto' : null;
|
||||
if ($config->find_unused_code) {
|
||||
$find_unused_code = 'auto';
|
||||
}
|
||||
if ($find_unused_code) {
|
||||
$clientConfiguration->findUnusedCode = $find_unused_code;
|
||||
}
|
||||
|
||||
if (isset($options['verbose'])) {
|
||||
$project_analyzer->language_server_verbose = true;
|
||||
$clientConfiguration->logLevel = $options['verbose'] ? MessageType::LOG : MessageType::INFO;
|
||||
} else {
|
||||
$clientConfiguration->logLevel = MessageType::INFO;
|
||||
}
|
||||
|
||||
$project_analyzer->server($options['tcp'] ?? null, isset($options['tcp-server']));
|
||||
$clientConfiguration->TCPServerAddress = $options['tcp'] ?? null;
|
||||
$clientConfiguration->TCPServerMode = isset($options['tcp-server']);
|
||||
|
||||
LanguageServerLanguageServer::run($config, $clientConfiguration, $current_dir, $inMemory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,15 +57,12 @@ use function getopt;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function ini_get;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_numeric;
|
||||
use function is_scalar;
|
||||
use function is_string;
|
||||
use function json_encode;
|
||||
use function max;
|
||||
use function microtime;
|
||||
use function opcache_get_status;
|
||||
use function parse_url;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
@@ -190,7 +187,7 @@ final class Psalm
|
||||
|
||||
self::validateCliArguments($args);
|
||||
|
||||
self::setMemoryLimit($options);
|
||||
CliUtils::setMemoryLimit($options);
|
||||
|
||||
self::syncShortOptions($options);
|
||||
|
||||
@@ -463,29 +460,6 @@ final class Psalm
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string,string|false|list<mixed>> $options
|
||||
*/
|
||||
private static function setMemoryLimit(array $options): void
|
||||
{
|
||||
if (!array_key_exists('use-ini-defaults', $options)) {
|
||||
ini_set('display_errors', 'stderr');
|
||||
ini_set('display_startup_errors', '1');
|
||||
|
||||
$memoryLimit = (8 * 1_024 * 1_024 * 1_024);
|
||||
|
||||
if (array_key_exists('memory-limit', $options)) {
|
||||
$memoryLimit = $options['memory-limit'];
|
||||
|
||||
if (!is_scalar($memoryLimit)) {
|
||||
throw new ConfigException('Invalid memory limit specified.');
|
||||
}
|
||||
}
|
||||
|
||||
ini_set('memory_limit', (string) $memoryLimit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $args
|
||||
*/
|
||||
@@ -923,11 +897,7 @@ final class Psalm
|
||||
// If Xdebug is enabled, restart without it
|
||||
$ini_handler->check();
|
||||
|
||||
if (!function_exists('opcache_get_status')
|
||||
|| !($opcache_status = opcache_get_status(false))
|
||||
|| !isset($opcache_status['opcache_enabled'])
|
||||
|| !$opcache_status['opcache_enabled']
|
||||
) {
|
||||
if (!function_exists('opcache_get_status')) {
|
||||
$progress->write(PHP_EOL
|
||||
. 'Install the opcache extension to make use of JIT on PHP 8.0+ for a 20%+ performance boost!'
|
||||
. PHP_EOL . PHP_EOL);
|
||||
@@ -1273,6 +1243,9 @@ final class Psalm
|
||||
--php-version=PHP_VERSION
|
||||
Explicitly set PHP version to analyse code against.
|
||||
|
||||
--error-level=ERROR_LEVEL
|
||||
Set the error reporting level
|
||||
|
||||
Surfacing issues:
|
||||
--show-info[=BOOLEAN]
|
||||
Show non-exception parser findings (defaults to false).
|
||||
|
||||
@@ -43,7 +43,6 @@ use function getcwd;
|
||||
use function getopt;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_dir;
|
||||
use function is_numeric;
|
||||
@@ -89,6 +88,7 @@ final class Psalter
|
||||
'add-newline-between-docblock-annotations:',
|
||||
'no-cache',
|
||||
'no-progress',
|
||||
'memory-limit:',
|
||||
];
|
||||
|
||||
/** @param array<int,string> $argv */
|
||||
@@ -100,8 +100,6 @@ final class Psalter
|
||||
|
||||
ErrorHandler::install($argv);
|
||||
|
||||
self::setMemoryLimit();
|
||||
|
||||
$args = array_slice($argv, 1);
|
||||
|
||||
// get options from command line
|
||||
@@ -109,6 +107,8 @@ final class Psalter
|
||||
|
||||
self::validateCliArguments($args);
|
||||
|
||||
CliUtils::setMemoryLimit($options);
|
||||
|
||||
self::syncShortOptions($options);
|
||||
|
||||
if (isset($options['c']) && is_array($options['c'])) {
|
||||
@@ -442,15 +442,6 @@ final class Psalter
|
||||
IssueBuffer::finish($project_analyzer, false, $start_time);
|
||||
}
|
||||
|
||||
private static function setMemoryLimit(): void
|
||||
{
|
||||
$memLimit = CliUtils::getMemoryLimitInBytes();
|
||||
// Magic number is 4096M in bytes
|
||||
if ($memLimit > 0 && $memLimit < 8 * 1_024 * 1_024 * 1_024) {
|
||||
ini_set('memory_limit', (string) (8 * 1_024 * 1_024 * 1_024));
|
||||
}
|
||||
}
|
||||
|
||||
/** @param array<int,string> $args */
|
||||
private static function validateCliArguments(array $args): void
|
||||
{
|
||||
|
||||
@@ -14,8 +14,8 @@ use Psalm\Report;
|
||||
use RuntimeException;
|
||||
|
||||
use function array_filter;
|
||||
use function array_key_exists;
|
||||
use function array_slice;
|
||||
use function assert;
|
||||
use function count;
|
||||
use function define;
|
||||
use function dirname;
|
||||
@@ -27,13 +27,13 @@ use function file_put_contents;
|
||||
use function fwrite;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function ini_get;
|
||||
use function ini_set;
|
||||
use function is_array;
|
||||
use function is_dir;
|
||||
use function is_scalar;
|
||||
use function is_string;
|
||||
use function json_decode;
|
||||
use function preg_last_error_msg;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function preg_split;
|
||||
use function realpath;
|
||||
@@ -41,7 +41,6 @@ use function stream_get_meta_data;
|
||||
use function stream_set_blocking;
|
||||
use function strlen;
|
||||
use function strpos;
|
||||
use function strtoupper;
|
||||
use function substr;
|
||||
use function substr_replace;
|
||||
use function trim;
|
||||
@@ -446,38 +445,27 @@ final class CliUtils
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
* @param array<string,string|false|list<mixed>> $options
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public static function getMemoryLimitInBytes(): int
|
||||
public static function setMemoryLimit(array $options): void
|
||||
{
|
||||
return self::convertMemoryLimitToBytes(ini_get('memory_limit'));
|
||||
}
|
||||
if (!array_key_exists('use-ini-defaults', $options)) {
|
||||
ini_set('display_errors', 'stderr');
|
||||
ini_set('display_startup_errors', '1');
|
||||
|
||||
/** @psalm-pure */
|
||||
public static function convertMemoryLimitToBytes(string $limit): int
|
||||
{
|
||||
// for unlimited = -1
|
||||
if ($limit < 0) {
|
||||
return -1;
|
||||
}
|
||||
$memoryLimit = (8 * 1_024 * 1_024 * 1_024);
|
||||
|
||||
if (preg_match('/^(\d+)(\D?)$/', $limit, $matches)) {
|
||||
assert(isset($matches[1]));
|
||||
$limit = (int)$matches[1];
|
||||
switch (strtoupper($matches[2] ?? '')) {
|
||||
case 'G':
|
||||
$limit *= 1_024 * 1_024 * 1_024;
|
||||
break;
|
||||
case 'M':
|
||||
$limit *= 1_024 * 1_024;
|
||||
break;
|
||||
case 'K':
|
||||
$limit *= 1_024;
|
||||
break;
|
||||
if (array_key_exists('memory-limit', $options)) {
|
||||
$memoryLimit = $options['memory-limit'];
|
||||
|
||||
if (!is_scalar($memoryLimit)) {
|
||||
throw new ConfigException('Invalid memory limit specified.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (int)$limit;
|
||||
ini_set('memory_limit', (string) $memoryLimit);
|
||||
}
|
||||
}
|
||||
|
||||
public static function initPhpVersion(array $options, Config $config, ProjectAnalyzer $project_analyzer): void
|
||||
|
||||
@@ -9,25 +9,23 @@ use Psalm\Type\Atomic;
|
||||
use Psalm\Type\Atomic\TMixed;
|
||||
|
||||
use function array_merge;
|
||||
use function array_values;
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class ClassConstantByWildcardResolver
|
||||
{
|
||||
private StorageByPatternResolver $resolver;
|
||||
private Codebase $codebase;
|
||||
|
||||
public function __construct(Codebase $codebase)
|
||||
{
|
||||
$this->resolver = new StorageByPatternResolver();
|
||||
$this->codebase = $codebase;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<Atomic>|null
|
||||
* @return non-empty-array<array-key,Atomic>|null
|
||||
*/
|
||||
public function resolve(string $class_name, string $constant_pattern): ?array
|
||||
{
|
||||
@@ -35,24 +33,27 @@ final class ClassConstantByWildcardResolver
|
||||
return null;
|
||||
}
|
||||
|
||||
$constant_regex_pattern = sprintf('#^%s$#', str_replace('*', '.*', $constant_pattern));
|
||||
$classlike_storage = $this->codebase->classlike_storage_provider->get($class_name);
|
||||
|
||||
$class_like_storage = $this->codebase->classlike_storage_provider->get($class_name);
|
||||
$matched_class_constant_types = [];
|
||||
|
||||
foreach ($class_like_storage->constants as $constant => $class_constant_storage) {
|
||||
if (preg_match($constant_regex_pattern, $constant) === 0) {
|
||||
continue;
|
||||
}
|
||||
$constants = $this->resolver->resolveConstants(
|
||||
$classlike_storage,
|
||||
$constant_pattern,
|
||||
);
|
||||
|
||||
$types = [];
|
||||
foreach ($constants as $class_constant_storage) {
|
||||
if (! $class_constant_storage->type) {
|
||||
$matched_class_constant_types[] = [new TMixed()];
|
||||
$types[] = [new TMixed()];
|
||||
continue;
|
||||
}
|
||||
|
||||
$matched_class_constant_types[] = $class_constant_storage->type->getAtomicTypes();
|
||||
$types[] = $class_constant_storage->type->getAtomicTypes();
|
||||
}
|
||||
|
||||
return array_values(array_merge([], ...$matched_class_constant_types));
|
||||
if ($types === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array_merge([], ...$types);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ use ReflectionProperty;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function array_filter;
|
||||
use function array_keys;
|
||||
use function array_merge;
|
||||
use function array_pop;
|
||||
use function count;
|
||||
@@ -1603,8 +1604,7 @@ class ClassLikes
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReflectionProperty::IS_PUBLIC|ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PRIVATE
|
||||
* $visibility
|
||||
* @param ReflectionProperty::IS_PUBLIC|ReflectionProperty::IS_PROTECTED|ReflectionProperty::IS_PRIVATE $visibility
|
||||
*/
|
||||
public function getClassConstantType(
|
||||
string $class_name,
|
||||
@@ -1612,7 +1612,8 @@ class ClassLikes
|
||||
int $visibility,
|
||||
?StatementsAnalyzer $statements_analyzer = null,
|
||||
array $visited_constant_ids = [],
|
||||
bool $late_static_binding = false
|
||||
bool $late_static_binding = false,
|
||||
bool $in_value_of_context = false
|
||||
): ?Union {
|
||||
$class_name = strtolower($class_name);
|
||||
|
||||
@@ -1622,41 +1623,42 @@ class ClassLikes
|
||||
|
||||
$storage = $this->classlike_storage_provider->get($class_name);
|
||||
|
||||
if (isset($storage->constants[$constant_name])) {
|
||||
$constant_storage = $storage->constants[$constant_name];
|
||||
$enum_types = null;
|
||||
|
||||
if ($visibility === ReflectionProperty::IS_PUBLIC
|
||||
&& $constant_storage->visibility !== ClassLikeAnalyzer::VISIBILITY_PUBLIC
|
||||
) {
|
||||
return null;
|
||||
if ($storage->is_enum) {
|
||||
$enum_types = $this->getEnumType(
|
||||
$storage,
|
||||
$constant_name,
|
||||
);
|
||||
|
||||
if ($in_value_of_context) {
|
||||
return $enum_types;
|
||||
}
|
||||
|
||||
if ($visibility === ReflectionProperty::IS_PROTECTED
|
||||
&& $constant_storage->visibility !== ClassLikeAnalyzer::VISIBILITY_PUBLIC
|
||||
&& $constant_storage->visibility !== ClassLikeAnalyzer::VISIBILITY_PROTECTED
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($constant_storage->unresolved_node) {
|
||||
/** @psalm-suppress InaccessibleProperty Lazy resolution */
|
||||
$constant_storage->inferred_type = new Union([ConstantTypeResolver::resolve(
|
||||
$this,
|
||||
$constant_storage->unresolved_node,
|
||||
$statements_analyzer,
|
||||
$visited_constant_ids,
|
||||
)]);
|
||||
if ($constant_storage->type === null || !$constant_storage->type->from_docblock) {
|
||||
/** @psalm-suppress InaccessibleProperty Lazy resolution */
|
||||
$constant_storage->type = $constant_storage->inferred_type;
|
||||
}
|
||||
}
|
||||
|
||||
return $late_static_binding ? $constant_storage->type : ($constant_storage->inferred_type ?? null);
|
||||
} elseif (isset($storage->enum_cases[$constant_name])) {
|
||||
return new Union([new TEnumCase($storage->name, $constant_name)]);
|
||||
}
|
||||
return null;
|
||||
|
||||
$constant_types = $this->getConstantType(
|
||||
$storage,
|
||||
$constant_name,
|
||||
$visibility,
|
||||
$statements_analyzer,
|
||||
$visited_constant_ids,
|
||||
$late_static_binding,
|
||||
);
|
||||
|
||||
$types = [];
|
||||
if ($enum_types !== null) {
|
||||
$types = array_merge($types, $enum_types->getAtomicTypes());
|
||||
}
|
||||
|
||||
if ($constant_types !== null) {
|
||||
$types = array_merge($types, $constant_types->getAtomicTypes());
|
||||
}
|
||||
|
||||
if ($types === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Union($types);
|
||||
}
|
||||
|
||||
private function checkMethodReferences(ClassLikeStorage $classlike_storage, Methods $methods): void
|
||||
@@ -2366,4 +2368,113 @@ class ClassLikes
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function getConstantType(
|
||||
ClassLikeStorage $class_like_storage,
|
||||
string $constant_name,
|
||||
int $visibility,
|
||||
?StatementsAnalyzer $statements_analyzer,
|
||||
array $visited_constant_ids,
|
||||
bool $late_static_binding
|
||||
): ?Union {
|
||||
$constant_resolver = new StorageByPatternResolver();
|
||||
$resolved_constants = $constant_resolver->resolveConstants(
|
||||
$class_like_storage,
|
||||
$constant_name,
|
||||
);
|
||||
|
||||
$filtered_constants_by_visibility = array_filter(
|
||||
$resolved_constants,
|
||||
fn(ClassConstantStorage $resolved_constant) => $this->filterConstantNameByVisibility(
|
||||
$resolved_constant,
|
||||
$visibility,
|
||||
)
|
||||
);
|
||||
|
||||
if ($filtered_constants_by_visibility === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$new_atomic_types = [];
|
||||
|
||||
foreach ($filtered_constants_by_visibility as $filtered_constant_name => $constant_storage) {
|
||||
if (!isset($class_like_storage->constants[$filtered_constant_name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($constant_storage->unresolved_node) {
|
||||
/** @psalm-suppress InaccessibleProperty Lazy resolution */
|
||||
$constant_storage->inferred_type = new Union([ConstantTypeResolver::resolve(
|
||||
$this,
|
||||
$constant_storage->unresolved_node,
|
||||
$statements_analyzer,
|
||||
$visited_constant_ids,
|
||||
)]);
|
||||
|
||||
if ($constant_storage->type === null || !$constant_storage->type->from_docblock) {
|
||||
/** @psalm-suppress InaccessibleProperty Lazy resolution */
|
||||
$constant_storage->type = $constant_storage->inferred_type;
|
||||
}
|
||||
}
|
||||
|
||||
$constant_type = $late_static_binding
|
||||
? $constant_storage->type
|
||||
: ($constant_storage->inferred_type ?? null);
|
||||
|
||||
if ($constant_type === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$new_atomic_types[] = $constant_type->getAtomicTypes();
|
||||
}
|
||||
|
||||
if ($new_atomic_types === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Union(array_merge([], ...$new_atomic_types));
|
||||
}
|
||||
|
||||
private function getEnumType(
|
||||
ClassLikeStorage $class_like_storage,
|
||||
string $constant_name
|
||||
): ?Union {
|
||||
$constant_resolver = new StorageByPatternResolver();
|
||||
$resolved_enums = $constant_resolver->resolveEnums(
|
||||
$class_like_storage,
|
||||
$constant_name,
|
||||
);
|
||||
|
||||
if ($resolved_enums === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$types = [];
|
||||
foreach (array_keys($resolved_enums) as $enum_case_name) {
|
||||
$types[$enum_case_name] = new TEnumCase($class_like_storage->name, $enum_case_name);
|
||||
}
|
||||
|
||||
return new Union($types);
|
||||
}
|
||||
|
||||
private function filterConstantNameByVisibility(
|
||||
ClassConstantStorage $constant_storage,
|
||||
int $visibility
|
||||
): bool {
|
||||
|
||||
if ($visibility === ReflectionProperty::IS_PUBLIC
|
||||
&& $constant_storage->visibility !== ClassLikeAnalyzer::VISIBILITY_PUBLIC
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($visibility === ReflectionProperty::IS_PROTECTED
|
||||
&& $constant_storage->visibility !== ClassLikeAnalyzer::VISIBILITY_PUBLIC
|
||||
&& $constant_storage->visibility !== ClassLikeAnalyzer::VISIBILITY_PROTECTED
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ use Psalm\Internal\Scanner\UnresolvedConstant\ArraySpread;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\ArrayValue;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\ClassConstant;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\Constant;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\EnumNameFetch;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\EnumPropertyFetch;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\EnumValueFetch;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedAdditionOp;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedBinaryOp;
|
||||
@@ -331,6 +334,24 @@ class ConstantTypeResolver
|
||||
}
|
||||
}
|
||||
|
||||
if ($c instanceof EnumPropertyFetch) {
|
||||
if ($classlikes->enumExists($c->fqcln)) {
|
||||
$enum_storage = $classlikes->getStorageFor($c->fqcln);
|
||||
if (isset($enum_storage->enum_cases[$c->case])) {
|
||||
if ($c instanceof EnumValueFetch) {
|
||||
$value = $enum_storage->enum_cases[$c->case]->value;
|
||||
if (is_string($value)) {
|
||||
return Type::getString($value)->getSingleAtomic();
|
||||
} elseif (is_int($value)) {
|
||||
return Type::getInt(false, $value)->getSingleAtomic();
|
||||
}
|
||||
} elseif ($c instanceof EnumNameFetch) {
|
||||
return Type::getString($c->case)->getSingleAtomic();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new TMixed;
|
||||
}
|
||||
|
||||
|
||||
@@ -825,8 +825,6 @@ class Methods
|
||||
return null;
|
||||
}
|
||||
|
||||
$candidate_type = null;
|
||||
|
||||
foreach ($class_storage->overridden_method_ids[$appearing_method_name] as $overridden_method_id) {
|
||||
$overridden_storage = $this->getStorage($overridden_method_id);
|
||||
|
||||
|
||||
@@ -920,8 +920,8 @@ class Populator
|
||||
$fq_class_name = $storage->name;
|
||||
$fq_class_name_lc = strtolower($fq_class_name);
|
||||
|
||||
if ($parent_storage->sealed_methods) {
|
||||
$storage->sealed_methods = true;
|
||||
if ($parent_storage->sealed_methods !== null) {
|
||||
$storage->sealed_methods = $parent_storage->sealed_methods;
|
||||
}
|
||||
|
||||
// register where they appear (can never be in a trait)
|
||||
@@ -1032,8 +1032,8 @@ class Populator
|
||||
ClassLikeStorage $storage,
|
||||
ClassLikeStorage $parent_storage
|
||||
): void {
|
||||
if ($parent_storage->sealed_properties) {
|
||||
$storage->sealed_properties = true;
|
||||
if ($parent_storage->sealed_properties !== null) {
|
||||
$storage->sealed_properties = $parent_storage->sealed_properties;
|
||||
}
|
||||
|
||||
// register where they appear (can never be in a trait)
|
||||
|
||||
@@ -291,6 +291,7 @@ class Scanner
|
||||
private function shouldScan(string $file_path): bool
|
||||
{
|
||||
return $this->file_provider->fileExists($file_path)
|
||||
&& !$this->file_provider->isDirectory($file_path)
|
||||
&& (!isset($this->scanned_files[$file_path])
|
||||
|| (isset($this->files_to_deep_scan[$file_path]) && !$this->scanned_files[$file_path]));
|
||||
}
|
||||
|
||||
87
vendor/vimeo/psalm/src/Psalm/Internal/Codebase/StorageByPatternResolver.php
vendored
Normal file
87
vendor/vimeo/psalm/src/Psalm/Internal/Codebase/StorageByPatternResolver.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psalm\Internal\Codebase;
|
||||
|
||||
use Psalm\Storage\ClassConstantStorage;
|
||||
use Psalm\Storage\ClassLikeStorage;
|
||||
use Psalm\Storage\EnumCaseStorage;
|
||||
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function str_replace;
|
||||
use function strpos;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class StorageByPatternResolver
|
||||
{
|
||||
public const RESOLVE_CONSTANTS = 1;
|
||||
public const RESOLVE_ENUMS = 2;
|
||||
|
||||
/**
|
||||
* @return array<string,ClassConstantStorage>
|
||||
*/
|
||||
public function resolveConstants(
|
||||
ClassLikeStorage $class_like_storage,
|
||||
string $pattern
|
||||
): array {
|
||||
$constants = $class_like_storage->constants;
|
||||
|
||||
if (strpos($pattern, '*') === false) {
|
||||
if (isset($constants[$pattern])) {
|
||||
return [$pattern => $constants[$pattern]];
|
||||
}
|
||||
|
||||
return [];
|
||||
} elseif ($pattern === '*') {
|
||||
return $constants;
|
||||
}
|
||||
|
||||
$regex_pattern = sprintf('#^%s$#', str_replace('*', '.*?', $pattern));
|
||||
$matched_constants = [];
|
||||
|
||||
foreach ($constants as $constant => $class_constant_storage) {
|
||||
if (preg_match($regex_pattern, $constant) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matched_constants[$constant] = $class_constant_storage;
|
||||
}
|
||||
|
||||
return $matched_constants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,EnumCaseStorage>
|
||||
*/
|
||||
public function resolveEnums(
|
||||
ClassLikeStorage $class_like_storage,
|
||||
string $pattern
|
||||
): array {
|
||||
$enum_cases = $class_like_storage->enum_cases;
|
||||
if (strpos($pattern, '*') === false) {
|
||||
if (isset($enum_cases[$pattern])) {
|
||||
return [$pattern => $enum_cases[$pattern]];
|
||||
}
|
||||
|
||||
return [];
|
||||
} elseif ($pattern === '*') {
|
||||
return $enum_cases;
|
||||
}
|
||||
|
||||
$regex_pattern = sprintf('#^%s$#', str_replace('*', '.*?', $pattern));
|
||||
$matched_enums = [];
|
||||
foreach ($enum_cases as $enum_case_name => $enum_case_storage) {
|
||||
if (preg_match($regex_pattern, $enum_case_name) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matched_enums[$enum_case_name] = $enum_case_storage;
|
||||
}
|
||||
|
||||
return $matched_enums;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ use Psalm\Plugin\EventHandler\AfterFunctionLikeAnalysisInterface;
|
||||
use Psalm\Plugin\EventHandler\AfterMethodCallAnalysisInterface;
|
||||
use Psalm\Plugin\EventHandler\AfterStatementAnalysisInterface;
|
||||
use Psalm\Plugin\EventHandler\BeforeAddIssueInterface;
|
||||
use Psalm\Plugin\EventHandler\BeforeExpressionAnalysisInterface;
|
||||
use Psalm\Plugin\EventHandler\BeforeFileAnalysisInterface;
|
||||
use Psalm\Plugin\EventHandler\BeforeStatementAnalysisInterface;
|
||||
use Psalm\Plugin\EventHandler\Event\AddRemoveTaintsEvent;
|
||||
@@ -32,6 +33,7 @@ use Psalm\Plugin\EventHandler\Event\AfterFunctionLikeAnalysisEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\AfterMethodCallAnalysisEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\AfterStatementAnalysisEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\BeforeAddIssueEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\BeforeExpressionAnalysisEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\BeforeFileAnalysisEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\BeforeStatementAnalysisEvent;
|
||||
use Psalm\Plugin\EventHandler\Event\StringInterpreterEvent;
|
||||
@@ -77,6 +79,13 @@ class EventDispatcher
|
||||
*/
|
||||
public array $after_every_function_checks = [];
|
||||
|
||||
/**
|
||||
* Static methods to be called before expression checks are completed
|
||||
*
|
||||
* @var list<class-string<BeforeExpressionAnalysisInterface>>
|
||||
*/
|
||||
public array $before_expression_checks = [];
|
||||
|
||||
/**
|
||||
* Static methods to be called after expression checks have completed
|
||||
*
|
||||
@@ -197,6 +206,10 @@ class EventDispatcher
|
||||
$this->after_every_function_checks[] = $class;
|
||||
}
|
||||
|
||||
if (is_subclass_of($class, BeforeExpressionAnalysisInterface::class)) {
|
||||
$this->before_expression_checks[] = $class;
|
||||
}
|
||||
|
||||
if (is_subclass_of($class, AfterExpressionAnalysisInterface::class)) {
|
||||
$this->after_expression_checks[] = $class;
|
||||
}
|
||||
@@ -284,6 +297,17 @@ class EventDispatcher
|
||||
}
|
||||
}
|
||||
|
||||
public function dispatchBeforeExpressionAnalysis(BeforeExpressionAnalysisEvent $event): ?bool
|
||||
{
|
||||
foreach ($this->before_expression_checks as $handler) {
|
||||
if ($handler::beforeExpressionAnalysis($event) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function dispatchAfterExpressionAnalysis(AfterExpressionAnalysisEvent $event): ?bool
|
||||
{
|
||||
foreach ($this->after_expression_checks as $handler) {
|
||||
|
||||
@@ -137,7 +137,7 @@ class FunctionDocblockManipulator
|
||||
if ($param->type) {
|
||||
$this->param_typehint_offsets[$param->var->name] = [
|
||||
(int) $param->type->getAttribute('startFilePos'),
|
||||
(int) $param->type->getAttribute('endFilePos'),
|
||||
(int) $param->type->getAttribute('endFilePos') + 1,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ class PsalmRestarter extends XdebugHandler
|
||||
'jit_buffer_size' => 512 * 1024 * 1024,
|
||||
'optimization_level' => '0x7FFEBFFF',
|
||||
'preload' => '',
|
||||
'log_verbosity_level' => 0,
|
||||
];
|
||||
|
||||
private bool $required = false;
|
||||
@@ -70,6 +71,7 @@ class PsalmRestarter extends XdebugHandler
|
||||
$opcache_settings = [
|
||||
'enable_cli' => in_array(ini_get('opcache.enable_cli'), ['1', 'true', true, 1]),
|
||||
'jit' => (int) ini_get('opcache.jit'),
|
||||
'log_verbosity_level' => (int) ini_get('opcache.log_verbosity_level'),
|
||||
'optimization_level' => (string) ini_get('opcache.optimization_level'),
|
||||
'preload' => (string) ini_get('opcache.preload'),
|
||||
'jit_buffer_size' => self::toBytes(ini_get('opcache.jit_buffer_size')),
|
||||
@@ -146,6 +148,7 @@ class PsalmRestarter extends XdebugHandler
|
||||
'-dopcache.jit=1205',
|
||||
'-dopcache.optimization_level=0x7FFEBFFF',
|
||||
'-dopcache.preload=',
|
||||
'-dopcache.log_verbosity_level=0',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,15 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace Psalm\Internal\LanguageServer\Client;
|
||||
|
||||
use Amp\Promise;
|
||||
use Generator;
|
||||
use JsonMapper;
|
||||
use LanguageServerProtocol\Diagnostic;
|
||||
use LanguageServerProtocol\TextDocumentIdentifier;
|
||||
use LanguageServerProtocol\TextDocumentItem;
|
||||
use Psalm\Internal\LanguageServer\ClientHandler;
|
||||
|
||||
use function Amp\call;
|
||||
use Psalm\Internal\LanguageServer\LanguageServer;
|
||||
|
||||
/**
|
||||
* Provides method handlers for all textDocument/* methods
|
||||
@@ -23,12 +17,12 @@ class TextDocument
|
||||
{
|
||||
private ClientHandler $handler;
|
||||
|
||||
private JsonMapper $mapper;
|
||||
private LanguageServer $server;
|
||||
|
||||
public function __construct(ClientHandler $handler, JsonMapper $mapper)
|
||||
public function __construct(ClientHandler $handler, LanguageServer $server)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
$this->mapper = $mapper;
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,40 +30,18 @@ class TextDocument
|
||||
*
|
||||
* @param Diagnostic[] $diagnostics
|
||||
*/
|
||||
public function publishDiagnostics(string $uri, array $diagnostics): void
|
||||
public function publishDiagnostics(string $uri, array $diagnostics, ?int $version = null): void
|
||||
{
|
||||
if (!$this->server->client->clientConfiguration->provideDiagnostics) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->server->logDebug("textDocument/publishDiagnostics");
|
||||
|
||||
$this->handler->notify('textDocument/publishDiagnostics', [
|
||||
'uri' => $uri,
|
||||
'diagnostics' => $diagnostics,
|
||||
'version' => $version,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The content request is sent from a server to a client
|
||||
* to request the current content of a text document identified by the URI
|
||||
*
|
||||
* @param TextDocumentIdentifier $textDocument The document to get the content for
|
||||
* @return Promise<TextDocumentItem> The document's current content
|
||||
* @psalm-suppress MixedReturnTypeCoercion due to Psalm bug
|
||||
*/
|
||||
public function xcontent(TextDocumentIdentifier $textDocument): Promise
|
||||
{
|
||||
return call(
|
||||
/**
|
||||
* @return Generator<int, Promise<object>, object, TextDocumentItem>
|
||||
*/
|
||||
function () use ($textDocument) {
|
||||
/** @var Promise<object> */
|
||||
$promise = $this->handler->request(
|
||||
'textDocument/xcontent',
|
||||
['textDocument' => $textDocument],
|
||||
);
|
||||
|
||||
$result = yield $promise;
|
||||
|
||||
/** @var TextDocumentItem */
|
||||
return $this->mapper->map($result, new TextDocumentItem);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
59
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Workspace.php
vendored
Normal file
59
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Client/Workspace.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psalm\Internal\LanguageServer\Client;
|
||||
|
||||
use Amp\Promise;
|
||||
use JsonMapper;
|
||||
use Psalm\Internal\LanguageServer\ClientHandler;
|
||||
use Psalm\Internal\LanguageServer\LanguageServer;
|
||||
|
||||
/**
|
||||
* Provides method handlers for all textDocument/* methods
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class Workspace
|
||||
{
|
||||
private ClientHandler $handler;
|
||||
|
||||
/**
|
||||
* @psalm-suppress UnusedProperty
|
||||
*/
|
||||
private JsonMapper $mapper;
|
||||
|
||||
private LanguageServer $server;
|
||||
|
||||
public function __construct(ClientHandler $handler, JsonMapper $mapper, LanguageServer $server)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
$this->mapper = $mapper;
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
/**
|
||||
* The workspace/configuration request is sent from the server to the client to
|
||||
* fetch configuration settings from the client. The request can fetch several
|
||||
* configuration settings in one roundtrip. The order of the returned configuration
|
||||
* settings correspond to the order of the passed ConfigurationItems (e.g. the first
|
||||
* item in the response is the result for the first configuration item in the params).
|
||||
*
|
||||
* @param string $section The configuration section asked for.
|
||||
* @param string|null $scopeUri The scope to get the configuration section for.
|
||||
*/
|
||||
public function requestConfiguration(string $section, ?string $scopeUri = null): Promise
|
||||
{
|
||||
$this->server->logDebug("workspace/configuration");
|
||||
|
||||
/** @var Promise<object> */
|
||||
return $this->handler->request('workspace/configuration', [
|
||||
'items' => [
|
||||
[
|
||||
'section' => $section,
|
||||
'scopeUri' => $scopeUri,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
129
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/ClientConfiguration.php
vendored
Normal file
129
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/ClientConfiguration.php
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psalm\Internal\LanguageServer;
|
||||
|
||||
use LanguageServerProtocol\MessageType;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ClientConfiguration
|
||||
{
|
||||
|
||||
/**
|
||||
* Location of Baseline file
|
||||
*/
|
||||
public ?string $baseline = null;
|
||||
|
||||
/**
|
||||
* TCP Server Address
|
||||
*/
|
||||
public ?string $TCPServerAddress = null;
|
||||
|
||||
/**
|
||||
* Use TCP in server mode (default is client)
|
||||
*/
|
||||
public ?bool $TCPServerMode = null;
|
||||
|
||||
/**
|
||||
* Hide Warnings or not
|
||||
*/
|
||||
public ?bool $hideWarnings = null;
|
||||
|
||||
/**
|
||||
* Provide Completion or not
|
||||
*/
|
||||
public ?bool $provideCompletion = null;
|
||||
|
||||
/**
|
||||
* Provide GoTo Definitions or not
|
||||
*/
|
||||
public ?bool $provideDefinition = null;
|
||||
|
||||
/**
|
||||
* Provide Hover Requests or not
|
||||
*/
|
||||
public ?bool $provideHover = null;
|
||||
|
||||
/**
|
||||
* Provide Signature Help or not
|
||||
*/
|
||||
public ?bool $provideSignatureHelp = null;
|
||||
|
||||
/**
|
||||
* Provide Code Actions or not
|
||||
*/
|
||||
public ?bool $provideCodeActions = null;
|
||||
|
||||
/**
|
||||
* Provide Diagnostics or not
|
||||
*/
|
||||
public ?bool $provideDiagnostics = null;
|
||||
|
||||
/**
|
||||
* Provide Completion or not
|
||||
*
|
||||
* @psalm-suppress PossiblyUnusedProperty
|
||||
*/
|
||||
public ?bool $findUnusedVariables = null;
|
||||
|
||||
/**
|
||||
* Look for dead code
|
||||
*
|
||||
* @var 'always'|'auto'|null
|
||||
*/
|
||||
public ?string $findUnusedCode = null;
|
||||
|
||||
/**
|
||||
* Log Level
|
||||
*
|
||||
* @see MessageType
|
||||
*/
|
||||
public ?int $logLevel = null;
|
||||
|
||||
/**
|
||||
* If added, the language server will not respond to onChange events.
|
||||
* You can also specify a line count over which Psalm will not run on-change events.
|
||||
*/
|
||||
public ?int $onchangeLineLimit = null;
|
||||
|
||||
/**
|
||||
* Debounce time in milliseconds for onChange events
|
||||
*/
|
||||
public ?int $onChangeDebounceMs = null;
|
||||
|
||||
/**
|
||||
* Undocumented function
|
||||
*
|
||||
* @param 'always'|'auto'|null $findUnusedCode
|
||||
*/
|
||||
public function __construct(
|
||||
bool $hideWarnings = true,
|
||||
?bool $provideCompletion = null,
|
||||
?bool $provideDefinition = null,
|
||||
?bool $provideHover = null,
|
||||
?bool $provideSignatureHelp = null,
|
||||
?bool $provideCodeActions = null,
|
||||
?bool $provideDiagnostics = null,
|
||||
?bool $findUnusedVariables = null,
|
||||
?string $findUnusedCode = null,
|
||||
?int $logLevel = null,
|
||||
?int $onchangeLineLimit = null,
|
||||
?string $baseline = null
|
||||
) {
|
||||
$this->hideWarnings = $hideWarnings;
|
||||
$this->provideCompletion = $provideCompletion;
|
||||
$this->provideDefinition = $provideDefinition;
|
||||
$this->provideHover = $provideHover;
|
||||
$this->provideSignatureHelp = $provideSignatureHelp;
|
||||
$this->provideCodeActions = $provideCodeActions;
|
||||
$this->provideDiagnostics = $provideDiagnostics;
|
||||
$this->findUnusedVariables = $findUnusedVariables;
|
||||
$this->findUnusedCode = $findUnusedCode;
|
||||
$this->logLevel = $logLevel;
|
||||
$this->onchangeLineLimit = $onchangeLineLimit;
|
||||
$this->baseline = $baseline;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ use Amp\Promise;
|
||||
use Generator;
|
||||
|
||||
use function Amp\call;
|
||||
use function error_log;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -59,7 +58,6 @@ class ClientHandler
|
||||
|
||||
$listener =
|
||||
function (Message $msg) use ($id, $deferred, &$listener): void {
|
||||
error_log('request handler');
|
||||
/**
|
||||
* @psalm-suppress UndefinedPropertyFetch
|
||||
* @psalm-suppress MixedArgument
|
||||
|
||||
@@ -5,7 +5,14 @@ declare(strict_types=1);
|
||||
namespace Psalm\Internal\LanguageServer;
|
||||
|
||||
use JsonMapper;
|
||||
use LanguageServerProtocol\LogMessage;
|
||||
use LanguageServerProtocol\LogTrace;
|
||||
use Psalm\Internal\LanguageServer\Client\TextDocument as ClientTextDocument;
|
||||
use Psalm\Internal\LanguageServer\Client\Workspace as ClientWorkspace;
|
||||
|
||||
use function is_null;
|
||||
use function json_decode;
|
||||
use function json_encode;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -17,44 +24,159 @@ class LanguageClient
|
||||
*/
|
||||
public ClientTextDocument $textDocument;
|
||||
|
||||
/**
|
||||
* Handles workspace/* methods
|
||||
*/
|
||||
public ClientWorkspace $workspace;
|
||||
|
||||
/**
|
||||
* The client handler
|
||||
*/
|
||||
private ClientHandler $handler;
|
||||
|
||||
public function __construct(ProtocolReader $reader, ProtocolWriter $writer)
|
||||
{
|
||||
$this->handler = new ClientHandler($reader, $writer);
|
||||
$mapper = new JsonMapper;
|
||||
/**
|
||||
* The Language Server
|
||||
*/
|
||||
private LanguageServer $server;
|
||||
|
||||
$this->textDocument = new ClientTextDocument($this->handler, $mapper);
|
||||
/**
|
||||
* The Client Configuration
|
||||
*/
|
||||
public ClientConfiguration $clientConfiguration;
|
||||
|
||||
public function __construct(
|
||||
ProtocolReader $reader,
|
||||
ProtocolWriter $writer,
|
||||
LanguageServer $server,
|
||||
ClientConfiguration $clientConfiguration
|
||||
) {
|
||||
$this->handler = new ClientHandler($reader, $writer);
|
||||
$this->server = $server;
|
||||
|
||||
$this->textDocument = new ClientTextDocument($this->handler, $this->server);
|
||||
$this->workspace = new ClientWorkspace($this->handler, new JsonMapper, $this->server);
|
||||
$this->clientConfiguration = $clientConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request Configuration from Client and save it
|
||||
*/
|
||||
public function refreshConfiguration(): void
|
||||
{
|
||||
$capabilities = $this->server->clientCapabilities;
|
||||
if ($capabilities && $capabilities->workspace && $capabilities->workspace->configuration) {
|
||||
$this->workspace->requestConfiguration('psalm')->onResolve(function ($error, $value): void {
|
||||
if ($error) {
|
||||
$this->server->logError('There was an error getting configuration');
|
||||
} else {
|
||||
/** @var array<int, object> $value */
|
||||
[$config] = $value;
|
||||
$this->configurationRefreshed((array) $config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A notification to log the trace of the server’s execution.
|
||||
* The amount and content of these notifications depends on the current trace configuration.
|
||||
*
|
||||
* @psalm-suppress PossiblyUnusedMethod
|
||||
*/
|
||||
public function logTrace(LogTrace $logTrace): void
|
||||
{
|
||||
//If trace is 'off', the server should not send any logTrace notification.
|
||||
if (is_null($this->server->trace) || $this->server->trace === 'off') {
|
||||
return;
|
||||
}
|
||||
|
||||
//If trace is 'messages', the server should not add the 'verbose' field in the LogTraceParams.
|
||||
if ($this->server->trace === 'messages') {
|
||||
$logTrace->verbose = null;
|
||||
}
|
||||
|
||||
$this->handler->notify(
|
||||
'$/logTrace',
|
||||
$logTrace,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a log message to the client.
|
||||
*
|
||||
* @param string $message The message to send to the client.
|
||||
* @psalm-param 1|2|3|4 $type
|
||||
* @param int $type The log type:
|
||||
* - 1 = Error
|
||||
* - 2 = Warning
|
||||
* - 3 = Info
|
||||
* - 4 = Log
|
||||
*/
|
||||
public function logMessage(string $message, int $type = 4, string $method = 'window/logMessage'): void
|
||||
public function logMessage(LogMessage $logMessage): void
|
||||
{
|
||||
// https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage
|
||||
|
||||
if ($type < 1 || $type > 4) {
|
||||
$type = 4;
|
||||
}
|
||||
|
||||
$this->handler->notify(
|
||||
$method,
|
||||
[
|
||||
'type' => $type,
|
||||
'message' => $message,
|
||||
],
|
||||
'window/logMessage',
|
||||
$logMessage,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The telemetry notification is sent from the
|
||||
* server to the client to ask the client to log
|
||||
* a telemetry event.
|
||||
*
|
||||
* The protocol doesn’t specify the payload since no
|
||||
* interpretation of the data happens in the protocol.
|
||||
* Most clients even don’t handle the event directly
|
||||
* but forward them to the extensions owing the corresponding
|
||||
* server issuing the event.
|
||||
*/
|
||||
public function event(LogMessage $logMessage): void
|
||||
{
|
||||
$this->handler->notify(
|
||||
'telemetry/event',
|
||||
$logMessage,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration Refreshed from Client
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
private function configurationRefreshed(array $config): void
|
||||
{
|
||||
//do things when the config is refreshed
|
||||
|
||||
if (empty($config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var array */
|
||||
$array = json_decode(json_encode($config), true);
|
||||
|
||||
if (isset($array['hideWarnings'])) {
|
||||
$this->clientConfiguration->hideWarnings = (bool) $array['hideWarnings'];
|
||||
}
|
||||
|
||||
if (isset($array['provideCompletion'])) {
|
||||
$this->clientConfiguration->provideCompletion = (bool) $array['provideCompletion'];
|
||||
}
|
||||
|
||||
if (isset($array['provideDefinition'])) {
|
||||
$this->clientConfiguration->provideDefinition = (bool) $array['provideDefinition'];
|
||||
}
|
||||
|
||||
if (isset($array['provideHover'])) {
|
||||
$this->clientConfiguration->provideHover = (bool) $array['provideHover'];
|
||||
}
|
||||
|
||||
if (isset($array['provideSignatureHelp'])) {
|
||||
$this->clientConfiguration->provideSignatureHelp = (bool) $array['provideSignatureHelp'];
|
||||
}
|
||||
|
||||
if (isset($array['provideCodeActions'])) {
|
||||
$this->clientConfiguration->provideCodeActions = (bool) $array['provideCodeActions'];
|
||||
}
|
||||
|
||||
if (isset($array['provideDiagnostics'])) {
|
||||
$this->clientConfiguration->provideDiagnostics = (bool) $array['provideDiagnostics'];
|
||||
}
|
||||
|
||||
if (isset($array['findUnusedVariables'])) {
|
||||
$this->clientConfiguration->findUnusedVariables = (bool) $array['findUnusedVariables'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,8 +24,6 @@ class Message
|
||||
|
||||
/**
|
||||
* Parses a message
|
||||
*
|
||||
* @psalm-suppress UnusedMethod
|
||||
*/
|
||||
public static function parse(string $msg): Message
|
||||
{
|
||||
@@ -35,7 +33,9 @@ class Message
|
||||
foreach ($parts as $line) {
|
||||
if ($line) {
|
||||
$pair = explode(': ', $line);
|
||||
$obj->headers[$pair[0]] = $pair[1];
|
||||
if (isset($pair[1])) {
|
||||
$obj->headers[$pair[0]] = $pair[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ class Message
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
|
||||
$body = (string)$this->body;
|
||||
$contentLength = strlen($body);
|
||||
$this->headers['Content-Length'] = (string) $contentLength;
|
||||
|
||||
58
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/PHPMarkdownContent.php
vendored
Normal file
58
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/PHPMarkdownContent.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psalm\Internal\LanguageServer;
|
||||
|
||||
use JsonSerializable;
|
||||
use LanguageServerProtocol\MarkupContent;
|
||||
use LanguageServerProtocol\MarkupKind;
|
||||
use ReturnTypeWillChange;
|
||||
|
||||
use function get_object_vars;
|
||||
|
||||
/**
|
||||
* @psalm-api
|
||||
* @internal
|
||||
*/
|
||||
class PHPMarkdownContent extends MarkupContent implements JsonSerializable
|
||||
{
|
||||
public string $code;
|
||||
|
||||
public ?string $title = null;
|
||||
|
||||
public ?string $description = null;
|
||||
|
||||
public function __construct(string $code, ?string $title = null, ?string $description = null)
|
||||
{
|
||||
$this->code = $code;
|
||||
$this->title = $title;
|
||||
$this->description = $description;
|
||||
|
||||
$markdown = '';
|
||||
if ($title !== null) {
|
||||
$markdown = "**$title**\n\n";
|
||||
}
|
||||
if ($description !== null) {
|
||||
$markdown = "$markdown$description\n\n";
|
||||
}
|
||||
parent::__construct(
|
||||
MarkupKind::MARKDOWN,
|
||||
"$markdown```php\n<?php\n$code\n```",
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is needed because VSCode Does not like nulls
|
||||
* meaning if a null is sent then this will not compute
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
#[ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
$vars = get_object_vars($this);
|
||||
unset($vars['title'], $vars['description'], $vars['code']);
|
||||
return $vars;
|
||||
}
|
||||
}
|
||||
35
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Progress.php
vendored
Normal file
35
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Progress.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\LanguageServer;
|
||||
|
||||
use Psalm\Progress\Progress as Base;
|
||||
|
||||
use function str_replace;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class Progress extends Base
|
||||
{
|
||||
|
||||
private ?LanguageServer $server = null;
|
||||
|
||||
public function setServer(LanguageServer $server): void
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
public function debug(string $message): void
|
||||
{
|
||||
if ($this->server) {
|
||||
$this->server->logDebug(str_replace("\n", "", $message));
|
||||
}
|
||||
}
|
||||
|
||||
public function write(string $message): void
|
||||
{
|
||||
if ($this->server) {
|
||||
$this->server->logInfo(str_replace("\n", "", $message));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,9 @@ class ProtocolStreamReader implements ProtocolReader
|
||||
$this->buffer = '';
|
||||
} elseif (substr($this->buffer, -2) === "\r\n") {
|
||||
$parts = explode(':', $this->buffer);
|
||||
$this->headers[$parts[0]] = trim($parts[1]);
|
||||
if (isset($parts[1])) {
|
||||
$this->headers[$parts[0]] = trim($parts[1]);
|
||||
}
|
||||
$this->buffer = '';
|
||||
}
|
||||
break;
|
||||
|
||||
47
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/ClassLikeStorageCacheProvider.php
vendored
Normal file
47
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/ClassLikeStorageCacheProvider.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\LanguageServer\Provider;
|
||||
|
||||
use Psalm\Internal\Provider\ClassLikeStorageCacheProvider as InternalClassLikeStorageCacheProvider;
|
||||
use Psalm\Storage\ClassLikeStorage;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ClassLikeStorageCacheProvider extends InternalClassLikeStorageCacheProvider
|
||||
{
|
||||
/** @var array<string, ClassLikeStorage> */
|
||||
private array $cache = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function writeToCache(ClassLikeStorage $storage, ?string $file_path, ?string $file_contents): void
|
||||
{
|
||||
$fq_classlike_name_lc = strtolower($storage->name);
|
||||
$this->cache[$fq_classlike_name_lc] = $storage;
|
||||
}
|
||||
|
||||
public function getLatestFromCache(
|
||||
string $fq_classlike_name_lc,
|
||||
?string $file_path,
|
||||
?string $file_contents
|
||||
): ClassLikeStorage {
|
||||
$cached_value = $this->loadFromCache($fq_classlike_name_lc);
|
||||
|
||||
if (!$cached_value) {
|
||||
throw new UnexpectedValueException('Should be in cache');
|
||||
}
|
||||
|
||||
return $cached_value;
|
||||
}
|
||||
|
||||
private function loadFromCache(string $fq_classlike_name_lc): ?ClassLikeStorage
|
||||
{
|
||||
return $this->cache[$fq_classlike_name_lc] ?? null;
|
||||
}
|
||||
}
|
||||
280
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileReferenceCacheProvider.php
vendored
Normal file
280
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileReferenceCacheProvider.php
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\LanguageServer\Provider;
|
||||
|
||||
use Psalm\Config;
|
||||
use Psalm\Internal\Provider\FileReferenceCacheProvider as InternalFileReferenceCacheProvider;
|
||||
|
||||
/**
|
||||
* Used to determine which files reference other files, necessary for using the --diff
|
||||
* option from the command line.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class FileReferenceCacheProvider extends InternalFileReferenceCacheProvider
|
||||
{
|
||||
private ?array $cached_file_references = null;
|
||||
|
||||
private ?array $cached_classlike_files = null;
|
||||
|
||||
private ?array $cached_method_class_references = null;
|
||||
|
||||
private ?array $cached_nonmethod_class_references = null;
|
||||
|
||||
private ?array $cached_method_member_references = null;
|
||||
|
||||
private ?array $cached_method_dependencies = null;
|
||||
|
||||
private ?array $cached_method_property_references = null;
|
||||
|
||||
private ?array $cached_method_method_return_references = null;
|
||||
|
||||
private ?array $cached_file_member_references = null;
|
||||
|
||||
private ?array $cached_file_property_references = null;
|
||||
|
||||
private ?array $cached_file_method_return_references = null;
|
||||
|
||||
private ?array $cached_method_missing_member_references = null;
|
||||
|
||||
private ?array $cached_file_missing_member_references = null;
|
||||
|
||||
private ?array $cached_unknown_member_references = null;
|
||||
|
||||
private ?array $cached_method_param_uses = null;
|
||||
|
||||
private ?array $cached_issues = null;
|
||||
|
||||
/** @var array<string, array<string, int>> */
|
||||
private array $cached_correct_methods = [];
|
||||
|
||||
/**
|
||||
* @var array<
|
||||
* string,
|
||||
* array{
|
||||
* 0: array<int, array{0: int, 1: non-empty-string}>,
|
||||
* 1: array<int, array{0: int, 1: non-empty-string}>,
|
||||
* 2: array<int, array{0: int, 1: non-empty-string, 2: int}>
|
||||
* }
|
||||
* >
|
||||
*/
|
||||
private array $cached_file_maps = [];
|
||||
|
||||
public function __construct(Config $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function getCachedFileReferences(): ?array
|
||||
{
|
||||
return $this->cached_file_references;
|
||||
}
|
||||
|
||||
public function getCachedClassLikeFiles(): ?array
|
||||
{
|
||||
return $this->cached_classlike_files;
|
||||
}
|
||||
|
||||
public function getCachedMethodClassReferences(): ?array
|
||||
{
|
||||
return $this->cached_method_class_references;
|
||||
}
|
||||
|
||||
public function getCachedNonMethodClassReferences(): ?array
|
||||
{
|
||||
return $this->cached_nonmethod_class_references;
|
||||
}
|
||||
|
||||
public function getCachedFileMemberReferences(): ?array
|
||||
{
|
||||
return $this->cached_file_member_references;
|
||||
}
|
||||
|
||||
public function getCachedFilePropertyReferences(): ?array
|
||||
{
|
||||
return $this->cached_file_property_references;
|
||||
}
|
||||
|
||||
public function getCachedFileMethodReturnReferences(): ?array
|
||||
{
|
||||
return $this->cached_file_method_return_references;
|
||||
}
|
||||
|
||||
public function getCachedMethodMemberReferences(): ?array
|
||||
{
|
||||
return $this->cached_method_member_references;
|
||||
}
|
||||
|
||||
public function getCachedMethodDependencies(): ?array
|
||||
{
|
||||
return $this->cached_method_dependencies;
|
||||
}
|
||||
|
||||
public function getCachedMethodPropertyReferences(): ?array
|
||||
{
|
||||
return $this->cached_method_property_references;
|
||||
}
|
||||
|
||||
public function getCachedMethodMethodReturnReferences(): ?array
|
||||
{
|
||||
return $this->cached_method_method_return_references;
|
||||
}
|
||||
|
||||
public function getCachedFileMissingMemberReferences(): ?array
|
||||
{
|
||||
return $this->cached_file_missing_member_references;
|
||||
}
|
||||
|
||||
public function getCachedMixedMemberNameReferences(): ?array
|
||||
{
|
||||
return $this->cached_unknown_member_references;
|
||||
}
|
||||
|
||||
public function getCachedMethodMissingMemberReferences(): ?array
|
||||
{
|
||||
return $this->cached_method_missing_member_references;
|
||||
}
|
||||
|
||||
public function getCachedMethodParamUses(): ?array
|
||||
{
|
||||
return $this->cached_method_param_uses;
|
||||
}
|
||||
|
||||
public function getCachedIssues(): ?array
|
||||
{
|
||||
return $this->cached_issues;
|
||||
}
|
||||
|
||||
public function setCachedFileReferences(array $file_references): void
|
||||
{
|
||||
$this->cached_file_references = $file_references;
|
||||
}
|
||||
|
||||
public function setCachedClassLikeFiles(array $file_references): void
|
||||
{
|
||||
$this->cached_classlike_files = $file_references;
|
||||
}
|
||||
|
||||
public function setCachedMethodClassReferences(array $method_class_references): void
|
||||
{
|
||||
$this->cached_method_class_references = $method_class_references;
|
||||
}
|
||||
|
||||
public function setCachedNonMethodClassReferences(array $file_class_references): void
|
||||
{
|
||||
$this->cached_nonmethod_class_references = $file_class_references;
|
||||
}
|
||||
|
||||
public function setCachedMethodMemberReferences(array $member_references): void
|
||||
{
|
||||
$this->cached_method_member_references = $member_references;
|
||||
}
|
||||
|
||||
public function setCachedMethodDependencies(array $member_references): void
|
||||
{
|
||||
$this->cached_method_dependencies = $member_references;
|
||||
}
|
||||
|
||||
public function setCachedMethodPropertyReferences(array $property_references): void
|
||||
{
|
||||
$this->cached_method_property_references = $property_references;
|
||||
}
|
||||
|
||||
public function setCachedMethodMethodReturnReferences(array $method_return_references): void
|
||||
{
|
||||
$this->cached_method_method_return_references = $method_return_references;
|
||||
}
|
||||
|
||||
public function setCachedMethodMissingMemberReferences(array $member_references): void
|
||||
{
|
||||
$this->cached_method_missing_member_references = $member_references;
|
||||
}
|
||||
|
||||
public function setCachedFileMemberReferences(array $member_references): void
|
||||
{
|
||||
$this->cached_file_member_references = $member_references;
|
||||
}
|
||||
|
||||
public function setCachedFilePropertyReferences(array $property_references): void
|
||||
{
|
||||
$this->cached_file_property_references = $property_references;
|
||||
}
|
||||
|
||||
public function setCachedFileMethodReturnReferences(array $method_return_references): void
|
||||
{
|
||||
$this->cached_file_method_return_references = $method_return_references;
|
||||
}
|
||||
|
||||
public function setCachedFileMissingMemberReferences(array $member_references): void
|
||||
{
|
||||
$this->cached_file_missing_member_references = $member_references;
|
||||
}
|
||||
|
||||
public function setCachedMixedMemberNameReferences(array $references): void
|
||||
{
|
||||
$this->cached_unknown_member_references = $references;
|
||||
}
|
||||
|
||||
public function setCachedMethodParamUses(array $uses): void
|
||||
{
|
||||
$this->cached_method_param_uses = $uses;
|
||||
}
|
||||
|
||||
public function setCachedIssues(array $issues): void
|
||||
{
|
||||
$this->cached_issues = $issues;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<string, int>>
|
||||
*/
|
||||
public function getAnalyzedMethodCache(): array
|
||||
{
|
||||
return $this->cached_correct_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array<string, int>> $analyzed_methods
|
||||
*/
|
||||
public function setAnalyzedMethodCache(array $analyzed_methods): void
|
||||
{
|
||||
$this->cached_correct_methods = $analyzed_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<
|
||||
* string,
|
||||
* array{
|
||||
* 0: array<int, array{0: int, 1: non-empty-string}>,
|
||||
* 1: array<int, array{0: int, 1: non-empty-string}>,
|
||||
* 2: array<int, array{0: int, 1: non-empty-string, 2: int}>
|
||||
* }
|
||||
* >
|
||||
*/
|
||||
public function getFileMapCache(): array
|
||||
{
|
||||
return $this->cached_file_maps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<
|
||||
* string,
|
||||
* array{
|
||||
* 0: array<int, array{0: int, 1: non-empty-string}>,
|
||||
* 1: array<int, array{0: int, 1: non-empty-string}>,
|
||||
* 2: array<int, array{0: int, 1: non-empty-string, 2: int}>
|
||||
* }
|
||||
* > $file_maps
|
||||
*/
|
||||
public function setFileMapCache(array $file_maps): void
|
||||
{
|
||||
$this->cached_file_maps = $file_maps;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, array{int, int}> $mixed_counts
|
||||
*/
|
||||
public function setTypeCoverage(array $mixed_counts): void
|
||||
{
|
||||
}
|
||||
}
|
||||
48
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileStorageCacheProvider.php
vendored
Normal file
48
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/FileStorageCacheProvider.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\LanguageServer\Provider;
|
||||
|
||||
use Psalm\Internal\Provider\FileStorageCacheProvider as InternalFileStorageCacheProvider;
|
||||
use Psalm\Storage\FileStorage;
|
||||
|
||||
use function strtolower;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class FileStorageCacheProvider extends InternalFileStorageCacheProvider
|
||||
{
|
||||
/** @var array<lowercase-string, FileStorage> */
|
||||
private array $cache = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function writeToCache(FileStorage $storage, string $file_contents): void
|
||||
{
|
||||
$file_path = strtolower($storage->file_path);
|
||||
$this->cache[$file_path] = $storage;
|
||||
}
|
||||
|
||||
public function getLatestFromCache(string $file_path, string $file_contents): ?FileStorage
|
||||
{
|
||||
$cached_value = $this->loadFromCache(strtolower($file_path));
|
||||
|
||||
if (!$cached_value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $cached_value;
|
||||
}
|
||||
|
||||
public function removeCacheForFile(string $file_path): void
|
||||
{
|
||||
unset($this->cache[strtolower($file_path)]);
|
||||
}
|
||||
|
||||
private function loadFromCache(string $file_path): ?FileStorage
|
||||
{
|
||||
return $this->cache[strtolower($file_path)] ?? null;
|
||||
}
|
||||
}
|
||||
109
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/ParserCacheProvider.php
vendored
Normal file
109
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/ParserCacheProvider.php
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\LanguageServer\Provider;
|
||||
|
||||
use PhpParser;
|
||||
use Psalm\Internal\Provider\ParserCacheProvider as InternalParserCacheProvider;
|
||||
|
||||
use function microtime;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ParserCacheProvider extends InternalParserCacheProvider
|
||||
{
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private array $file_contents_cache = [];
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private array $file_content_hash = [];
|
||||
|
||||
/**
|
||||
* @var array<string, list<PhpParser\Node\Stmt>>
|
||||
*/
|
||||
private array $statements_cache = [];
|
||||
|
||||
/**
|
||||
* @var array<string, float>
|
||||
*/
|
||||
private array $statements_cache_time = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function loadStatementsFromCache(
|
||||
string $file_path,
|
||||
int $file_modified_time,
|
||||
string $file_content_hash
|
||||
): ?array {
|
||||
if (isset($this->statements_cache[$file_path])
|
||||
&& $this->statements_cache_time[$file_path] >= $file_modified_time
|
||||
&& $this->file_content_hash[$file_path] === $file_content_hash
|
||||
) {
|
||||
return $this->statements_cache[$file_path];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<PhpParser\Node\Stmt>|null
|
||||
*/
|
||||
public function loadExistingStatementsFromCache(string $file_path): ?array
|
||||
{
|
||||
if (isset($this->statements_cache[$file_path])) {
|
||||
return $this->statements_cache[$file_path];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<PhpParser\Node\Stmt> $stmts
|
||||
*/
|
||||
public function saveStatementsToCache(
|
||||
string $file_path,
|
||||
string $file_content_hash,
|
||||
array $stmts,
|
||||
bool $touch_only
|
||||
): void {
|
||||
$this->statements_cache[$file_path] = $stmts;
|
||||
$this->statements_cache_time[$file_path] = microtime(true);
|
||||
$this->file_content_hash[$file_path] = $file_content_hash;
|
||||
}
|
||||
|
||||
public function loadExistingFileContentsFromCache(string $file_path): ?string
|
||||
{
|
||||
if (isset($this->file_contents_cache[$file_path])) {
|
||||
return $this->file_contents_cache[$file_path];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function cacheFileContents(string $file_path, string $file_contents): void
|
||||
{
|
||||
$this->file_contents_cache[$file_path] = $file_contents;
|
||||
}
|
||||
|
||||
public function deleteOldParserCaches(float $time_before): int
|
||||
{
|
||||
$this->existing_file_content_hashes = null;
|
||||
$this->new_file_content_hashes = [];
|
||||
|
||||
$this->file_contents_cache = [];
|
||||
$this->file_content_hash = [];
|
||||
$this->statements_cache = [];
|
||||
$this->statements_cache_time = [];
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function saveFileContentHashes(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
41
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/ProjectCacheProvider.php
vendored
Normal file
41
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Provider/ProjectCacheProvider.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\LanguageServer\Provider;
|
||||
|
||||
use Psalm\Internal\Provider\ProjectCacheProvider as PsalmProjectCacheProvider;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class ProjectCacheProvider extends PsalmProjectCacheProvider
|
||||
{
|
||||
private int $last_run = 0;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function getLastRun(string $psalm_version): int
|
||||
{
|
||||
return $this->last_run;
|
||||
}
|
||||
|
||||
public function processSuccessfulRun(float $start_time, string $psalm_version): void
|
||||
{
|
||||
$this->last_run = (int) $start_time;
|
||||
}
|
||||
|
||||
public function canDiffFiles(): bool
|
||||
{
|
||||
return $this->last_run > 0;
|
||||
}
|
||||
|
||||
public function hasLockfileChanged(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function updateComposerLockHash(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
22
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Reference.php
vendored
Normal file
22
vendor/vimeo/psalm/src/Psalm/Internal/LanguageServer/Reference.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\LanguageServer;
|
||||
|
||||
use LanguageServerProtocol\Range;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class Reference
|
||||
{
|
||||
public string $file_path;
|
||||
public string $symbol;
|
||||
public Range $range;
|
||||
|
||||
public function __construct(string $file_path, string $symbol, Range $range)
|
||||
{
|
||||
$this->file_path = $file_path;
|
||||
$this->symbol = $symbol;
|
||||
$this->range = $range;
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,12 @@ namespace Psalm\Internal\LanguageServer\Server;
|
||||
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
use LanguageServerProtocol\CodeAction;
|
||||
use LanguageServerProtocol\CodeActionContext;
|
||||
use LanguageServerProtocol\CodeActionKind;
|
||||
use LanguageServerProtocol\CompletionList;
|
||||
use LanguageServerProtocol\Hover;
|
||||
use LanguageServerProtocol\Location;
|
||||
use LanguageServerProtocol\MarkupContent;
|
||||
use LanguageServerProtocol\MarkupKind;
|
||||
use LanguageServerProtocol\Position;
|
||||
use LanguageServerProtocol\Range;
|
||||
use LanguageServerProtocol\SignatureHelp;
|
||||
@@ -21,6 +22,7 @@ use LanguageServerProtocol\TextEdit;
|
||||
use LanguageServerProtocol\VersionedTextDocumentIdentifier;
|
||||
use LanguageServerProtocol\WorkspaceEdit;
|
||||
use Psalm\Codebase;
|
||||
use Psalm\Exception\TypeParseTreeException;
|
||||
use Psalm\Exception\UnanalyzedFileException;
|
||||
use Psalm\Internal\Analyzer\ProjectAnalyzer;
|
||||
use Psalm\Internal\LanguageServer\LanguageServer;
|
||||
@@ -28,7 +30,6 @@ use UnexpectedValueException;
|
||||
|
||||
use function array_values;
|
||||
use function count;
|
||||
use function error_log;
|
||||
use function preg_match;
|
||||
use function substr_count;
|
||||
|
||||
@@ -68,36 +69,41 @@ class TextDocument
|
||||
*/
|
||||
public function didOpen(TextDocumentItem $textDocument): void
|
||||
{
|
||||
$this->server->logDebug(
|
||||
'textDocument/didOpen',
|
||||
['version' => $textDocument->version, 'uri' => $textDocument->uri],
|
||||
);
|
||||
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
if (!$this->codebase->config->isInProjectDirs($file_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->codebase->removeTemporaryFileChanges($file_path);
|
||||
$this->codebase->file_provider->openFile($file_path);
|
||||
$this->codebase->file_provider->setOpenContents($file_path, $textDocument->text);
|
||||
|
||||
$this->server->queueFileAnalysis($file_path, $textDocument->uri);
|
||||
$this->server->queueOpenFileAnalysis($file_path, $textDocument->uri, $textDocument->version);
|
||||
}
|
||||
|
||||
/**
|
||||
* The document save notification is sent from the client to the server when the document was saved in the client
|
||||
*
|
||||
* @param TextDocumentItem $textDocument the document that was opened
|
||||
* @param ?string $text the content when saved
|
||||
* @param TextDocumentIdentifier $textDocument the document that was opened
|
||||
* @param string|null $text Optional the content when saved. Depends on the includeText value
|
||||
* when the save notification was requested.
|
||||
*/
|
||||
public function didSave(TextDocumentItem $textDocument, ?string $text): void
|
||||
public function didSave(TextDocumentIdentifier $textDocument, ?string $text = null): void
|
||||
{
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
$this->server->logDebug(
|
||||
'textDocument/didSave',
|
||||
['uri' => (array) $textDocument],
|
||||
);
|
||||
|
||||
if (!$this->codebase->config->isInProjectDirs($file_path)) {
|
||||
return;
|
||||
}
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
// reopen file
|
||||
$this->codebase->removeTemporaryFileChanges($file_path);
|
||||
$this->codebase->file_provider->setOpenContents($file_path, (string) $text);
|
||||
$this->codebase->file_provider->setOpenContents($file_path, $text);
|
||||
|
||||
$this->server->queueFileAnalysis($file_path, $textDocument->uri);
|
||||
$this->server->queueSaveFileAnalysis($file_path, $textDocument->uri);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,13 +114,14 @@ class TextDocument
|
||||
*/
|
||||
public function didChange(VersionedTextDocumentIdentifier $textDocument, array $contentChanges): void
|
||||
{
|
||||
$this->server->logDebug(
|
||||
'textDocument/didChange',
|
||||
['version' => $textDocument->version, 'uri' => $textDocument->uri],
|
||||
);
|
||||
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
if (!$this->codebase->config->isInProjectDirs($file_path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($contentChanges) === 1 && $contentChanges[0]->range === null) {
|
||||
if (count($contentChanges) === 1 && isset($contentChanges[0]) && $contentChanges[0]->range === null) {
|
||||
$new_content = $contentChanges[0]->text;
|
||||
} else {
|
||||
throw new UnexpectedValueException('Not expecting partial diff');
|
||||
@@ -126,8 +133,8 @@ class TextDocument
|
||||
}
|
||||
}
|
||||
|
||||
$this->codebase->addTemporaryFileChanges($file_path, $new_content);
|
||||
$this->server->queueTemporaryFileAnalysis($file_path, $textDocument->uri);
|
||||
$this->codebase->addTemporaryFileChanges($file_path, $new_content, $textDocument->version);
|
||||
$this->server->queueChangeFileAnalysis($file_path, $textDocument->uri, $textDocument->version);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,6 +149,11 @@ class TextDocument
|
||||
*/
|
||||
public function didClose(TextDocumentIdentifier $textDocument): void
|
||||
{
|
||||
$this->server->logDebug(
|
||||
'textDocument/didClose',
|
||||
['uri' => $textDocument->uri],
|
||||
);
|
||||
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
$this->codebase->file_provider->closeFile($file_path);
|
||||
@@ -158,24 +170,34 @@ class TextDocument
|
||||
*/
|
||||
public function definition(TextDocumentIdentifier $textDocument, Position $position): Promise
|
||||
{
|
||||
if (!$this->server->client->clientConfiguration->provideDefinition) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
$this->server->logDebug(
|
||||
'textDocument/definition',
|
||||
);
|
||||
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
//This currently doesnt work right with out of project files
|
||||
if (!$this->codebase->config->isInProjectDirs($file_path)) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
try {
|
||||
$reference_location = $this->codebase->getReferenceAtPosition($file_path, $position);
|
||||
$reference = $this->codebase->getReferenceAtPositionAsReference($file_path, $position);
|
||||
} catch (UnanalyzedFileException $e) {
|
||||
$this->codebase->file_provider->openFile($file_path);
|
||||
$this->server->queueFileAnalysis($file_path, $textDocument->uri);
|
||||
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
if ($reference_location === null) {
|
||||
if ($reference === null) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
[$reference] = $reference_location;
|
||||
|
||||
$code_location = $this->codebase->getSymbolLocation($file_path, $reference);
|
||||
$code_location = $this->codebase->getSymbolLocationByReference($reference);
|
||||
|
||||
if (!$code_location) {
|
||||
return new Success(null);
|
||||
@@ -202,39 +224,44 @@ class TextDocument
|
||||
*/
|
||||
public function hover(TextDocumentIdentifier $textDocument, Position $position): Promise
|
||||
{
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
try {
|
||||
$reference_location = $this->codebase->getReferenceAtPosition($file_path, $position);
|
||||
} catch (UnanalyzedFileException $e) {
|
||||
$this->codebase->file_provider->openFile($file_path);
|
||||
$this->server->queueFileAnalysis($file_path, $textDocument->uri);
|
||||
|
||||
if (!$this->server->client->clientConfiguration->provideHover) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
if ($reference_location === null) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
[$reference, $range] = $reference_location;
|
||||
|
||||
$symbol_information = $this->codebase->getSymbolInformation($file_path, $reference);
|
||||
|
||||
if ($symbol_information === null) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
$content = "```php\n" . $symbol_information['type'] . "\n```";
|
||||
if (isset($symbol_information['description'])) {
|
||||
$content .= "\n---\n" . $symbol_information['description'];
|
||||
}
|
||||
$contents = new MarkupContent(
|
||||
MarkupKind::MARKDOWN,
|
||||
$content,
|
||||
$this->server->logDebug(
|
||||
'textDocument/hover',
|
||||
);
|
||||
|
||||
return new Success(new Hover($contents, $range));
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
//This currently doesnt work right with out of project files
|
||||
if (!$this->codebase->config->isInProjectDirs($file_path)) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
try {
|
||||
$reference = $this->codebase->getReferenceAtPositionAsReference($file_path, $position);
|
||||
} catch (UnanalyzedFileException $e) {
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
if ($reference === null) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
try {
|
||||
$markup = $this->codebase->getMarkupContentForSymbolByReference($reference);
|
||||
} catch (UnexpectedValueException $e) {
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
if ($markup === null) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
return new Success(new Hover($markup, $reference->range));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,56 +276,74 @@ class TextDocument
|
||||
*
|
||||
* @param TextDocumentIdentifier $textDocument The text document
|
||||
* @param Position $position The position
|
||||
* @psalm-return Promise<array<never, never>>|Promise<CompletionList>
|
||||
* @psalm-return Promise<array<empty, empty>>|Promise<CompletionList>|Promise<null>
|
||||
*/
|
||||
public function completion(TextDocumentIdentifier $textDocument, Position $position): Promise
|
||||
{
|
||||
if (!$this->server->client->clientConfiguration->provideCompletion) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
$this->server->logDebug(
|
||||
'textDocument/completion',
|
||||
);
|
||||
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
//This currently doesnt work right with out of project files
|
||||
if (!$this->codebase->config->isInProjectDirs($file_path)) {
|
||||
return new Success([]);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
try {
|
||||
$completion_data = $this->codebase->getCompletionDataAtPosition($file_path, $position);
|
||||
} catch (UnanalyzedFileException $e) {
|
||||
$this->codebase->file_provider->openFile($file_path);
|
||||
$this->server->queueFileAnalysis($file_path, $textDocument->uri);
|
||||
if ($completion_data) {
|
||||
[$recent_type, $gap, $offset] = $completion_data;
|
||||
|
||||
return new Success([]);
|
||||
if ($gap === '->' || $gap === '::') {
|
||||
$snippetSupport = ($this->server->clientCapabilities &&
|
||||
$this->server->clientCapabilities->textDocument &&
|
||||
$this->server->clientCapabilities->textDocument->completion &&
|
||||
$this->server->clientCapabilities->textDocument->completion->completionItem &&
|
||||
$this->server->clientCapabilities->textDocument->completion->completionItem->snippetSupport)
|
||||
? true : false;
|
||||
$completion_items =
|
||||
$this->codebase->getCompletionItemsForClassishThing($recent_type, $gap, $snippetSupport);
|
||||
} elseif ($gap === '[') {
|
||||
$completion_items = $this->codebase->getCompletionItemsForArrayKeys($recent_type);
|
||||
} else {
|
||||
$completion_items = $this->codebase->getCompletionItemsForPartialSymbol(
|
||||
$recent_type,
|
||||
$offset,
|
||||
$file_path,
|
||||
);
|
||||
}
|
||||
return new Success(new CompletionList($completion_items, false));
|
||||
}
|
||||
} catch (UnanalyzedFileException $e) {
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
} catch (TypeParseTreeException $e) {
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
try {
|
||||
$type_context = $this->codebase->getTypeContextAtPosition($file_path, $position);
|
||||
} catch (UnexpectedValueException $e) {
|
||||
error_log('completion errored at ' . $position->line . ':' . $position->character.
|
||||
', Reason: '.$e->getMessage());
|
||||
return new Success([]);
|
||||
}
|
||||
|
||||
if (!$completion_data && !$type_context) {
|
||||
error_log('completion not found at ' . $position->line . ':' . $position->character);
|
||||
return new Success([]);
|
||||
}
|
||||
|
||||
if ($completion_data) {
|
||||
[$recent_type, $gap, $offset] = $completion_data;
|
||||
|
||||
if ($gap === '->' || $gap === '::') {
|
||||
$completion_items = $this->codebase->getCompletionItemsForClassishThing($recent_type, $gap);
|
||||
} elseif ($gap === '[') {
|
||||
$completion_items = $this->codebase->getCompletionItemsForArrayKeys($recent_type);
|
||||
} else {
|
||||
$completion_items = $this->codebase->getCompletionItemsForPartialSymbol(
|
||||
$recent_type,
|
||||
$offset,
|
||||
$file_path,
|
||||
);
|
||||
if ($type_context) {
|
||||
$completion_items = $this->codebase->getCompletionItemsForType($type_context);
|
||||
return new Success(new CompletionList($completion_items, false));
|
||||
}
|
||||
} else {
|
||||
$completion_items = $this->codebase->getCompletionItemsForType($type_context);
|
||||
} catch (UnexpectedValueException $e) {
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
} catch (TypeParseTreeException $e) {
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
return new Success(new CompletionList($completion_items, false));
|
||||
$this->server->logError('completion not found at ' . $position->line . ':' . $position->character);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,96 +352,134 @@ class TextDocument
|
||||
*/
|
||||
public function signatureHelp(TextDocumentIdentifier $textDocument, Position $position): Promise
|
||||
{
|
||||
if (!$this->server->client->clientConfiguration->provideSignatureHelp) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
$this->server->logDebug(
|
||||
'textDocument/signatureHelp',
|
||||
);
|
||||
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
|
||||
//This currently doesnt work right with out of project files
|
||||
if (!$this->codebase->config->isInProjectDirs($file_path)) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
try {
|
||||
$argument_location = $this->codebase->getFunctionArgumentAtPosition($file_path, $position);
|
||||
} catch (UnanalyzedFileException $e) {
|
||||
$this->codebase->file_provider->openFile($file_path);
|
||||
$this->server->queueFileAnalysis($file_path, $textDocument->uri);
|
||||
|
||||
return new Success(new SignatureHelp());
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
if ($argument_location === null) {
|
||||
return new Success(new SignatureHelp());
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
$signature_information = $this->codebase->getSignatureInformation($argument_location[0], $file_path);
|
||||
try {
|
||||
$signature_information = $this->codebase->getSignatureInformation($argument_location[0], $file_path);
|
||||
} catch (UnexpectedValueException $e) {
|
||||
$this->server->logThrowable($e);
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
if (!$signature_information) {
|
||||
return new Success(new SignatureHelp());
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
return new Success(new SignatureHelp([
|
||||
$signature_information,
|
||||
], 0, $argument_location[1]));
|
||||
return new Success(
|
||||
new SignatureHelp(
|
||||
[$signature_information],
|
||||
0,
|
||||
$argument_location[1],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The code action request is sent from the client to the server to compute commands
|
||||
* for a given text document and range. These commands are typically code fixes to
|
||||
* either fix problems or to beautify/refactor code.
|
||||
*
|
||||
* @psalm-suppress PossiblyUnusedParam
|
||||
*/
|
||||
public function codeAction(TextDocumentIdentifier $textDocument, Range $range): Promise
|
||||
public function codeAction(TextDocumentIdentifier $textDocument, Range $range, CodeActionContext $context): Promise
|
||||
{
|
||||
if (!$this->server->client->clientConfiguration->provideCodeActions) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
$this->server->logDebug(
|
||||
'textDocument/codeAction',
|
||||
);
|
||||
|
||||
$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
if (!$this->codebase->file_provider->isOpen($file_path)) {
|
||||
|
||||
//Don't report code actions for files we arent watching
|
||||
if (!$this->codebase->config->isInProjectDirs($file_path)) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
$issues = $this->server->getCurrentIssues();
|
||||
|
||||
if (empty($issues[$file_path])) {
|
||||
return new Success(null);
|
||||
}
|
||||
|
||||
$file_contents = $this->codebase->getFileContents($file_path);
|
||||
|
||||
$offsetStart = $range->start->toOffset($file_contents);
|
||||
$offsetEnd = $range->end->toOffset($file_contents);
|
||||
|
||||
$fixers = [];
|
||||
foreach ($issues[$file_path] as $issue) {
|
||||
if ($offsetStart === $issue->from && $offsetEnd === $issue->to) {
|
||||
$snippetRange = new Range(
|
||||
new Position($issue->line_from-1),
|
||||
new Position($issue->line_to),
|
||||
);
|
||||
foreach ($context->diagnostics as $diagnostic) {
|
||||
if ($diagnostic->source !== 'psalm') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$indentation = '';
|
||||
if (preg_match('/^(\s*)/', $issue->snippet, $matches)) {
|
||||
$indentation = $matches[1] ?? '';
|
||||
}
|
||||
/** @var array{type: string, snippet: string, line_from: int, line_to: int} */
|
||||
$data = (array)$diagnostic->data;
|
||||
|
||||
/**
|
||||
* Suppress Psalm because ther are bugs in how
|
||||
* LanguageServer's signature of WorkspaceEdit is declared:
|
||||
*
|
||||
* See:
|
||||
* https://github.com/felixfbecker/php-language-server-protocol
|
||||
* See:
|
||||
* https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#workspaceEdit
|
||||
*/
|
||||
$edit = new WorkspaceEdit([
|
||||
//$file_path = LanguageServer::uriToPath($textDocument->uri);
|
||||
//$contents = $this->codebase->file_provider->getContents($file_path);
|
||||
|
||||
$snippetRange = new Range(
|
||||
new Position($data['line_from']-1),
|
||||
new Position($data['line_to']),
|
||||
);
|
||||
|
||||
$indentation = '';
|
||||
if (preg_match('/^(\s*)/', $data['snippet'], $matches)) {
|
||||
$indentation = $matches[1] ?? '';
|
||||
}
|
||||
|
||||
//Suppress Ability
|
||||
$fixers["suppress.{$data['type']}"] = new CodeAction(
|
||||
"Suppress {$data['type']} for this line",
|
||||
CodeActionKind::QUICK_FIX,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new WorkspaceEdit([
|
||||
$textDocument->uri => [
|
||||
new TextEdit(
|
||||
$snippetRange,
|
||||
"{$indentation}/**\n".
|
||||
"{$indentation} * @psalm-suppress {$issue->type}\n".
|
||||
"{$indentation} */\n".
|
||||
"{$issue->snippet}\n",
|
||||
"{$indentation}/** @psalm-suppress {$data['type']} */\n".
|
||||
"{$data['snippet']}\n",
|
||||
),
|
||||
],
|
||||
]);
|
||||
]),
|
||||
);
|
||||
|
||||
//Suppress Ability
|
||||
$fixers["suppress.{$issue->type}"] = [
|
||||
'title' => "Suppress {$issue->type} for this line",
|
||||
'kind' => 'quickfix',
|
||||
'edit' => $edit,
|
||||
];
|
||||
}
|
||||
/*
|
||||
$fixers["fixAll.{$diagnostic->data->type}"] = new CodeAction(
|
||||
"FixAll {$diagnostic->data->type} for this file",
|
||||
CodeActionKind::QUICK_FIX,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new Command(
|
||||
"Fix All",
|
||||
"psalm.fixall",
|
||||
[
|
||||
'uri' => $textDocument->uri,
|
||||
'type' => $diagnostic->data->type
|
||||
]
|
||||
)
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
if (empty($fixers)) {
|
||||
|
||||
@@ -4,11 +4,21 @@ declare(strict_types=1);
|
||||
|
||||
namespace Psalm\Internal\LanguageServer\Server;
|
||||
|
||||
use Amp\Promise;
|
||||
use Amp\Success;
|
||||
use InvalidArgumentException;
|
||||
use LanguageServerProtocol\FileChangeType;
|
||||
use LanguageServerProtocol\FileEvent;
|
||||
use Psalm\Codebase;
|
||||
use Psalm\Internal\Analyzer\ProjectAnalyzer;
|
||||
use Psalm\Internal\Composer;
|
||||
use Psalm\Internal\LanguageServer\LanguageServer;
|
||||
use Psalm\Internal\Provider\FileReferenceProvider;
|
||||
|
||||
use function array_filter;
|
||||
use function array_map;
|
||||
use function in_array;
|
||||
use function realpath;
|
||||
|
||||
/**
|
||||
* Provides method handlers for all workspace/* methods
|
||||
@@ -46,9 +56,35 @@ class Workspace
|
||||
*/
|
||||
public function didChangeWatchedFiles(array $changes): void
|
||||
{
|
||||
$this->server->logDebug(
|
||||
'workspace/didChangeWatchedFiles',
|
||||
);
|
||||
|
||||
$realFiles = array_filter(
|
||||
array_map(function (FileEvent $change) {
|
||||
try {
|
||||
return LanguageServer::uriToPath($change->uri);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return null;
|
||||
}
|
||||
}, $changes),
|
||||
);
|
||||
|
||||
$composerLockFile = realpath(Composer::getLockFilePath($this->codebase->config->base_dir));
|
||||
if (in_array($composerLockFile, $realFiles)) {
|
||||
$this->server->logInfo('Composer.lock file changed. Reloading codebase');
|
||||
FileReferenceProvider::clearCache();
|
||||
$this->server->queueFileAnalysisWithOpenedFiles();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($changes as $change) {
|
||||
$file_path = LanguageServer::uriToPath($change->uri);
|
||||
|
||||
if ($composerLockFile === $file_path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($change->type === FileChangeType::DELETED) {
|
||||
$this->codebase->invalidateInformationForFile($file_path);
|
||||
continue;
|
||||
@@ -62,10 +98,64 @@ class Workspace
|
||||
continue;
|
||||
}
|
||||
|
||||
//If the file is currently open then dont analyse it because its tracked by the client
|
||||
//If the file is currently open then dont analize it because its tracked in didChange
|
||||
if (!$this->codebase->file_provider->isOpen($file_path)) {
|
||||
$this->server->queueFileAnalysis($file_path, $change->uri);
|
||||
$this->server->queueClosedFileAnalysis($file_path, $change->uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A notification sent from the client to the server to signal the change of configuration settings.
|
||||
*
|
||||
* @param mixed $settings
|
||||
* @psalm-suppress PossiblyUnusedMethod, PossiblyUnusedParam
|
||||
*/
|
||||
public function didChangeConfiguration($settings): void
|
||||
{
|
||||
$this->server->logDebug(
|
||||
'workspace/didChangeConfiguration',
|
||||
);
|
||||
$this->server->client->refreshConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* The workspace/executeCommand request is sent from the client to the server to
|
||||
* trigger command execution on the server.
|
||||
*
|
||||
* @param mixed $arguments
|
||||
* @psalm-suppress PossiblyUnusedMethod
|
||||
*/
|
||||
public function executeCommand(string $command, $arguments): Promise
|
||||
{
|
||||
$this->server->logDebug(
|
||||
'workspace/executeCommand',
|
||||
[
|
||||
'command' => $command,
|
||||
'arguments' => $arguments,
|
||||
],
|
||||
);
|
||||
|
||||
switch ($command) {
|
||||
case 'psalm.analyze.uri':
|
||||
/** @var array{uri: string} */
|
||||
$arguments = (array) $arguments;
|
||||
$file = LanguageServer::uriToPath($arguments['uri']);
|
||||
$this->codebase->reloadFiles(
|
||||
$this->project_analyzer,
|
||||
[$file],
|
||||
true,
|
||||
);
|
||||
|
||||
$this->codebase->analyzer->addFilesToAnalyze(
|
||||
[$file => $file],
|
||||
);
|
||||
$this->codebase->analyzer->analyzeFiles($this->project_analyzer, 1, false);
|
||||
|
||||
$this->server->emitVersionedIssues([$file => $arguments['uri']]);
|
||||
break;
|
||||
}
|
||||
|
||||
return new Success(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,10 +241,24 @@ class ClassLikeDocblockParser
|
||||
if (isset($parsed_docblock->tags['psalm-seal-properties'])) {
|
||||
$info->sealed_properties = true;
|
||||
}
|
||||
if (isset($parsed_docblock->tags['psalm-no-seal-properties'])) {
|
||||
$info->sealed_properties = false;
|
||||
}
|
||||
|
||||
if (isset($parsed_docblock->tags['psalm-seal-methods'])) {
|
||||
$info->sealed_methods = true;
|
||||
}
|
||||
if (isset($parsed_docblock->tags['psalm-no-seal-methods'])) {
|
||||
$info->sealed_methods = false;
|
||||
}
|
||||
|
||||
if (isset($parsed_docblock->tags['psalm-inheritors'])) {
|
||||
foreach ($parsed_docblock->tags['psalm-inheritors'] as $template_line) {
|
||||
$doc_line_parts = CommentAnalyzer::splitDocLine($template_line);
|
||||
$doc_line_parts[0] = CommentAnalyzer::sanitizeDocblockType($doc_line_parts[0]);
|
||||
$info->inheritors = $doc_line_parts[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($parsed_docblock->tags['psalm-immutable'])
|
||||
|| isset($parsed_docblock->tags['psalm-mutation-free'])
|
||||
@@ -296,6 +310,9 @@ class ClassLikeDocblockParser
|
||||
}
|
||||
|
||||
if (isset($parsed_docblock->combined_tags['method'])) {
|
||||
if ($info->sealed_methods === null) {
|
||||
$info->sealed_methods = true;
|
||||
}
|
||||
foreach ($parsed_docblock->combined_tags['method'] as $offset => $method_entry) {
|
||||
$method_entry = preg_replace('/[ \t]+/', ' ', trim($method_entry));
|
||||
|
||||
@@ -481,6 +498,13 @@ class ClassLikeDocblockParser
|
||||
|
||||
$info->public_api = isset($parsed_docblock->tags['psalm-api']) || isset($parsed_docblock->tags['api']);
|
||||
|
||||
if (isset($parsed_docblock->tags['property'])
|
||||
&& $codebase->config->docblock_property_types_seal_properties
|
||||
&& $info->sealed_properties === null
|
||||
) {
|
||||
$info->sealed_properties = true;
|
||||
}
|
||||
|
||||
self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'property');
|
||||
self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'psalm-property');
|
||||
self::addMagicPropertyToInfo($comment, $info, $parsed_docblock->tags, 'property-read');
|
||||
|
||||
@@ -143,6 +143,7 @@ class ClassLikeNodeScanner
|
||||
|
||||
/**
|
||||
* @return false|null
|
||||
* @psalm-suppress ComplexMethod
|
||||
*/
|
||||
public function start(PhpParser\Node\Stmt\ClassLike $node): ?bool
|
||||
{
|
||||
@@ -420,10 +421,19 @@ class ClassLikeNodeScanner
|
||||
|
||||
if ($template_map[1] !== null && $template_map[2] !== null) {
|
||||
if (trim($template_map[2])) {
|
||||
$type_string = $template_map[2];
|
||||
try {
|
||||
$type_string = CommentAnalyzer::splitDocLine($type_string)[0];
|
||||
} catch (DocblockParseException $e) {
|
||||
throw new DocblockParseException(
|
||||
$type_string . ' is not a valid type: ' . $e->getMessage(),
|
||||
);
|
||||
}
|
||||
$type_string = CommentAnalyzer::sanitizeDocblockType($type_string);
|
||||
try {
|
||||
$template_type = TypeParser::parseTokens(
|
||||
TypeTokenizer::getFullyQualifiedTokens(
|
||||
$template_map[2],
|
||||
$type_string,
|
||||
$this->aliases,
|
||||
$storage->template_types,
|
||||
$this->type_aliases,
|
||||
@@ -529,6 +539,31 @@ class ClassLikeNodeScanner
|
||||
$storage->sealed_properties = $docblock_info->sealed_properties;
|
||||
$storage->sealed_methods = $docblock_info->sealed_methods;
|
||||
|
||||
|
||||
if ($docblock_info->inheritors) {
|
||||
try {
|
||||
$storage->inheritors = TypeParser::parseTokens(
|
||||
TypeTokenizer::getFullyQualifiedTokens(
|
||||
$docblock_info->inheritors,
|
||||
$storage->aliases,
|
||||
$storage->template_types ?? [],
|
||||
$storage->type_aliases,
|
||||
$fq_classlike_name,
|
||||
),
|
||||
null,
|
||||
$storage->template_types ?? [],
|
||||
$storage->type_aliases,
|
||||
true,
|
||||
);
|
||||
} catch (TypeParseTreeException $e) {
|
||||
$storage->docblock_issues[] = new InvalidDocblock(
|
||||
'@psalm-inheritors contains invalid reference:' . $e->getMessage(),
|
||||
$name_location ?? $class_location,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($docblock_info->properties) {
|
||||
foreach ($docblock_info->properties as $property) {
|
||||
$pseudo_property_type_tokens = TypeTokenizer::getFullyQualifiedTokens(
|
||||
@@ -567,8 +602,6 @@ class ClassLikeNodeScanner
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$storage->sealed_properties = true;
|
||||
}
|
||||
|
||||
foreach ($docblock_info->methods as $method) {
|
||||
@@ -595,8 +628,6 @@ class ClassLikeNodeScanner
|
||||
$lc_method_name,
|
||||
);
|
||||
}
|
||||
|
||||
$storage->sealed_methods = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1173,7 +1204,7 @@ class ClassLikeNodeScanner
|
||||
$storage->template_type_uses_count[$generic_class_lc] = count($atomic_type->type_params);
|
||||
|
||||
foreach ($atomic_type->type_params as $type_param) {
|
||||
$used_type_parameters[] = $type_param;
|
||||
$used_type_parameters[] = $type_param->replaceClassLike('self', $storage->name);
|
||||
}
|
||||
|
||||
$storage->template_extended_offsets[$atomic_type->value] = $used_type_parameters;
|
||||
@@ -1905,9 +1936,12 @@ class ClassLikeNodeScanner
|
||||
}
|
||||
|
||||
$type_string = str_replace("\n", '', implode('', $var_line_parts));
|
||||
|
||||
// Strip any remaining characters after the last grouping character >, } or )
|
||||
$type_string = preg_replace('/(?<=[>})])[^>})]*$/', '', $type_string, 1);
|
||||
try {
|
||||
$type_string = CommentAnalyzer::splitDocLine($type_string)[0];
|
||||
} catch (DocblockParseException $e) {
|
||||
throw new DocblockParseException($type_string . ' is not a valid type: '.$e->getMessage());
|
||||
}
|
||||
$type_string = CommentAnalyzer::sanitizeDocblockType($type_string);
|
||||
|
||||
try {
|
||||
$type_tokens = TypeTokenizer::getFullyQualifiedTokens(
|
||||
|
||||
@@ -15,6 +15,8 @@ use Psalm\Internal\Scanner\UnresolvedConstant\ArraySpread;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\ArrayValue;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\ClassConstant;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\Constant;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\EnumNameFetch;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\EnumValueFetch;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\KeyValuePair;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\ScalarValue;
|
||||
use Psalm\Internal\Scanner\UnresolvedConstant\UnresolvedAdditionOp;
|
||||
@@ -34,6 +36,7 @@ use function assert;
|
||||
use function class_exists;
|
||||
use function function_exists;
|
||||
use function implode;
|
||||
use function in_array;
|
||||
use function interface_exists;
|
||||
use function strtolower;
|
||||
|
||||
@@ -297,6 +300,24 @@ class ExpressionResolver
|
||||
return new ArrayValue($items);
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Expr\PropertyFetch
|
||||
&& $stmt->var instanceof PhpParser\Node\Expr\ClassConstFetch
|
||||
&& $stmt->var->class instanceof PhpParser\Node\Name
|
||||
&& $stmt->var->name instanceof PhpParser\Node\Identifier
|
||||
&& $stmt->name instanceof PhpParser\Node\Identifier
|
||||
&& in_array($stmt->name->name, ['name', 'value', true])
|
||||
) {
|
||||
$enum_fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject(
|
||||
$stmt->var->class,
|
||||
$aliases,
|
||||
);
|
||||
if ($stmt->name->name === 'value') {
|
||||
return new EnumValueFetch($enum_fq_class_name, $stmt->var->name->name);
|
||||
} elseif ($stmt->name->name === 'name') {
|
||||
return new EnumNameFetch($enum_fq_class_name, $stmt->var->name->name);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@ use Psalm\CodeLocation;
|
||||
use Psalm\CodeLocation\DocblockTypeLocation;
|
||||
use Psalm\Codebase;
|
||||
use Psalm\Config;
|
||||
use Psalm\Exception\DocblockParseException;
|
||||
use Psalm\Exception\InvalidMethodOverrideException;
|
||||
use Psalm\Exception\TypeParseTreeException;
|
||||
use Psalm\Internal\Analyzer\CommentAnalyzer;
|
||||
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
|
||||
use Psalm\Internal\Scanner\FileScanner;
|
||||
use Psalm\Internal\Scanner\FunctionDocblockComment;
|
||||
@@ -61,6 +63,7 @@ use function strlen;
|
||||
use function strpos;
|
||||
use function strtolower;
|
||||
use function substr;
|
||||
use function substr_replace;
|
||||
use function trim;
|
||||
|
||||
/**
|
||||
@@ -1252,7 +1255,7 @@ class FunctionLikeDocblockScanner
|
||||
|
||||
if (strpos($assertion['param_name'], $param->name.'->') === 0) {
|
||||
$storage->assertions[] = new Possibilities(
|
||||
str_replace($param->name, (string) $i, $assertion['param_name']),
|
||||
substr_replace($assertion['param_name'], (string) $i, 0, strlen($param->name)),
|
||||
$assertion_type_parts,
|
||||
);
|
||||
continue 2;
|
||||
@@ -1439,10 +1442,17 @@ class FunctionLikeDocblockScanner
|
||||
|
||||
if ($template_map[1] !== null && $template_map[2] !== null) {
|
||||
if (trim($template_map[2])) {
|
||||
$type_string = $template_map[2];
|
||||
try {
|
||||
$type_string = CommentAnalyzer::splitDocLine($type_string)[0];
|
||||
} catch (DocblockParseException $e) {
|
||||
throw new DocblockParseException($type_string . ' is not a valid type: '.$e->getMessage());
|
||||
}
|
||||
$type_string = CommentAnalyzer::sanitizeDocblockType($type_string);
|
||||
try {
|
||||
$template_type = TypeParser::parseTokens(
|
||||
TypeTokenizer::getFullyQualifiedTokens(
|
||||
$template_map[2],
|
||||
$type_string,
|
||||
$aliases,
|
||||
$storage->template_types + ($template_types ?: []),
|
||||
$type_aliases,
|
||||
|
||||
@@ -238,6 +238,12 @@ class ReflectorVisitor extends PhpParser\NodeVisitorAbstract implements FileSour
|
||||
$var_id = '$' . $var->name;
|
||||
|
||||
$functionlike_node_scanner->storage->global_variables[$var_id] = true;
|
||||
|
||||
if (isset($this->codebase->config->globals[$var_id])) {
|
||||
$var_type = Type::parseString($this->codebase->config->globals[$var_id]);
|
||||
/** @psalm-suppress UnusedMethodCall */
|
||||
$var_type->queueClassLikesForScanning($this->codebase, $this->file_storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,10 +49,14 @@ class ClassLikeStorageProvider
|
||||
return self::$storage[$fq_classlike_name_lc];
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function has(string $fq_classlike_name): bool
|
||||
{
|
||||
$fq_classlike_name_lc = strtolower($fq_classlike_name);
|
||||
|
||||
/** @psalm-suppress ImpureStaticProperty Used only for caching */
|
||||
return isset(self::$storage[$fq_classlike_name_lc]);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user