diff --git a/dictionaries/CallMap.php b/dictionaries/CallMap.php index 9da39e76efc..2271871a17d 100644 --- a/dictionaries/CallMap.php +++ b/dictionaries/CallMap.php @@ -3211,6 +3211,18 @@ 'fgetcsv' => ['list|array{0: null}|false|null', 'stream'=>'resource', 'length='=>'int', 'separator='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'fgets' => ['string|false', 'stream'=>'resource', 'length='=>'int'], 'fgetss' => ['string|false', 'fp'=>'resource', 'length='=>'int', 'allowable_tags='=>'string'], +'Fiber::__construct' => ['void', 'callback'=>'callable'], +'Fiber::start' => ['mixed', '...args'=>'mixed'], +'Fiber::resume' => ['mixed', 'value='=>'null|mixed'], +'Fiber::throw' => ['mixed', 'exception'=>'Throwable'], +'Fiber::isStarted' => ['bool'], +'Fiber::isSuspended' => ['bool'], +'Fiber::isRunning' => ['bool'], +'Fiber::isTerminated' => ['bool'], +'Fiber::getReturn' => ['mixed'], +'Fiber::getCurrent' => ['?self'], +'Fiber::suspend' => ['mixed', 'value='=>'null|mixed'], +'FiberError::__construct' => ['void'], 'file' => ['list|false', 'filename'=>'string', 'flags='=>'int', 'context='=>'resource'], 'file_exists' => ['bool', 'filename'=>'string'], 'file_get_contents' => ['string|false', 'filename'=>'string', 'use_include_path='=>'bool', 'context='=>'?resource', 'offset='=>'int', 'length='=>'int'], @@ -3361,18 +3373,6 @@ 'func_num_args' => ['int'], 'function_exists' => ['bool', 'function'=>'string'], 'fwrite' => ['int|false', 'stream'=>'resource', 'data'=>'string', 'length='=>'int'], -'Fiber::__construct' => ['void', 'callback'=>'callable'], -'Fiber::start' => ['mixed', '...args'=>'mixed'], -'Fiber::resume' => ['mixed', 'value='=>'null|mixed'], -'Fiber::throw' => ['mixed', 'exception'=>'Throwable'], -'Fiber::isStarted' => ['bool'], -'Fiber::isSuspended' => ['bool'], -'Fiber::isRunning' => ['bool'], -'Fiber::isTerminated' => ['bool'], -'Fiber::getReturn' => ['mixed'], -'Fiber::getCurrent' => ['?self'], -'Fiber::suspend' => ['mixed', 'value='=>'null|mixed'], -'FiberError::__construct' => ['void'], 'gc_collect_cycles' => ['int'], 'gc_disable' => ['void'], 'gc_enable' => ['void'], diff --git a/tests/Internal/Codebase/InternalCallMapHandlerTest.php b/tests/Internal/Codebase/InternalCallMapHandlerTest.php index 0a672a487e2..54286bee08f 100644 --- a/tests/Internal/Codebase/InternalCallMapHandlerTest.php +++ b/tests/Internal/Codebase/InternalCallMapHandlerTest.php @@ -16,7 +16,10 @@ use Psalm\Tests\TestCase; use Psalm\Tests\TestConfig; use Psalm\Type; +use ReflectionException; use ReflectionFunction; +use ReflectionFunctionAbstract; +use ReflectionMethod; use ReflectionParameter; use ReflectionType; @@ -49,63 +52,162 @@ class InternalCallMapHandlerTest extends TestCase * @var array> */ private static $ignoredFunctions = [ - 'apcu_entry', + 'argumentcounterror::__construct', + 'arithmeticerror::__construct', 'array_multisort', + 'arrayiterator::asort', + 'arrayiterator::ksort', + 'arrayiterator::offsetexists', + 'arrayiterator::offsetget', + 'arrayiterator::offsetset', + 'arrayiterator::offsetunset', + 'arrayiterator::seek', + 'arrayiterator::setflags', + 'arrayiterator::uasort', + 'arrayiterator::uksort', + 'arrayiterator::unserialize', + 'arrayobject::__construct', + 'arrayobject::asort', + 'arrayobject::exchangearray', + 'arrayobject::ksort', + 'arrayobject::offsetexists', + 'arrayobject::offsetget', + 'arrayobject::offsetset', + 'arrayobject::offsetunset', + 'arrayobject::setiteratorclass', + 'arrayobject::uasort', + 'arrayobject::uksort', + 'arrayobject::unserialize', + 'badfunctioncallexception::__construct', + 'badmethodcallexception::__construct', 'bcdiv', 'bcmod', 'bcpowmod', 'bzdecompress', + 'cachingiterator::offsetexists', + 'cachingiterator::offsetget', + 'cachingiterator::offsetset', + 'cachingiterator::offsetunset', + 'callbackfilteriterator::__construct', + 'closure::bind', + 'closure::bindto', + 'closure::call', + 'closure::fromcallable', + 'collator::asort', + 'collator::getattribute', + 'collator::setattribute', + 'collator::sort', + 'collator::sortwithsortkeys', 'crypt', + 'curlfile::__construct', + 'curlfile::setmimetype', + 'curlfile::setpostfilename', 'date_isodate_set', + 'dateinterval::__construct', + 'dateinterval::createfromdatestring', + 'datetime::createfromformat', + 'datetime::diff', + 'datetime::modify', + 'datetime::setisodate', + 'datetime::settime', + 'datetime::settimestamp', + 'datetimezone::gettransitions', 'debug_zval_dump', 'deflate_add', + 'directoryiterator::__construct', + 'directoryiterator::getfileinfo', + 'directoryiterator::getpathinfo', + 'directoryiterator::openfile', + 'directoryiterator::seek', + 'directoryiterator::setfileclass', + 'directoryiterator::setinfoclass', 'dns_get_mx', + 'domainexception::__construct', + 'domattr::insertbefore', + 'domattr::isdefaultnamespace', + 'domattr::issamenode', + 'domattr::lookupprefix', + 'domattr::removechild', + 'domattr::replacechild', + 'domcdatasection::__construct', + 'domcomment::__construct', + 'domdocument::createattribute', + 'domdocument::createattributens', + 'domdocument::createelement', + 'domdocument::createelementns', + 'domdocument::createtextnode', + 'domdocument::getelementbyid', + 'domdocument::getelementsbytagname', + 'domdocument::getelementsbytagnamens', + 'domdocument::importnode', + 'domdocument::registernodeclass', + 'domelement::__construct', + 'domelement::getattribute', + 'domelement::getattributenode', + 'domelement::getattributenodens', + 'domelement::getattributens', + 'domelement::getelementsbytagname', + 'domelement::getelementsbytagnamens', + 'domelement::hasattribute', + 'domelement::hasattributens', + 'domelement::removeattribute', + 'domelement::removeattributenode', + 'domelement::removeattributens', + 'domelement::setattribute', + 'domelement::setattributens', + 'domelement::setidattribute', + 'domelement::setidattributenode', + 'domelement::setidattributens', + 'domimplementation::createdocument', + 'domimplementation::createdocumenttype', + 'domnamednodemap::getnameditem', + 'domnamednodemap::getnameditemns', + 'domnode::appendchild', + 'domnode::c14n', + 'domnode::c14nfile', + 'domnode::insertbefore', + 'domnode::isdefaultnamespace', + 'domnode::issamenode', + 'domnode::lookupprefix', + 'domnode::removechild', + 'domnode::replacechild', + 'domprocessinginstruction::__construct', + 'domtext::__construct', + 'domxpath::__construct', + 'domxpath::evaluate', + 'domxpath::query', + 'domxpath::registernamespace', + 'domxpath::registerphpfunctions', 'easter_date', - 'enchant_broker_describe', - 'enchant_broker_dict_exists', - 'enchant_broker_free', - 'enchant_broker_free_dict', - 'enchant_broker_get_dict_path', - 'enchant_broker_get_error', - 'enchant_broker_list_dicts', - 'enchant_broker_request_dict', - 'enchant_broker_request_pwl_dict', - 'enchant_broker_set_dict_path', - 'enchant_broker_set_ordering', - 'enchant_dict_add_to_personal', - 'enchant_dict_add_to_session', - 'enchant_dict_check', - 'enchant_dict_describe', - 'enchant_dict_get_error', - 'enchant_dict_is_in_session', - 'enchant_dict_quick_check', - 'enchant_dict_store_replacement', - 'enchant_dict_suggest', + 'error::__construct', + 'errorexception::__construct', + 'exception::__construct', + 'fiber::start', + 'filesystemiterator::__construct', + 'filesystemiterator::getfileinfo', + 'filesystemiterator::getpathinfo', + 'filesystemiterator::openfile', + 'filesystemiterator::seek', + 'filesystemiterator::setfileclass', + 'filesystemiterator::setflags', + 'filesystemiterator::setinfoclass', + 'finfo::__construct', + 'finfo::buffer', + 'finfo::file', + 'finfo::set_flags', + 'generator::throw', 'get_headers', + 'globiterator::__construct', + 'globiterator::getfileinfo', + 'globiterator::getpathinfo', + 'globiterator::openfile', + 'globiterator::seek', + 'globiterator::setfileclass', + 'globiterator::setflags', + 'globiterator::setinfoclass', 'gmp_clrbit', 'gmp_div', 'gmp_setbit', - 'gnupg_adddecryptkey', - 'gnupg_addencryptkey', - 'gnupg_addsignkey', - 'gnupg_cleardecryptkeys', - 'gnupg_clearencryptkeys', - 'gnupg_clearsignkeys', - 'gnupg_decrypt', - 'gnupg_decryptverify', - 'gnupg_encrypt', - 'gnupg_encryptsign', - 'gnupg_export', - 'gnupg_geterror', - 'gnupg_getprotocol', - 'gnupg_import', - 'gnupg_init', - 'gnupg_keyinfo', - 'gnupg_setarmor', - 'gnupg_seterrormode', - 'gnupg_setsignmode', - 'gnupg_sign', - 'gnupg_verify', 'hash_hmac_file', 'igbinary_unserialize', 'imagefilledpolygon', @@ -125,99 +227,204 @@ class InternalCallMapHandlerTest extends TestCase 'inflate_add', 'inflate_get_read_len', 'inflate_get_status', - 'inotify_rm_watch', + 'intlbreakiterator::getlocale', + 'intlbreakiterator::getpartsiterator', 'intlcal_from_date_time', 'intlcal_get_weekend_transition', + 'intlcalendar::add', + 'intlcalendar::createinstance', + 'intlcalendar::fielddifference', + 'intlcalendar::fromdatetime', + 'intlcalendar::getkeywordvaluesforlocale', + 'intlcalendar::getlocale', + 'intlcalendar::getweekendtransition', + 'intlcalendar::isweekend', + 'intlcalendar::roll', + 'intlcalendar::setlenient', + 'intlcalendar::setminimaldaysinfirstweek', + 'intlcalendar::setrepeatedwalltimeoption', + 'intlcalendar::setskippedwalltimeoption', + 'intlcalendar::settime', + 'intlcalendar::settimezone', + 'intlchar::charage', + 'intlchar::chardigitvalue', + 'intlchar::chardirection', + 'intlchar::charfromname', + 'intlchar::charmirror', + 'intlchar::charname', + 'intlchar::chartype', + 'intlchar::chr', + 'intlchar::digit', + 'intlchar::enumcharnames', + 'intlchar::enumchartypes', + 'intlchar::foldcase', + 'intlchar::fordigit', + 'intlchar::getbidipairedbracket', + 'intlchar::getblockcode', + 'intlchar::getcombiningclass', + 'intlchar::getfc_nfkc_closure', + 'intlchar::getintpropertyvalue', + 'intlchar::getnumericvalue', + 'intlchar::getpropertyname', + 'intlchar::getpropertyvaluename', + 'intlchar::hasbinaryproperty', + 'intlchar::isalnum', + 'intlchar::isalpha', + 'intlchar::isbase', + 'intlchar::isblank', + 'intlchar::iscntrl', + 'intlchar::isdefined', + 'intlchar::isdigit', + 'intlchar::isgraph', + 'intlchar::isidignorable', + 'intlchar::isidpart', + 'intlchar::isidstart', + 'intlchar::isisocontrol', + 'intlchar::isjavaidpart', + 'intlchar::isjavaidstart', + 'intlchar::isjavaspacechar', + 'intlchar::islower', + 'intlchar::ismirrored', + 'intlchar::isprint', + 'intlchar::ispunct', + 'intlchar::isspace', + 'intlchar::istitle', + 'intlchar::isualphabetic', + 'intlchar::isulowercase', + 'intlchar::isupper', + 'intlchar::isuuppercase', + 'intlchar::isuwhitespace', + 'intlchar::iswhitespace', + 'intlchar::isxdigit', + 'intlchar::ord', + 'intlchar::tolower', + 'intlchar::totitle', + 'intlchar::toupper', + 'intlcodepointbreakiterator::following', + 'intlcodepointbreakiterator::getlocale', + 'intlcodepointbreakiterator::getpartsiterator', + 'intlcodepointbreakiterator::isboundary', + 'intlcodepointbreakiterator::next', + 'intlcodepointbreakiterator::preceding', + 'intlexception::__construct', 'intlgregcal_create_instance', 'intlgregcal_is_leap_year', + 'intlgregoriancalendar::__construct', + 'intlgregoriancalendar::add', + 'intlgregoriancalendar::createinstance', + 'intlgregoriancalendar::fielddifference', + 'intlgregoriancalendar::fromdatetime', + 'intlgregoriancalendar::getkeywordvaluesforlocale', + 'intlgregoriancalendar::getlocale', + 'intlgregoriancalendar::getweekendtransition', + 'intlgregoriancalendar::isweekend', + 'intlgregoriancalendar::roll', + 'intlgregoriancalendar::setgregorianchange', + 'intlgregoriancalendar::setlenient', + 'intlgregoriancalendar::setminimaldaysinfirstweek', + 'intlgregoriancalendar::setrepeatedwalltimeoption', + 'intlgregoriancalendar::setskippedwalltimeoption', + 'intlgregoriancalendar::settime', + 'intlgregoriancalendar::settimezone', + 'intlrulebasedbreakiterator::__construct', + 'intlrulebasedbreakiterator::getlocale', + 'intlrulebasedbreakiterator::getpartsiterator', + 'intltimezone::countequivalentids', + 'intltimezone::createtimezone', + 'intltimezone::createtimezoneidenumeration', + 'intltimezone::fromdatetimezone', + 'intltimezone::getcanonicalid', + 'intltimezone::getdisplayname', + 'intltimezone::getequivalentid', + 'intltimezone::getidforwindowsid', + 'intltimezone::getoffset', + 'intltimezone::getregion', + 'intltimezone::getwindowsid', + 'intltimezone::hassamerules', 'intltz_create_enumeration', 'intltz_get_canonical_id', 'intltz_get_display_name', + 'invalidargumentexception::__construct', + 'iteratoriterator::__construct', + 'jsonexception::__construct', + 'lengthexception::__construct', + 'limititerator::__construct', + 'limititerator::seek', + 'locale::filtermatches', + 'locale::getdisplaylanguage', + 'locale::getdisplayname', + 'locale::getdisplayregion', + 'locale::getdisplayscript', + 'locale::getdisplayvariant', + 'locale::lookup', + 'logicexception::__construct', 'long2ip', - 'lzf_compress', - 'lzf_decompress', 'mail', - 'mailparse_msg_extract_part', - 'mailparse_msg_extract_part_file', - 'mailparse_msg_extract_whole_part_file', - 'mailparse_msg_free', - 'mailparse_msg_get_part', - 'mailparse_msg_get_part_data', - 'mailparse_msg_get_structure', - 'mailparse_msg_parse', - 'mailparse_stream_encode', - 'memcache_add', - 'memcache_add_server', - 'memcache_append', - 'memcache_cas', - 'memcache_close', - 'memcache_connect', - 'memcache_decrement', - 'memcache_delete', - 'memcache_flush', - 'memcache_get_extended_stats', - 'memcache_get_server_status', - 'memcache_get_stats', - 'memcache_get_version', - 'memcache_increment', - 'memcache_pconnect', - 'memcache_prepend', - 'memcache_replace', - 'memcache_set', - 'memcache_set_compress_threshold', - 'memcache_set_failure_callback', - 'memcache_set_server_params', - 'mongodb\bson\tophp', + 'messageformatter::format', + 'messageformatter::formatmessage', + 'messageformatter::parse', + 'messageformatter::parsemessage', + 'mongodb\bson\javascript::__construct', + 'mongodb\driver\bulkwrite::delete', + 'mongodb\driver\bulkwrite::update', + 'mongodb\driver\clientencryption::__construct', + 'mongodb\driver\clientencryption::decrypt', + 'mongodb\driver\command::__construct', + 'mongodb\driver\exception\runtimeexception::haserrorlabel', + 'mongodb\driver\manager::__construct', + 'mongodb\driver\manager::executebulkwrite', + 'mongodb\driver\manager::executequery', + 'mongodb\driver\manager::executereadcommand', + 'mongodb\driver\manager::executewritecommand', + 'mongodb\driver\query::__construct', + 'mongodb\driver\server::executebulkwrite', + 'mongodb\driver\server::executequery', + 'mongodb\driver\server::executereadcommand', + 'mongodb\driver\server::executereadwritecommand', + 'mongodb\driver\server::executewritecommand', + 'mongodb\driver\session::advanceoperationtime', + 'mongodb\driver\topologydescription::hasreadableserver', 'msg_receive', 'msg_remove_queue', 'msg_send', 'msg_set_queue', 'msg_stat_queue', + 'multipleiterator::attachiterator', + 'mysqli::poll', 'mysqli_poll', 'mysqli_real_connect', + 'mysqli_stmt::__construct', + 'mysqli_stmt::bind_param', 'mysqli_stmt_bind_param', + 'normalizer::getrawdecomposition', + 'normalizer::isnormalized', + 'normalizer::normalize', 'normalizer_get_raw_decomposition', - 'oauth_get_sbs', - 'oci_collection_append', - 'oci_collection_assign', - 'oci_collection_element_assign', - 'oci_collection_element_get', - 'oci_collection_max', - 'oci_collection_size', - 'oci_collection_trim', - 'oci_fetch_object', - 'oci_field_is_null', - 'oci_field_name', - 'oci_field_precision', - 'oci_field_scale', - 'oci_field_size', - 'oci_field_type', - 'oci_field_type_raw', - 'oci_free_collection', - 'oci_free_descriptor', - 'oci_lob_append', - 'oci_lob_eof', - 'oci_lob_erase', - 'oci_lob_export', - 'oci_lob_flush', - 'oci_lob_import', - 'oci_lob_load', - 'oci_lob_read', - 'oci_lob_rewind', - 'oci_lob_save', - 'oci_lob_seek', - 'oci_lob_size', - 'oci_lob_tell', - 'oci_lob_truncate', - 'oci_lob_write', - 'oci_register_taf_callback', - 'oci_result', - 'ocigetbufferinglob', - 'ocisetbufferinglob', + 'numberformatter::formatcurrency', + 'numberformatter::getattribute', + 'numberformatter::getsymbol', + 'numberformatter::gettextattribute', + 'numberformatter::parse', + 'numberformatter::parsecurrency', + 'numberformatter::setattribute', + 'numberformatter::setsymbol', + 'numberformatter::settextattribute', 'odbc_procedurecolumns', 'odbc_procedures', 'odbc_result', 'openssl_pkcs7_read', + 'outofboundsexception::__construct', + 'outofrangeexception::__construct', + 'overflowexception::__construct', + 'parseerror::__construct', + 'pdo::__construct', + 'pdo::exec', + 'pdo::prepare', + 'pdo::quote', + 'pdostatement::bindcolumn', + 'pdostatement::bindparam', + 'pdostatement::fetchobject', + 'pdostatement::getattribute', 'pg_exec', 'pg_fetch_all', 'pg_get_notify', @@ -225,13 +432,114 @@ class InternalCallMapHandlerTest extends TestCase 'pg_pconnect', 'pg_select', 'pg_send_execute', + 'phar::__construct', + 'phar::addemptydir', + 'phar::addfile', + 'phar::addfromstring', + 'phar::buildfromdirectory', + 'phar::buildfromiterator', + 'phar::cancompress', + 'phar::copy', + 'phar::count', + 'phar::createdefaultstub', + 'phar::delete', + 'phar::extractto', + 'phar::mapphar', + 'phar::mount', + 'phar::mungserver', + 'phar::offsetexists', + 'phar::offsetget', + 'phar::offsetset', + 'phar::offsetunset', + 'phar::running', + 'phar::setdefaultstub', + 'phar::setsignaturealgorithm', + 'phar::unlinkarchive', + 'phar::webphar', + 'phardata::__construct', + 'phardata::addemptydir', + 'phardata::addfile', + 'phardata::addfromstring', + 'phardata::buildfromdirectory', + 'phardata::buildfromiterator', + 'phardata::copy', + 'phardata::delete', + 'phardata::extractto', + 'phardata::offsetexists', + 'phardata::offsetget', + 'phardata::offsetset', + 'phardata::offsetunset', + 'phardata::setdefaultstub', + 'phardata::setsignaturealgorithm', + 'pharfileinfo::__construct', + 'pharfileinfo::chmod', + 'pharfileinfo::iscompressed', 'preg_filter', 'preg_replace_callback_array', - 'sapi_windows_cp_get', + 'rangeexception::__construct', + 'recursivearrayiterator::asort', + 'recursivearrayiterator::ksort', + 'recursivearrayiterator::offsetexists', + 'recursivearrayiterator::offsetget', + 'recursivearrayiterator::offsetset', + 'recursivearrayiterator::offsetunset', + 'recursivearrayiterator::seek', + 'recursivearrayiterator::setflags', + 'recursivearrayiterator::uasort', + 'recursivearrayiterator::uksort', + 'recursivearrayiterator::unserialize', + 'recursivecachingiterator::__construct', + 'recursivecachingiterator::offsetexists', + 'recursivecachingiterator::offsetget', + 'recursivecachingiterator::offsetset', + 'recursivecachingiterator::offsetunset', + 'recursivecallbackfilteriterator::__construct', + 'recursivedirectoryiterator::__construct', + 'recursivedirectoryiterator::getfileinfo', + 'recursivedirectoryiterator::getpathinfo', + 'recursivedirectoryiterator::haschildren', + 'recursivedirectoryiterator::openfile', + 'recursivedirectoryiterator::seek', + 'recursivedirectoryiterator::setfileclass', + 'recursivedirectoryiterator::setflags', + 'recursivedirectoryiterator::setinfoclass', + 'recursiveiteratoriterator::__construct', + 'recursiveiteratoriterator::setmaxdepth', + 'recursiveregexiterator::__construct', + 'recursiveregexiterator::setflags', + 'recursiveregexiterator::setmode', + 'recursiveregexiterator::setpregflags', + 'recursivetreeiterator::__construct', + 'recursivetreeiterator::setmaxdepth', + 'recursivetreeiterator::setpostfix', + 'recursivetreeiterator::setprefixpart', + 'reflectionclass::__construct', + 'reflectionclass::implementsinterface', + 'reflectionclassconstant::__construct', + 'reflectionfunction::__construct', + 'reflectiongenerator::__construct', + 'reflectionmethod::setaccessible', + 'reflectionobject::__construct', + 'reflectionobject::getconstants', + 'reflectionobject::getreflectionconstants', + 'reflectionobject::implementsinterface', + 'reflectionparameter::__construct', + 'reflectionproperty::__construct', + 'reflectionproperty::setaccessible', + 'regexiterator::__construct', + 'regexiterator::setflags', + 'regexiterator::setmode', + 'regexiterator::setpregflags', + 'resourcebundle::__construct', + 'resourcebundle::create', + 'resourcebundle::getlocales', + 'runtimeexception::__construct', 'sem_acquire', 'sem_get', 'sem_release', 'sem_remove', + 'sessionhandler::gc', + 'sessionhandler::open', 'shm_detach', 'shm_get_var', 'shm_has_var', @@ -243,9 +551,14 @@ class InternalCallMapHandlerTest extends TestCase 'shmop_read', 'shmop_size', 'shmop_write', - 'snmp_set_enum_print', - 'snmp_set_valueretrieval', - 'snmpset', + 'simplexmlelement::__construct', + 'simplexmlelement::addattribute', + 'simplexmlelement::addchild', + 'simplexmlelement::attributes', + 'simplexmlelement::children', + 'simplexmlelement::getdocnamespaces', + 'simplexmlelement::registerxpathnamespace', + 'simplexmlelement::xpath', 'socket_addrinfo_lookup', 'socket_bind', 'socket_cmsg_space', @@ -274,59 +587,104 @@ class InternalCallMapHandlerTest extends TestCase 'sodium_crypto_generichash_update', 'sodium_crypto_kx_client_session_keys', 'sodium_crypto_secretstream_xchacha20poly1305_rekey', - 'sqlsrv_connect', - 'sqlsrv_errors', - 'sqlsrv_fetch_array', - 'sqlsrv_fetch_object', - 'sqlsrv_get_field', - 'sqlsrv_prepare', - 'sqlsrv_query', - 'sqlsrv_server_info', + 'spldoublylinkedlist::add', + 'spldoublylinkedlist::offsetset', + 'spldoublylinkedlist::setiteratormode', + 'spldoublylinkedlist::unserialize', + 'splfileinfo::__construct', + 'splfileinfo::getfileinfo', + 'splfileinfo::getpathinfo', + 'splfileinfo::openfile', + 'splfileinfo::setfileclass', + 'splfileinfo::setinfoclass', + 'splfileobject::__construct', + 'splfileobject::fgetcsv', + 'splfileobject::flock', + 'splfileobject::fputcsv', + 'splfileobject::fseek', + 'splfileobject::fwrite', + 'splfileobject::getfileinfo', + 'splfileobject::getpathinfo', + 'splfileobject::openfile', + 'splfileobject::seek', + 'splfileobject::setcsvcontrol', + 'splfileobject::setfileclass', + 'splfileobject::setinfoclass', + 'splfileobject::setmaxlinelen', + 'splfixedarray::fromarray', + 'splfixedarray::offsetset', + 'splmaxheap::compare', + 'splminheap::compare', + 'splobjectstorage::addall', + 'splobjectstorage::attach', + 'splobjectstorage::count', + 'splobjectstorage::offsetset', + 'splobjectstorage::removeall', + 'splobjectstorage::removeallexcept', + 'splobjectstorage::setinfo', + 'splobjectstorage::unserialize', + 'splpriorityqueue::compare', + 'splqueue::offsetset', + 'splqueue::unserialize', + 'splstack::add', + 'splstack::offsetset', + 'splstack::unserialize', + 'spltempfileobject::__construct', + 'spltempfileobject::fgetcsv', + 'spltempfileobject::flock', + 'spltempfileobject::fputcsv', + 'spltempfileobject::fseek', + 'spltempfileobject::fwrite', + 'spltempfileobject::getfileinfo', + 'spltempfileobject::getpathinfo', + 'spltempfileobject::openfile', + 'spltempfileobject::seek', + 'spltempfileobject::setcsvcontrol', + 'spltempfileobject::setfileclass', + 'spltempfileobject::setinfoclass', + 'spltempfileobject::setmaxlinelen', + 'spoofchecker::areconfusable', + 'spoofchecker::issuspicious', + 'spoofchecker::setallowedlocales', + 'spoofchecker::setchecks', + 'spoofchecker::setrestrictionlevel', + 'sqlite3::__construct', + 'sqlite3::open', 'ssh2_forward_accept', - 'stomp_abort', - 'stomp_ack', - 'stomp_begin', - 'stomp_commit', - 'stomp_read_frame', - 'stomp_send', - 'stomp_set_read_timeout', - 'stomp_subscribe', - 'stomp_unsubscribe', - 'stream_select' => ['8.0'], 'substr_replace', - 'tidy_getopt', - 'uopz_allow_exit', - 'uopz_get_mock', - 'uopz_get_property', - 'uopz_get_return', - 'uopz_get_static', - 'uopz_set_mock', - 'uopz_set_property', - 'uopz_set_static', - 'uopz_unset_mock', - 'xdiff_file_bdiff', - 'xdiff_file_bdiff_size', - 'xdiff_file_diff', - 'xdiff_file_diff_binary', - 'xdiff_file_merge3', - 'xdiff_file_rabdiff', - 'xdiff_string_bdiff', - 'xdiff_string_bdiff_size', - 'xdiff_string_bpatch', - 'xdiff_string_diff', - 'xdiff_string_diff_binary', - 'xdiff_string_merge3', - 'xdiff_string_patch', - 'xdiff_string_patch_binary', - 'xdiff_string_rabdiff', - 'xmlrpc_server_add_introspection_data', - 'xmlrpc_server_call_method', - 'xmlrpc_server_destroy', - 'xmlrpc_server_register_introspection_callback', - 'xmlrpc_server_register_method', + 'transliterator::transliterate', + 'typeerror::__construct', + 'uconverter::convert', + 'uconverter::fromucallback', + 'uconverter::reasontext', + 'uconverter::transcode', + 'underflowexception::__construct', + 'unexpectedvalueexception::__construct', + 'xmlreader::getattributens', + 'xmlreader::movetoattributens', + 'xmlreader::next', + 'xmlreader::open', + 'xmlreader::xml', + 'xsltprocessor::registerphpfunctions', + 'xsltprocessor::transformtodoc', 'yaml_emit', 'yaml_emit_file', 'zip_entry_close', + 'ziparchive::addemptydir', + 'ziparchive::addfile', + 'ziparchive::addfromstring', + 'ziparchive::getfromindex', + 'ziparchive::getfromname', + 'ziparchive::getstream', + 'ziparchive::iscompressionmethodsupported', + 'ziparchive::isencryptionmethodsupported', + 'ziparchive::locatename', + 'ziparchive::open', + 'ziparchive::replacefile', + 'ziparchive::setcompressionindex', + 'ziparchive::setcompressionname', + 'ziparchive::setencryptionindex', + 'ziparchive::statname', 'zlib_encode', ]; @@ -336,17 +694,78 @@ class InternalCallMapHandlerTest extends TestCase * @var list */ private static $ignoredReturnTypeOnlyFunctions = [ + 'appenditerator::getinneriterator', + 'appenditerator::getiteratorindex', + 'arrayiterator::key', + 'arrayiterator::natcasesort', + 'arrayiterator::natsort', + 'arrayobject::getiterator', + 'arrayobject::natcasesort', + 'arrayobject::natsort', + 'badfunctioncallexception::getprevious', + 'badmethodcallexception::getprevious', 'bcsqrt', + 'cachingiterator::getinneriterator', + 'callbackfilteriterator::getinneriterator', + 'closedgeneratorexception::getprevious', + 'curl_multi_getcontent', 'curl_multi_init', - 'curl_multi_getcontent', // issue #8351 'datefmt_set_lenient', + 'datetime::__set_state', + 'datetime::add', + 'datetime::createfromimmutable', + 'datetime::createfrominterface', + 'datetime::setdate', + 'datetime::settimezone', + 'datetime::sub', + 'datetimeimmutable::__set_state', + 'datetimeimmutable::createfrominterface', 'deflate_init', - 'enchant_broker_init', + 'domainexception::getprevious', + 'domcharacterdata::appenddata', + 'domcharacterdata::deletedata', + 'domcharacterdata::insertdata', + 'domcharacterdata::replacedata', + 'domdocument::createcomment', + 'domdocument::createdocumentfragment', + 'emptyiterator::current', + 'emptyiterator::key', + 'error::getprevious', + 'errorexception::getprevious', + 'exception::getprevious', 'fgetcsv', + 'fiber::getcurrent', + 'filesystemiterator::_bad_state_ex', + 'filesystemiterator::current', 'filter_input_array', + 'filteriterator::getinneriterator', 'fpassthru', 'ftp_get_option', 'get_declared_traits', + 'globiterator::getatime', + 'globiterator::getbasename', + 'globiterator::getctime', + 'globiterator::getextension', + 'globiterator::getfilename', + 'globiterator::getgroup', + 'globiterator::getinode', + 'globiterator::getlinktarget', + 'globiterator::getmtime', + 'globiterator::getowner', + 'globiterator::getpath', + 'globiterator::getpathname', + 'globiterator::getperms', + 'globiterator::getrealpath', + 'globiterator::getsize', + 'globiterator::gettype', + 'globiterator::isdir', + 'globiterator::isdot', + 'globiterator::isexecutable', + 'globiterator::isfile', + 'globiterator::islink', + 'globiterator::isreadable', + 'globiterator::iswritable', + 'globiterator::valid', 'gmp_export', 'gmp_hamdist', 'gmp_import', @@ -360,7 +779,6 @@ class InternalCallMapHandlerTest extends TestCase 'imagecolorexactalpha', 'imagecolorresolve', 'imagecolorresolvealpha', - 'imagecolorset', 'imagecolorsforindex', 'imagecolorstotal', 'imagecolortransparent', @@ -370,58 +788,332 @@ class InternalCallMapHandlerTest extends TestCase 'imap_mailboxmsginfo', 'imap_msgno', 'imap_num_recent', + 'infiniteiterator::getinneriterator', 'inflate_init', + 'intlbreakiterator::createcharacterinstance', + 'intlbreakiterator::createlineinstance', + 'intlbreakiterator::createsentenceinstance', + 'intlbreakiterator::createtitleinstance', + 'intlbreakiterator::createwordinstance', + 'intlbreakiterator::gettext', + 'intlbreakiterator::settext', 'intlcal_get', 'intlcal_get_keyword_values_for_locale', + 'intlcodepointbreakiterator::createcharacterinstance', + 'intlcodepointbreakiterator::createlineinstance', + 'intlcodepointbreakiterator::createsentenceinstance', + 'intlcodepointbreakiterator::createtitleinstance', + 'intlcodepointbreakiterator::createwordinstance', + 'intlcodepointbreakiterator::gettext', + 'intlcodepointbreakiterator::settext', 'intlgregcal_set_gregorian_change', + 'intlrulebasedbreakiterator::createcharacterinstance', + 'intlrulebasedbreakiterator::createlineinstance', + 'intlrulebasedbreakiterator::createsentenceinstance', + 'intlrulebasedbreakiterator::createtitleinstance', + 'intlrulebasedbreakiterator::createwordinstance', + 'intlrulebasedbreakiterator::gettext', + 'intlrulebasedbreakiterator::settext', 'intltz_get_offset', + 'invalidargumentexception::getprevious', + 'iteratoriterator::getinneriterator', 'jddayofweek', 'jdtounix', 'ldap_count_entries', 'ldap_exop', 'ldap_get_attributes', + 'lengthexception::getprevious', + 'limititerator::getinneriterator', + 'locale::canonicalize', + 'locale::getallvariants', + 'locale::getkeywords', + 'locale::getprimarylanguage', + 'locale::getregion', + 'locale::getscript', + 'locale::parselocale', + 'logicexception::getprevious', 'mb_encoding_aliases', + 'messageformatter::create', 'metaphone', + 'mongodb\bson\binary::jsonserialize', + 'mongodb\bson\dbpointer::jsonserialize', + 'mongodb\bson\decimal128::jsonserialize', + 'mongodb\bson\int64::jsonserialize', + 'mongodb\bson\javascript::jsonserialize', + 'mongodb\bson\maxkey::jsonserialize', + 'mongodb\bson\minkey::jsonserialize', + 'mongodb\bson\objectid::jsonserialize', + 'mongodb\bson\regex::jsonserialize', + 'mongodb\bson\symbol::jsonserialize', + 'mongodb\bson\timestamp::jsonserialize', + 'mongodb\bson\utcdatetime::jsonserialize', + 'mongodb\bson\undefined::jsonserialize', 'msg_get_queue', + 'multipleiterator::current', + 'multipleiterator::setflags', + 'mysqli::get_charset', + 'mysqli_stmt::get_warnings', 'mysqli_stmt_get_warnings', 'mysqli_stmt_insert_id', + 'norewinditerator::getinneriterator', + 'numberformatter::create', 'numfmt_create', 'ob_list_handlers', 'openssl_random_pseudo_bytes', 'openssl_spki_export', 'openssl_spki_export_challenge', + 'outofboundsexception::getprevious', + 'outofrangeexception::getprevious', + 'overflowexception::getprevious', 'pack', + 'parentiterator::getchildren', + 'parentiterator::valid', 'parse_url', + 'parseerror::getprevious', 'passthru', 'pcntl_exec', 'pcntl_strerror', + 'pdo::getattribute', 'pg_port', + 'phar::compress', + 'phar::converttodata', + 'phar::converttoexecutable', + 'phar::decompress', + 'phar::getalias', + 'phar::iscompressed', + 'phardata::compress', + 'phardata::compressfiles', + 'phardata::converttodata', + 'phardata::converttoexecutable', + 'phardata::decompress', + 'phptoken::gettokenname', 'pspell_config_create', 'pspell_new', 'pspell_new_config', 'pspell_new_personal', + 'rangeexception::getprevious', + 'recursivearrayiterator::getchildren', + 'recursivearrayiterator::getflags', + 'recursivearrayiterator::key', + 'recursivearrayiterator::natcasesort', + 'recursivearrayiterator::natsort', + 'recursivecachingiterator::getchildren', + 'recursivecachingiterator::getinneriterator', + 'recursivecallbackfilteriterator::getinneriterator', + 'recursivedirectoryiterator::_bad_state_ex', + 'recursivefilteriterator::getchildren', + 'recursivefilteriterator::getinneriterator', + 'recursiveiteratoriterator::beginiteration', + 'recursiveiteratoriterator::callgetchildren', + 'recursiveiteratoriterator::enditeration', + 'recursiveiteratoriterator::getsubiterator', + 'recursiveregexiterator::current', + 'recursiveregexiterator::getinneriterator', + 'recursiveregexiterator::key', + 'recursiveregexiterator::next', + 'recursiveregexiterator::rewind', + 'recursiveregexiterator::valid', + 'recursivetreeiterator::beginiteration', + 'recursivetreeiterator::callgetchildren', + 'recursivetreeiterator::getsubiterator', + 'reflectionclass::getstaticproperties', + 'reflectionclass::gettraitaliases', + 'reflectionclass::gettraitnames', + 'reflectionclass::newinstanceargs', + 'reflectionfunction::getclosure', + 'reflectionfunction::getclosurescopeclass', + 'reflectionfunction::getclosurethis', + 'reflectionfunctionabstract::getextension', + 'reflectionmethod::getclosure', + 'reflectionmethod::getclosurescopeclass', + 'reflectionmethod::getclosurethis', + 'reflectionmethod::getextension', + 'reflectionobject::getstaticproperties', + 'reflectionobject::newinstanceargs', + 'reflectionparameter::iscallable', + 'regexiterator::getinneriterator', 'register_shutdown_function', + 'resourcebundle::get', 'rewinddir', + 'runtimeexception::getprevious', + 'sessionhandler::create_sid', 'shm_attach', 'shmop_open', 'simplexml_import_dom', + 'simplexmlelement::savexml', 'sleep', - 'snmp_set_oid_numeric_print', 'socket_import_stream', 'sodium_crypto_aead_chacha20poly1305_encrypt', 'sodium_crypto_aead_chacha20poly1305_ietf_encrypt', 'sodium_crypto_aead_xchacha20poly1305_ietf_encrypt', 'spl_autoload_functions', + 'spldoublylinkedlist::key', + 'spldoublylinkedlist::unshift', + 'splfileobject::fgets', + 'splfileobject::fpassthru', + 'splfileobject::fscanf', + 'splfileobject::getcurrentline', + 'splheap::recoverfromcorruption', + 'splminheap::insert', + 'splminheap::iscorrupted', + 'splminheap::key', + 'splminheap::recoverfromcorruption', + 'splobjectstorage::offsetunset', + 'splpriorityqueue::key', + 'splpriorityqueue::setextractflags', + 'splqueue::key', + 'splqueue::setiteratormode', + 'splqueue::unshift', + 'splstack::key', + 'splstack::setiteratormode', + 'splstack::unshift', + 'spltempfileobject::_bad_state_ex', + 'spltempfileobject::fpassthru', + 'spltempfileobject::fscanf', 'stream_bucket_new', 'stream_set_chunk_size', 'substr', 'substr_compare', + 'transliterator::createinverse', + 'typeerror::getprevious', + 'uconverter::getaliases', + 'uconverter::getdestinationencoding', + 'uconverter::getdestinationtype', + 'uconverter::geterrormessage', + 'uconverter::getsourceencoding', + 'uconverter::getsourcetype', + 'uconverter::getstandards', + 'uconverter::getsubstchars', + 'uconverter::toucallback', + 'underflowexception::getprevious', + 'unexpectedvalueexception::getprevious', 'user_error', 'xml_get_current_byte_index', 'xml_get_current_column_number', 'xml_get_current_line_number', 'xml_get_error_code', 'xml_parser_get_option', + 'xsltprocessor::transformtoxml', + 'ziparchive::addglob', + 'ziparchive::addpattern', + 'ziparchive::getstatusstring', + ]; + + /** + * List of function names to ignore because they cannot be reflected. + * + * These could be truly inaccessible, or they could be functions removed in newer PHP versions. + * Removed functions should be removed from CallMap and added to the appropriate delta. + * + * @var list + */ + private static $ignoredUnreflectableFunctions = [ + 'closure::__invoke', + 'curlfile::__wakeup', + 'domdocumenttype::entities', + 'domdocumenttype::internal_subset', + 'domdocumenttype::name', + 'domdocumenttype::notations', + 'domdocumenttype::public_id', + 'domdocumenttype::system_id', + 'domelement::get_attribute', + 'domelement::get_attribute_node', + 'domelement::get_elements_by_tagname', + 'domelement::has_attribute', + 'domelement::remove_attribute', + 'domelement::set_attribute', + 'domelement::set_attribute_node', + 'domelement::tagname', + 'domimplementation::__construct', + 'domnode::add_namespace', + 'domnode::append_child', + 'domprocessinginstruction::data', + 'domprocessinginstruction::target', + 'finfo::finfo', + 'generator::__wakeup', + 'gmp::__construct', + 'gmp::__tostring', + 'gmp::serialize', + 'gmp::unserialize', + 'intlchar::getintpropertymxvalue', + 'intliterator::__construct', + 'mongodb\driver\clientencryption::addkeyaltname', + 'mongodb\driver\clientencryption::deletekey', + 'mongodb\driver\clientencryption::getkey', + 'mongodb\driver\clientencryption::getkeybyaltname', + 'mongodb\driver\clientencryption::getkeys', + 'mongodb\driver\clientencryption::removekeyaltname', + 'mongodb\driver\clientencryption::rewrapmanydatakey', + 'mysqli::disable_reads_from_master', + 'mysqli::rpl_query_type', + 'mysqli::send_query', + 'mysqli::set_local_infile_default', + 'mysqli::set_local_infile_handler', + 'mysqli_driver::embedded_server_end', + 'mysqli_driver::embedded_server_start', + 'pdo::__sleep', + 'pdo::__wakeup', + 'pdo::cubrid_schema', + 'pdo::pgsqlcopyfromarray', + 'pdo::pgsqlcopyfromfile', + 'pdo::pgsqlcopytoarray', + 'pdo::pgsqlcopytofile', + 'pdo::pgsqlgetnotify', + 'pdo::pgsqlgetpid', + 'pdo::pgsqllobcreate', + 'pdo::pgsqllobopen', + 'pdo::pgsqllobunlink', + 'pdo::sqlitecreateaggregate', + 'pdo::sqlitecreatecollation', + 'pdo::sqlitecreatefunction', + 'pdostatement::__sleep', + 'pdostatement::__wakeup', + 'phar::compressallfilesbzip2', + 'phar::compressallfilesgz', + 'phar::uncompressallfiles', + 'pharfileinfo::iscompressedbzip2', + 'pharfileinfo::iscompressedgz', + 'pharfileinfo::setcompressedbzip2', + 'pharfileinfo::setcompressedgz', + 'pharfileinfo::setuncompressed', + 'reflection::export', + 'reflectionclass::export', + 'reflectionclassconstant::export', + 'reflectionextension::export', + 'reflectionfunction::export', + 'reflectionfunctionabstract::export', + 'reflectionmethod::export', + 'reflectionobject::export', + 'reflectionparameter::export', + 'reflectionproperty::export', + 'reflectionzendextension::export', + 'sessionhandler::updatetimestamp', + 'sessionhandler::validateid', + 'simplexmlelement::__get', + 'simplexmlelement::offsetexists', + 'simplexmlelement::offsetget', + 'simplexmlelement::offsetset', + 'simplexmlelement::offsetunset', + 'spldoublylinkedlist::__construct', + 'splfileinfo::__wakeup', + 'splfixedarray::current', + 'splfixedarray::key', + 'splfixedarray::next', + 'splfixedarray::rewind', + 'splfixedarray::valid', + 'splheap::__construct', + 'splmaxheap::__construct', + 'splobjectstorage::__construct', + 'splpriorityqueue::__construct', + 'splstack::__construct', + 'spltempfileobject::fgetss', + 'weakmap::__construct', + 'weakmap::current', + 'weakmap::key', + 'weakmap::next', + 'weakmap::rewind', + 'weakmap::valid', + 'ziparchive::createemptydir', ]; /** @@ -452,11 +1144,9 @@ public function testIgnoresAreSortedAndUnique(): void $diff = strcmp($function, $previousFunction); if ($diff <= 0) { - // faster debugging errors in tests - echo "\n" . $previousFunction . "\n" . $function . "\n"; + $this->fail("'{$function}' should come before '{$previousFunction}' in InternalCallMapHandlerTest::\$ignoredFunctions"); } - $this->assertGreaterThan(0, $diff); $previousFunction = $function; } } @@ -501,10 +1191,16 @@ public function callMapEntryProvider(): iterable ); $callMap = InternalCallMapHandler::getCallMap(); foreach ($callMap as $function => $entry) { - // Skip class methods - if (strpos($function, '::') !== false || !function_exists($function)) { + // Skip all Object::Method names with exceptions + if (strpos($function, '::') !== false) { + $className = substr($function, 0, strpos($function, '::')); + if (!class_exists($className, false)) { + continue; + } + } elseif (!function_exists($function)) { continue; } + // Skip functions with alternate signatures if (isset($callMap["$function'1"]) || preg_match("/\'\d$/", $function)) { continue; @@ -538,6 +1234,13 @@ private function isReturnTypeOnlyIgnored(string $functionName): bool return in_array($functionName, static::$ignoredReturnTypeOnlyFunctions, true); } + /** + */ + private function isUnreflectableIgnored(string $functionName): bool + { + return in_array($functionName, static::$ignoredUnreflectableFunctions, true); + } + /** * @depends testIgnoresAreSortedAndUnique * @depends testGetcallmapReturnsAValidCallmap @@ -549,13 +1252,21 @@ private function isReturnTypeOnlyIgnored(string $functionName): bool public function testIgnoredFunctionsStillFail(string $functionName, array $callMapEntry): void { $functionIgnored = $this->isIgnored($functionName); - if (!$functionIgnored && !$this->isReturnTypeOnlyIgnored($functionName)) { + $unreflectableIgnored = $this->isUnreflectableIgnored($functionName); + if (!$functionIgnored && !$this->isReturnTypeOnlyIgnored($functionName) && !$unreflectableIgnored) { // Dummy assertion to mark it as passed $this->assertTrue(true); return; } - $function = new ReflectionFunction($functionName); + $function = $this->getReflectionFunction($functionName); + if ($unreflectableIgnored && $function !== null) { + $this->fail("Remove '{$functionName}' from InternalCallMapHandlerTest::\$ignoredUnreflectableFunctions"); + } elseif ($function === null) { + $this->assertTrue(true); + return; + } + /** @var string $entryReturnType */ $entryReturnType = array_shift($callMapEntry); @@ -601,7 +1312,14 @@ public function testCallMapCompliesWithReflection(string $functionName, array $c $this->markTestSkipped("Function $functionName is ignored in config"); } - $function = new ReflectionFunction($functionName); + $function = $this->getReflectionFunction($functionName); + if ($function === null) { + if (!$this->isUnreflectableIgnored($functionName)) { + $this->fail('Unable to reflect method. Add name to $ignoredUnreflectableFunctions if exists in latest PHP version.'); + } + return; + } + /** @var string $entryReturnType */ $entryReturnType = array_shift($callMapEntry); @@ -613,11 +1331,27 @@ public function testCallMapCompliesWithReflection(string $functionName, array $c } } + /** + * Returns the correct reflection type for function or method name. + */ + private function getReflectionFunction(string $functionName): ?ReflectionFunctionAbstract + { + try { + if (strpos($functionName, '::') !== false) { + return new ReflectionMethod($functionName); + } + + return new ReflectionFunction($functionName); + } catch (ReflectionException $e) { + return null; + } + } + /** * * @param array $entryParameters */ - private function assertEntryParameters(ReflectionFunction $function, array $entryParameters): void + private function assertEntryParameters(ReflectionFunctionAbstract $function, array $entryParameters): void { /** * Parse the parameter names from the map. @@ -694,7 +1428,7 @@ private function assertParameter(array $normalizedEntry, ReflectionParameter $pa } /** @psalm-suppress UndefinedMethod */ - public function assertEntryReturnType(ReflectionFunction $function, string $entryReturnType): void + public function assertEntryReturnType(ReflectionFunctionAbstract $function, string $entryReturnType): void { if (version_compare(PHP_VERSION, '8.1.0', '>=')) { /** @var ReflectionType|null $expectedType */ @@ -703,10 +1437,9 @@ public function assertEntryReturnType(ReflectionFunction $function, string $entr $expectedType = $function->getReturnType(); } + $this->assertNotEmpty($entryReturnType, 'CallMap entry has empty return type'); if ($expectedType !== null) { $this->assertTypeValidity($expectedType, $entryReturnType, true, 'CallMap entry has incorrect return type, reflection returned: ' . $expectedType); - } else { - $this->assertNotEmpty($entryReturnType); } }