Core composer packages update
This commit is contained in:
3
vendor/vimeo/psalm/composer.json
vendored
3
vendor/vimeo/psalm/composer.json
vendored
@@ -39,6 +39,9 @@
|
||||
"symfony/console": "^4.1.6 || ^5.0 || ^6.0",
|
||||
"symfony/filesystem": "^5.4 || ^6.0"
|
||||
},
|
||||
"conflict": {
|
||||
"nikic/php-parser": "4.17.0"
|
||||
},
|
||||
"provide": {
|
||||
"psalm/psalm": "self.version"
|
||||
},
|
||||
|
||||
16
vendor/vimeo/psalm/dictionaries/CallMap.php
vendored
16
vendor/vimeo/psalm/dictionaries/CallMap.php
vendored
@@ -1679,10 +1679,10 @@ return [
|
||||
'DOMDocument::getElementsByTagName' => ['DOMNodeList', 'qualifiedName'=>'string'],
|
||||
'DOMDocument::getElementsByTagNameNS' => ['DOMNodeList', 'namespace'=>'?string', 'localName'=>'string'],
|
||||
'DOMDocument::importNode' => ['DOMNode|false', 'node'=>'DOMNode', 'deep='=>'bool'],
|
||||
'DOMDocument::load' => ['DOMDocument|bool', 'filename'=>'string', 'options='=>'int'],
|
||||
'DOMDocument::load' => ['bool', 'filename'=>'string', 'options='=>'int'],
|
||||
'DOMDocument::loadHTML' => ['bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
'DOMDocument::loadHTMLFile' => ['bool', 'filename'=>'string', 'options='=>'int'],
|
||||
'DOMDocument::loadXML' => ['DOMDocument|bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
'DOMDocument::loadXML' => ['bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
'DOMDocument::normalizeDocument' => ['void'],
|
||||
'DOMDocument::registerNodeClass' => ['bool', 'baseClass'=>'string', 'extendedClass'=>'?string'],
|
||||
'DOMDocument::relaxNGValidate' => ['bool', 'filename'=>'string'],
|
||||
@@ -7825,10 +7825,10 @@ return [
|
||||
'mysqli::begin_transaction' => ['bool', 'flags='=>'int', 'name='=>'?string'],
|
||||
'mysqli::change_user' => ['bool', 'username'=>'string', 'password'=>'string', 'database'=>'?string'],
|
||||
'mysqli::character_set_name' => ['string'],
|
||||
'mysqli::close' => ['bool'],
|
||||
'mysqli::close' => ['true'],
|
||||
'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::debug' => ['true', 'options'=>'string'],
|
||||
'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'],
|
||||
@@ -7857,7 +7857,7 @@ return [
|
||||
'mysqli::select_db' => ['bool', 'database'=>'string'],
|
||||
'mysqli::set_charset' => ['bool', 'charset'=>'string'],
|
||||
'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::ssl_set' => ['true', 'key'=>'?string', 'certificate'=>'?string', 'ca_certificate'=>'?string', 'ca_path'=>'?string', 'cipher_algos'=>'?string'],
|
||||
'mysqli::stat' => ['string|false'],
|
||||
'mysqli::stmt_init' => ['mysqli_stmt'],
|
||||
'mysqli::store_result' => ['mysqli_result|false', 'mode='=>'int'],
|
||||
@@ -7903,7 +7903,7 @@ return [
|
||||
'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'],
|
||||
'mysqli_field_count' => ['int', 'mysql'=>'mysqli'],
|
||||
'mysqli_field_seek' => ['bool', 'result'=>'mysqli_result', 'index'=>'int'],
|
||||
'mysqli_field_seek' => ['true', 'result'=>'mysqli_result', 'index'=>'int'],
|
||||
'mysqli_field_tell' => ['int', 'result'=>'mysqli_result'],
|
||||
'mysqli_free_result' => ['void', 'result'=>'mysqli_result'],
|
||||
'mysqli_get_cache_stats' => ['array|false'],
|
||||
@@ -7957,7 +7957,7 @@ return [
|
||||
'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'],
|
||||
'mysqli_result::field_seek' => ['true', 'index'=>'int'],
|
||||
'mysqli_result::free' => ['void'],
|
||||
'mysqli_result::free_result' => ['void'],
|
||||
'mysqli_rollback' => ['bool', 'mysql'=>'mysqli', 'flags='=>'int', 'name='=>'?string'],
|
||||
@@ -7981,7 +7981,7 @@ return [
|
||||
'mysqli_stmt::attr_set' => ['bool', 'attribute'=>'int', 'value'=>'int'],
|
||||
'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::close' => ['true'],
|
||||
'mysqli_stmt::data_seek' => ['void', 'offset'=>'int'],
|
||||
'mysqli_stmt::execute' => ['bool', 'params='=>'list<mixed>|null'],
|
||||
'mysqli_stmt::fetch' => ['bool|null'],
|
||||
|
||||
@@ -100,6 +100,22 @@ return [
|
||||
'old' => ['DOMNodeList', 'namespace'=>'string', 'localName'=>'string'],
|
||||
'new' => ['DOMNodeList', 'namespace'=>'?string', 'localName'=>'string'],
|
||||
],
|
||||
'DOMDocument::load' => [
|
||||
'old' => ['DOMDocument|bool', 'filename'=>'string', 'options='=>'int'],
|
||||
'new' => ['bool', 'filename'=>'string', 'options='=>'int'],
|
||||
],
|
||||
'DOMDocument::loadXML' => [
|
||||
'old' => ['DOMDocument|bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
'new' => ['bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
],
|
||||
'DOMDocument::loadHTML' => [
|
||||
'old' => ['DOMDocument|bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
'new' => ['bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
],
|
||||
'DOMDocument::loadHTMLFile' => [
|
||||
'old' => ['DOMDocument|bool', 'filename'=>'string', 'options='=>'int'],
|
||||
'new' => ['bool', 'filename'=>'string', 'options='=>'int'],
|
||||
],
|
||||
'DOMImplementation::createDocument' => [
|
||||
'old' => ['DOMDocument|false', 'namespace='=>'string', 'qualifiedName='=>'string', 'doctype='=>'DOMDocumentType'],
|
||||
'new' => ['DOMDocument|false', 'namespace='=>'?string', 'qualifiedName='=>'string', 'doctype='=>'?DOMDocumentType'],
|
||||
@@ -224,6 +240,14 @@ return [
|
||||
'old' => ['string', 'locale'=>'string', 'displayLocale='=>'string'],
|
||||
'new' => ['string', 'locale'=>'string', 'displayLocale='=>'?string'],
|
||||
],
|
||||
'mysqli_field_seek' => [
|
||||
'old' => ['bool', 'result'=>'mysqli_result', 'index'=>'int'],
|
||||
'new' => ['true', 'result'=>'mysqli_result', 'index'=>'int'],
|
||||
],
|
||||
'mysqli_result::field_seek' => [
|
||||
'old' => ['bool', 'index'=>'int'],
|
||||
'new' => ['true', 'index'=>'int'],
|
||||
],
|
||||
'mysqli_stmt::__construct' => [
|
||||
'old' => ['void', 'mysql'=>'mysqli', 'query='=>'string'],
|
||||
'new' => ['void', 'mysql'=>'mysqli', 'query='=>'?string'],
|
||||
|
||||
@@ -94,6 +94,10 @@ return [
|
||||
'old' => ['int|false', 'fields'=>'array<array-key, null|scalar|Stringable>', 'separator='=>'string', 'enclosure='=>'string', 'escape='=>'string'],
|
||||
'new' => ['int|false', 'fields'=>'array<array-key, null|scalar|Stringable>', 'separator='=>'string', 'enclosure='=>'string', 'escape='=>'string', 'eol='=>'string'],
|
||||
],
|
||||
'hash_pbkdf2' => [
|
||||
'old' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'binary='=>'bool'],
|
||||
'new' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'binary='=>'bool', 'options=' => 'array'],
|
||||
],
|
||||
'finfo_buffer' => [
|
||||
'old' => ['string|false', 'finfo'=>'resource', 'string'=>'string', 'flags='=>'int', 'context='=>'resource'],
|
||||
'new' => ['string|false', 'finfo'=>'finfo', 'string'=>'string', 'flags='=>'int', 'context='=>'resource'],
|
||||
|
||||
@@ -49,10 +49,6 @@ return [
|
||||
'old' => ['bool', '&rw_array'=>'array', 'flags='=>'int'],
|
||||
'new' => ['true', '&rw_array'=>'array', 'flags='=>'int'],
|
||||
],
|
||||
'hash_pbkdf2' => [
|
||||
'old' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'binary='=>'bool'],
|
||||
'new' => ['non-empty-string', 'algo'=>'string', 'password'=>'string', 'salt'=>'string', 'iterations'=>'int', 'length='=>'int', 'binary='=>'bool', 'options=' => 'array'],
|
||||
],
|
||||
'imap_setflag_full' => [
|
||||
'old' => ['bool', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'],
|
||||
'new' => ['true', 'imap'=>'IMAP\Connection', 'sequence'=>'string', 'flag'=>'string', 'options='=>'int'],
|
||||
|
||||
@@ -733,8 +733,8 @@ return [
|
||||
'DOMDocument::getElementsByTagNameNS' => ['DOMNodeList', 'namespace'=>'string', 'localName'=>'string'],
|
||||
'DOMDocument::importNode' => ['DOMNode|false', 'node'=>'DOMNode', 'deep='=>'bool'],
|
||||
'DOMDocument::load' => ['DOMDocument|bool', 'filename'=>'string', 'options='=>'int'],
|
||||
'DOMDocument::loadHTML' => ['bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
'DOMDocument::loadHTMLFile' => ['bool', 'filename'=>'string', 'options='=>'int'],
|
||||
'DOMDocument::loadHTML' => ['DOMDocument|bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
'DOMDocument::loadHTMLFile' => ['DOMDocument|bool', 'filename'=>'string', 'options='=>'int'],
|
||||
'DOMDocument::loadXML' => ['DOMDocument|bool', 'source'=>'non-empty-string', 'options='=>'int'],
|
||||
'DOMDocument::normalizeDocument' => ['void'],
|
||||
'DOMDocument::registerNodeClass' => ['bool', 'baseClass'=>'string', 'extendedClass'=>'?string'],
|
||||
@@ -12737,10 +12737,10 @@ return [
|
||||
'mysqli::begin_transaction' => ['bool', 'flags='=>'int', 'name='=>'string'],
|
||||
'mysqli::change_user' => ['bool', 'username'=>'string', 'password'=>'string', 'database'=>'?string'],
|
||||
'mysqli::character_set_name' => ['string'],
|
||||
'mysqli::close' => ['bool'],
|
||||
'mysqli::close' => ['true'],
|
||||
'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::debug' => ['true', 'options'=>'string'],
|
||||
'mysqli::dump_debug_info' => ['bool'],
|
||||
'mysqli::escape_string' => ['string', 'string'=>'string'],
|
||||
'mysqli::get_charset' => ['object'],
|
||||
@@ -12768,7 +12768,7 @@ return [
|
||||
'mysqli::select_db' => ['bool', 'database'=>'string'],
|
||||
'mysqli::set_charset' => ['bool', 'charset'=>'string'],
|
||||
'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::ssl_set' => ['true', 'key'=>'?string', 'certificate'=>'?string', 'ca_certificate'=>'?string', 'ca_path'=>'?string', 'cipher_algos'=>'?string'],
|
||||
'mysqli::stat' => ['string|false'],
|
||||
'mysqli::stmt_init' => ['mysqli_stmt'],
|
||||
'mysqli::store_result' => ['mysqli_result|false', 'mode='=>'int'],
|
||||
@@ -12889,7 +12889,7 @@ return [
|
||||
'mysqli_stmt::attr_set' => ['bool', 'attribute'=>'int', 'value'=>'int'],
|
||||
'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::close' => ['true'],
|
||||
'mysqli_stmt::data_seek' => ['void', 'offset'=>'int'],
|
||||
'mysqli_stmt::execute' => ['bool'],
|
||||
'mysqli_stmt::fetch' => ['bool|null'],
|
||||
|
||||
1
vendor/vimeo/psalm/src/Psalm/Codebase.php
vendored
1
vendor/vimeo/psalm/src/Psalm/Codebase.php
vendored
@@ -699,6 +699,7 @@ final class Codebase
|
||||
);
|
||||
}
|
||||
|
||||
/** @psalm-mutation-free */
|
||||
public function classExtendsOrImplements(string $fq_class_name, string $possible_parent): bool
|
||||
{
|
||||
return $this->classlikes->classExtends($fq_class_name, $possible_parent)
|
||||
|
||||
53
vendor/vimeo/psalm/src/Psalm/Config.php
vendored
53
vendor/vimeo/psalm/src/Psalm/Config.php
vendored
@@ -42,7 +42,6 @@ use Psalm\Progress\Progress;
|
||||
use Psalm\Progress\VoidProgress;
|
||||
use RuntimeException;
|
||||
use SimpleXMLElement;
|
||||
use SimpleXMLIterator;
|
||||
use Symfony\Component\Filesystem\Path;
|
||||
use Throwable;
|
||||
use UnexpectedValueException;
|
||||
@@ -728,8 +727,6 @@ class Config
|
||||
$this->eventDispatcher = new EventDispatcher();
|
||||
$this->universal_object_crates = [
|
||||
strtolower(stdClass::class),
|
||||
strtolower(SimpleXMLElement::class),
|
||||
strtolower(SimpleXMLIterator::class),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1030,7 +1027,6 @@ class Config
|
||||
|
||||
/**
|
||||
* @param non-empty-string $file_contents
|
||||
* @psalm-suppress MixedMethodCall
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress MixedArgument
|
||||
* @psalm-suppress MixedPropertyFetch
|
||||
@@ -1161,12 +1157,13 @@ class Config
|
||||
}
|
||||
|
||||
if (isset($config_xml['autoloader'])) {
|
||||
$autoloader_path = $config->base_dir . DIRECTORY_SEPARATOR . $config_xml['autoloader'];
|
||||
$autoloader = (string) $config_xml['autoloader'];
|
||||
$autoloader_path = $config->base_dir . DIRECTORY_SEPARATOR . $autoloader;
|
||||
|
||||
if (!file_exists($autoloader_path)) {
|
||||
// in here for legacy reasons where people put absolute paths but psalm resolved it relative
|
||||
if ($config_xml['autoloader']->__toString()[0] === '/') {
|
||||
$autoloader_path = $config_xml['autoloader']->__toString();
|
||||
if ($autoloader[0] === '/') {
|
||||
$autoloader_path = $autoloader;
|
||||
}
|
||||
|
||||
if (!file_exists($autoloader_path)) {
|
||||
@@ -1312,7 +1309,7 @@ class Config
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($config_xml->fileExtensions)) {
|
||||
if (isset($config_xml->fileExtensions->extension)) {
|
||||
$config->file_extensions = [];
|
||||
|
||||
$config->loadFileExtensions($config_xml->fileExtensions->extension);
|
||||
@@ -1336,7 +1333,6 @@ class Config
|
||||
|
||||
if (isset($config_xml->ignoreExceptions)) {
|
||||
if (isset($config_xml->ignoreExceptions->class)) {
|
||||
/** @var SimpleXMLElement $exception_class */
|
||||
foreach ($config_xml->ignoreExceptions->class as $exception_class) {
|
||||
$exception_name = (string) $exception_class['name'];
|
||||
$global_attribute_text = (string) $exception_class['onlyGlobalScope'];
|
||||
@@ -1347,7 +1343,6 @@ class Config
|
||||
}
|
||||
}
|
||||
if (isset($config_xml->ignoreExceptions->classAndDescendants)) {
|
||||
/** @var SimpleXMLElement $exception_class */
|
||||
foreach ($config_xml->ignoreExceptions->classAndDescendants as $exception_class) {
|
||||
$exception_name = (string) $exception_class['name'];
|
||||
$global_attribute_text = (string) $exception_class['onlyGlobalScope'];
|
||||
@@ -1401,7 +1396,6 @@ class Config
|
||||
// this plugin loading system borrows heavily from etsy/phan
|
||||
if (isset($config_xml->plugins)) {
|
||||
if (isset($config_xml->plugins->plugin)) {
|
||||
/** @var SimpleXMLElement $plugin */
|
||||
foreach ($config_xml->plugins->plugin as $plugin) {
|
||||
$plugin_file_name = (string) $plugin['filename'];
|
||||
|
||||
@@ -1413,7 +1407,6 @@ class Config
|
||||
}
|
||||
}
|
||||
if (isset($config_xml->plugins->pluginClass)) {
|
||||
/** @var SimpleXMLElement $plugin */
|
||||
foreach ($config_xml->plugins->pluginClass as $plugin) {
|
||||
$plugin_class_name = $plugin['class'];
|
||||
// any child elements are used as plugin configuration
|
||||
@@ -1429,21 +1422,23 @@ class Config
|
||||
|
||||
if (isset($config_xml->issueHandlers)) {
|
||||
foreach ($config_xml->issueHandlers as $issue_handlers) {
|
||||
/** @var SimpleXMLElement $issue_handler */
|
||||
foreach ($issue_handlers->children() as $key => $issue_handler) {
|
||||
if ($key === 'PluginIssue') {
|
||||
$custom_class_name = (string) $issue_handler['name'];
|
||||
/** @var string $key */
|
||||
$config->issue_handlers[$custom_class_name] = IssueHandler::loadFromXMLElement(
|
||||
$issue_handler,
|
||||
$base_dir,
|
||||
);
|
||||
} else {
|
||||
/** @var string $key */
|
||||
$config->issue_handlers[$key] = IssueHandler::loadFromXMLElement(
|
||||
$issue_handler,
|
||||
$base_dir,
|
||||
);
|
||||
$issue_handler_children = $issue_handlers->children();
|
||||
if ($issue_handler_children) {
|
||||
foreach ($issue_handler_children as $key => $issue_handler) {
|
||||
if ($key === 'PluginIssue') {
|
||||
$custom_class_name = (string)$issue_handler['name'];
|
||||
/** @var string $key */
|
||||
$config->issue_handlers[$custom_class_name] = IssueHandler::loadFromXMLElement(
|
||||
$issue_handler,
|
||||
$base_dir,
|
||||
);
|
||||
} else {
|
||||
/** @var string $key */
|
||||
$config->issue_handlers[$key] = IssueHandler::loadFromXMLElement(
|
||||
$issue_handler,
|
||||
$base_dir,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2263,6 +2258,10 @@ class Config
|
||||
$stubsDir . 'SPL.phpstub',
|
||||
];
|
||||
|
||||
if ($codebase->analysis_php_version_id >= 7_04_00) {
|
||||
$this->internal_stubs[] = $stubsDir . 'Php74.phpstub';
|
||||
}
|
||||
|
||||
if ($codebase->analysis_php_version_id >= 8_00_00) {
|
||||
$this->internal_stubs[] = $stubsDir . 'CoreGenericAttributes.phpstub';
|
||||
$this->internal_stubs[] = $stubsDir . 'Php80.phpstub';
|
||||
|
||||
@@ -389,7 +389,6 @@ class FileFilter
|
||||
|
||||
if ($e->directory) {
|
||||
$config['directory'] = [];
|
||||
/** @var SimpleXMLElement $directory */
|
||||
foreach ($e->directory as $directory) {
|
||||
$config['directory'][] = [
|
||||
'name' => (string) $directory['name'],
|
||||
@@ -402,7 +401,6 @@ class FileFilter
|
||||
|
||||
if ($e->file) {
|
||||
$config['file'] = [];
|
||||
/** @var SimpleXMLElement $file */
|
||||
foreach ($e->file as $file) {
|
||||
$config['file'][]['name'] = (string) $file['name'];
|
||||
}
|
||||
@@ -410,7 +408,6 @@ class FileFilter
|
||||
|
||||
if ($e->referencedClass) {
|
||||
$config['referencedClass'] = [];
|
||||
/** @var SimpleXMLElement $referenced_class */
|
||||
foreach ($e->referencedClass as $referenced_class) {
|
||||
$config['referencedClass'][]['name'] = strtolower((string)$referenced_class['name']);
|
||||
}
|
||||
@@ -418,7 +415,6 @@ class FileFilter
|
||||
|
||||
if ($e->referencedMethod) {
|
||||
$config['referencedMethod'] = [];
|
||||
/** @var SimpleXMLElement $referenced_method */
|
||||
foreach ($e->referencedMethod as $referenced_method) {
|
||||
$config['referencedMethod'][]['name'] = (string)$referenced_method['name'];
|
||||
}
|
||||
@@ -426,7 +422,6 @@ class FileFilter
|
||||
|
||||
if ($e->referencedFunction) {
|
||||
$config['referencedFunction'] = [];
|
||||
/** @var SimpleXMLElement $referenced_function */
|
||||
foreach ($e->referencedFunction as $referenced_function) {
|
||||
$config['referencedFunction'][]['name'] = strtolower((string)$referenced_function['name']);
|
||||
}
|
||||
@@ -434,7 +429,6 @@ class FileFilter
|
||||
|
||||
if ($e->referencedProperty) {
|
||||
$config['referencedProperty'] = [];
|
||||
/** @var SimpleXMLElement $referenced_property */
|
||||
foreach ($e->referencedProperty as $referenced_property) {
|
||||
$config['referencedProperty'][]['name'] = strtolower((string)$referenced_property['name']);
|
||||
}
|
||||
@@ -442,7 +436,6 @@ class FileFilter
|
||||
|
||||
if ($e->referencedConstant) {
|
||||
$config['referencedConstant'] = [];
|
||||
/** @var SimpleXMLElement $referenced_constant */
|
||||
foreach ($e->referencedConstant as $referenced_constant) {
|
||||
$config['referencedConstant'][]['name'] = strtolower((string)$referenced_constant['name']);
|
||||
}
|
||||
@@ -450,8 +443,6 @@ class FileFilter
|
||||
|
||||
if ($e->referencedVariable) {
|
||||
$config['referencedVariable'] = [];
|
||||
|
||||
/** @var SimpleXMLElement $referenced_variable */
|
||||
foreach ($e->referencedVariable as $referenced_variable) {
|
||||
$config['referencedVariable'][]['name'] = strtolower((string)$referenced_variable['name']);
|
||||
}
|
||||
|
||||
@@ -38,9 +38,10 @@ final class IssueHandler
|
||||
}
|
||||
}
|
||||
|
||||
/** @var SimpleXMLElement $error_level */
|
||||
foreach ($e->errorLevel as $error_level) {
|
||||
$handler->custom_levels[] = ErrorLevelFileFilter::loadFromXMLElement($error_level, $base_dir, true);
|
||||
if (isset($e->errorLevel)) {
|
||||
foreach ($e->errorLevel as $error_level) {
|
||||
$handler->custom_levels[] = ErrorLevelFileFilter::loadFromXMLElement($error_level, $base_dir, true);
|
||||
}
|
||||
}
|
||||
|
||||
return $handler;
|
||||
|
||||
@@ -28,7 +28,6 @@ final class ProjectFileFilter extends FileFilter
|
||||
throw new ConfigException('Cannot nest ignoreFiles inside itself');
|
||||
}
|
||||
|
||||
/** @var SimpleXMLElement $e->ignoreFiles */
|
||||
$filter->file_filter = static::loadFromXMLElement($e->ignoreFiles, $base_dir, false);
|
||||
}
|
||||
|
||||
|
||||
16
vendor/vimeo/psalm/src/Psalm/Context.php
vendored
16
vendor/vimeo/psalm/src/Psalm/Context.php
vendored
@@ -12,7 +12,8 @@ use Psalm\Internal\Scope\LoopScope;
|
||||
use Psalm\Internal\Type\AssertionReconciler;
|
||||
use Psalm\Storage\FunctionLikeStorage;
|
||||
use Psalm\Type\Atomic\DependentType;
|
||||
use Psalm\Type\Atomic\TArray;
|
||||
use Psalm\Type\Atomic\TIntRange;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Union;
|
||||
use RuntimeException;
|
||||
|
||||
@@ -868,10 +869,19 @@ final class Context
|
||||
public function defineGlobals(): void
|
||||
{
|
||||
$globals = [
|
||||
// not sure why this is declared here again, see VariableFetchAnalyzer
|
||||
'$argv' => new Union([
|
||||
new TArray([Type::getInt(), Type::getString()]),
|
||||
Type::getNonEmptyListAtomic(Type::getString()),
|
||||
new TNull(),
|
||||
], [
|
||||
'ignore_nullable_issues' => true,
|
||||
]),
|
||||
'$argc' => new Union([
|
||||
new TIntRange(1, null),
|
||||
new TNull(),
|
||||
], [
|
||||
'ignore_nullable_issues' => true,
|
||||
]),
|
||||
'$argc' => Type::getInt(),
|
||||
];
|
||||
|
||||
$config = Config::getInstance();
|
||||
|
||||
@@ -200,6 +200,10 @@ class ProjectAnalyzer
|
||||
UnnecessaryVarAnnotation::class,
|
||||
];
|
||||
|
||||
private const PHP_VERSION_REGEX = '^(0|[1-9]\d*)\.(0|[1-9]\d*)(?:\..*)?$';
|
||||
|
||||
private const PHP_SUPPORTED_VERSIONS_REGEX = '^(5\.[456]|7\.[01234]|8\.[0123])(\..*)?$';
|
||||
|
||||
/**
|
||||
* @param array<ReportOptions> $generated_report_options
|
||||
*/
|
||||
@@ -1179,8 +1183,16 @@ class ProjectAnalyzer
|
||||
*/
|
||||
public function setPhpVersion(string $version, string $source): void
|
||||
{
|
||||
if (!preg_match('/^(5\.[456]|7\.[01234]|8\.[012])(\..*)?$/', $version)) {
|
||||
throw new UnexpectedValueException('Expecting a version number in the format x.y');
|
||||
if (!preg_match('/' . self::PHP_VERSION_REGEX . '/', $version)) {
|
||||
throw new UnexpectedValueException('Expecting a version number in the format x.y or x.y.z');
|
||||
}
|
||||
|
||||
if (!preg_match('/' . self::PHP_SUPPORTED_VERSIONS_REGEX . '/', $version)) {
|
||||
throw new UnexpectedValueException(
|
||||
'Psalm supports PHP version ">=5.4". The specified version '
|
||||
. $version
|
||||
. " is either not supported or doesn't exist.",
|
||||
);
|
||||
}
|
||||
|
||||
[$php_major_version, $php_minor_version] = explode('.', $version);
|
||||
|
||||
@@ -755,20 +755,6 @@ class ForeachAnalyzer
|
||||
|
||||
$has_valid_iterator = true;
|
||||
|
||||
if ($iterator_atomic_type instanceof TNamedObject
|
||||
&& strtolower($iterator_atomic_type->value) === 'simplexmlelement'
|
||||
) {
|
||||
$value_type = Type::combineUnionTypes(
|
||||
$value_type,
|
||||
new Union([$iterator_atomic_type]),
|
||||
);
|
||||
|
||||
$key_type = Type::combineUnionTypes(
|
||||
$key_type,
|
||||
Type::getString(),
|
||||
);
|
||||
}
|
||||
|
||||
if ($iterator_atomic_type instanceof TIterable
|
||||
|| (strtolower($iterator_atomic_type->value) === 'traversable'
|
||||
|| $codebase->classImplements(
|
||||
|
||||
@@ -29,6 +29,7 @@ use Psalm\Issue\UndefinedMethod;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TNamedObject;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
use Psalm\Type\Union;
|
||||
|
||||
@@ -412,7 +413,7 @@ class MethodCallAnalyzer extends CallAnalyzer
|
||||
$types = $class_type->getAtomicTypes();
|
||||
|
||||
foreach ($types as $key => &$type) {
|
||||
if (!$type instanceof TNamedObject) {
|
||||
if (!$type instanceof TNamedObject && !$type instanceof TObject) {
|
||||
unset($types[$key]);
|
||||
} else {
|
||||
$type = $type->setFromDocblock(false);
|
||||
|
||||
@@ -1737,8 +1737,12 @@ class ArrayFetchAnalyzer
|
||||
?Union &$array_access_type,
|
||||
bool &$has_array_access
|
||||
): void {
|
||||
if (strtolower($type->value) === 'simplexmlelement') {
|
||||
$call_array_access_type = new Union([new TNamedObject('SimpleXMLElement')]);
|
||||
$codebase = $statements_analyzer->getCodebase();
|
||||
if (strtolower($type->value) === 'simplexmlelement'
|
||||
|| ($codebase->classExists($type->value)
|
||||
&& $codebase->classExtendsOrImplements($type->value, 'SimpleXMLElement'))
|
||||
) {
|
||||
$call_array_access_type = new Union([new TNull(), new TNamedObject('SimpleXMLElement')]);
|
||||
} elseif (strtolower($type->value) === 'domnodelist' && $stmt->dim) {
|
||||
$old_data_provider = $statements_analyzer->node_data;
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ class AtomicPropertyFetchAnalyzer
|
||||
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);
|
||||
self::handleEnumName($statements_analyzer, $stmt, $stmt_var_type, $class_storage);
|
||||
} else {
|
||||
self::handleNonExistentProperty(
|
||||
$statements_analyzer,
|
||||
@@ -979,16 +979,31 @@ class AtomicPropertyFetchAnalyzer
|
||||
private static function handleEnumName(
|
||||
StatementsAnalyzer $statements_analyzer,
|
||||
PropertyFetch $stmt,
|
||||
Atomic $lhs_type_part
|
||||
Union $stmt_var_type,
|
||||
ClassLikeStorage $class_storage
|
||||
): void {
|
||||
if ($lhs_type_part instanceof TEnumCase) {
|
||||
$statements_analyzer->node_data->setType(
|
||||
$stmt,
|
||||
new Union([Type::getAtomicStringFromLiteral($lhs_type_part->case_name)]),
|
||||
);
|
||||
} else {
|
||||
$statements_analyzer->node_data->setType($stmt, Type::getNonEmptyString());
|
||||
$relevant_enum_cases = array_filter(
|
||||
$stmt_var_type->getAtomicTypes(),
|
||||
static fn(Atomic $type): bool => $type instanceof TEnumCase,
|
||||
);
|
||||
$relevant_enum_case_names = array_map(
|
||||
static fn(TEnumCase $enumCase): string => $enumCase->case_name,
|
||||
$relevant_enum_cases,
|
||||
);
|
||||
|
||||
if (empty($relevant_enum_case_names)) {
|
||||
$relevant_enum_case_names = array_keys($class_storage->enum_cases);
|
||||
}
|
||||
|
||||
$statements_analyzer->node_data->setType(
|
||||
$stmt,
|
||||
empty($relevant_enum_case_names)
|
||||
? Type::getNonEmptyString()
|
||||
: new Union(array_map(
|
||||
fn(string $name): TString => Type::getAtomicStringFromLiteral($name),
|
||||
$relevant_enum_case_names,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
private static function handleEnumValue(
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
namespace Psalm\Internal\Analyzer\Statements\Expression;
|
||||
|
||||
use PhpParser;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\Context;
|
||||
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
|
||||
use Psalm\Internal\Analyzer\StatementsAnalyzer;
|
||||
use Psalm\Issue\InvalidArgument;
|
||||
use Psalm\IssueBuffer;
|
||||
use Psalm\Type;
|
||||
|
||||
/**
|
||||
@@ -30,6 +33,15 @@ class IssetAnalyzer
|
||||
$context->vars_in_scope[$var_id] = Type::getMixed();
|
||||
$context->vars_possibly_in_scope[$var_id] = true;
|
||||
}
|
||||
} elseif (!self::isValidStatement($isset_var)) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidArgument(
|
||||
'Isset only works with variables and array elements',
|
||||
new CodeLocation($statements_analyzer->getSource(), $isset_var),
|
||||
'empty',
|
||||
),
|
||||
$statements_analyzer->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
|
||||
self::analyzeIssetVar($statements_analyzer, $isset_var, $context);
|
||||
@@ -49,4 +61,15 @@ class IssetAnalyzer
|
||||
|
||||
$context->inside_isset = false;
|
||||
}
|
||||
|
||||
private static function isValidStatement(PhpParser\Node\Expr $stmt): bool
|
||||
{
|
||||
return $stmt instanceof PhpParser\Node\Expr\Variable
|
||||
|| $stmt instanceof PhpParser\Node\Expr\ArrayDimFetch
|
||||
|| $stmt instanceof PhpParser\Node\Expr\PropertyFetch
|
||||
|| $stmt instanceof PhpParser\Node\Expr\StaticPropertyFetch
|
||||
|| $stmt instanceof PhpParser\Node\Expr\NullsafePropertyFetch
|
||||
|| $stmt instanceof PhpParser\Node\Expr\ClassConstFetch
|
||||
|| $stmt instanceof PhpParser\Node\Expr\AssignRef;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ use Psalm\Exception\ConfigNotFoundException;
|
||||
use Psalm\Internal\Analyzer\ProjectAnalyzer;
|
||||
use Psalm\Report;
|
||||
use RuntimeException;
|
||||
use UnexpectedValueException;
|
||||
|
||||
use function array_filter;
|
||||
use function array_key_exists;
|
||||
@@ -485,7 +486,15 @@ final class CliUtils
|
||||
}
|
||||
|
||||
if ($version !== null && $source !== null) {
|
||||
$project_analyzer->setPhpVersion($version, $source);
|
||||
try {
|
||||
$project_analyzer->setPhpVersion($version, $source);
|
||||
} catch (UnexpectedValueException $e) {
|
||||
fwrite(
|
||||
STDERR,
|
||||
$e->getMessage() . PHP_EOL,
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -597,6 +597,7 @@ class ClassLikes
|
||||
/**
|
||||
* Determine whether or not a class extends a parent
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
* @throws UnpopulatedClasslikeException when called on unpopulated class
|
||||
* @throws InvalidArgumentException when class does not exist
|
||||
*/
|
||||
@@ -620,6 +621,8 @@ class ClassLikes
|
||||
|
||||
/**
|
||||
* Check whether a class implements an interface
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function classImplements(string $fq_class_name, string $interface): bool
|
||||
{
|
||||
|
||||
@@ -23,7 +23,6 @@ use LanguageServerProtocol\CodeDescription;
|
||||
use LanguageServerProtocol\CompletionOptions;
|
||||
use LanguageServerProtocol\Diagnostic;
|
||||
use LanguageServerProtocol\DiagnosticSeverity;
|
||||
use LanguageServerProtocol\ExecuteCommandOptions;
|
||||
use LanguageServerProtocol\InitializeResult;
|
||||
use LanguageServerProtocol\InitializeResultServerInfo;
|
||||
use LanguageServerProtocol\LogMessage;
|
||||
@@ -446,9 +445,6 @@ class LanguageServer extends Dispatcher
|
||||
|
||||
$serverCapabilities = new ServerCapabilities();
|
||||
|
||||
//The server provides execute command support.
|
||||
$serverCapabilities->executeCommandProvider = new ExecuteCommandOptions(['test']);
|
||||
|
||||
$textDocumentSyncOptions = new TextDocumentSyncOptions();
|
||||
|
||||
//Open and close notifications are sent to the server.
|
||||
|
||||
@@ -455,25 +455,6 @@ class TextDocument
|
||||
],
|
||||
]),
|
||||
);
|
||||
|
||||
/*
|
||||
$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)) {
|
||||
|
||||
@@ -11,7 +11,6 @@ use Psalm\Internal\Provider\ReturnTypeProvider\DateTimeModifyReturnTypeProvider;
|
||||
use Psalm\Internal\Provider\ReturnTypeProvider\DomNodeAppendChild;
|
||||
use Psalm\Internal\Provider\ReturnTypeProvider\ImagickPixelColorReturnTypeProvider;
|
||||
use Psalm\Internal\Provider\ReturnTypeProvider\PdoStatementReturnTypeProvider;
|
||||
use Psalm\Internal\Provider\ReturnTypeProvider\SimpleXmlElementAsXml;
|
||||
use Psalm\Plugin\EventHandler\Event\MethodReturnTypeProviderEvent;
|
||||
use Psalm\Plugin\EventHandler\MethodReturnTypeProviderInterface;
|
||||
use Psalm\StatementsSource;
|
||||
@@ -39,7 +38,6 @@ class MethodReturnTypeProvider
|
||||
|
||||
$this->registerClass(DomNodeAppendChild::class);
|
||||
$this->registerClass(ImagickPixelColorReturnTypeProvider::class);
|
||||
$this->registerClass(SimpleXmlElementAsXml::class);
|
||||
$this->registerClass(PdoStatementReturnTypeProvider::class);
|
||||
$this->registerClass(ClosureFromCallableReturnTypeProvider::class);
|
||||
$this->registerClass(DateTimeModifyReturnTypeProvider::class);
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\Provider\ReturnTypeProvider;
|
||||
|
||||
use Psalm\Plugin\EventHandler\Event\MethodReturnTypeProviderEvent;
|
||||
use Psalm\Plugin\EventHandler\MethodReturnTypeProviderInterface;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Union;
|
||||
|
||||
use function count;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class SimpleXmlElementAsXml implements MethodReturnTypeProviderInterface
|
||||
{
|
||||
public static function getClassLikeNames(): array
|
||||
{
|
||||
return ['SimpleXMLElement'];
|
||||
}
|
||||
|
||||
public static function getMethodReturnType(MethodReturnTypeProviderEvent $event): ?Union
|
||||
{
|
||||
$call_args = $event->getCallArgs();
|
||||
$method_name_lowercase = $event->getMethodNameLowercase();
|
||||
if ($method_name_lowercase === 'asxml'
|
||||
&& !count($call_args)
|
||||
) {
|
||||
return Type::parseString('string|false');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace Psalm\Internal\Provider\ReturnTypeProvider;
|
||||
|
||||
use ArgumentCountError;
|
||||
use Psalm\Issue\InvalidArgument;
|
||||
use Psalm\Issue\RedundantFunctionCall;
|
||||
use Psalm\Issue\TooFewArguments;
|
||||
use Psalm\Issue\TooManyArguments;
|
||||
use Psalm\IssueBuffer;
|
||||
@@ -25,6 +26,7 @@ use function count;
|
||||
use function is_string;
|
||||
use function preg_match;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -47,6 +49,11 @@ class SprintfReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
$statements_source = $event->getStatementsSource();
|
||||
$call_args = $event->getCallArgs();
|
||||
|
||||
// invalid - will already report an error for the params anyway
|
||||
if (count($call_args) < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$has_splat_args = false;
|
||||
$node_type_provider = $statements_source->getNodeTypeProvider();
|
||||
foreach ($call_args as $call_arg) {
|
||||
@@ -67,17 +74,29 @@ class SprintfReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
// eventually this could be refined
|
||||
// to check if it's an array with literal string as first element for further checking
|
||||
if (count($call_args) === 1 && $has_splat_args === true) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new RedundantFunctionCall(
|
||||
'Using the splat operator is redundant, as v' . $event->getFunctionId()
|
||||
. ' without splat operator can be used instead of ' . $event->getFunctionId(),
|
||||
$event->getCodeLocation(),
|
||||
),
|
||||
$statements_source->getSuppressedIssues(),
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// it makes no sense to use sprintf when there is only 1 arg (the format)
|
||||
// as it wouldn't have any placeholders
|
||||
if (count($call_args) === 1 && $event->getFunctionId() === 'sprintf') {
|
||||
// if it's a literal string, we can check it further though!
|
||||
$first_arg_type = $node_type_provider->getType($call_args[0]->value);
|
||||
if (count($call_args) === 1
|
||||
&& ($first_arg_type === null || !$first_arg_type->isSingleStringLiteral())) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new TooFewArguments(
|
||||
'Too few arguments for ' . $event->getFunctionId() . ', expecting at least 2 arguments',
|
||||
new RedundantFunctionCall(
|
||||
'Using ' . $event->getFunctionId()
|
||||
. ' with a single argument is redundant, since there are no placeholder params to be substituted',
|
||||
$event->getCodeLocation(),
|
||||
$event->getFunctionId(),
|
||||
),
|
||||
$statements_source->getSuppressedIssues(),
|
||||
);
|
||||
@@ -89,7 +108,10 @@ class SprintfReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
$is_falsable = true;
|
||||
foreach ($call_args as $index => $call_arg) {
|
||||
$type = $node_type_provider->getType($call_arg->value);
|
||||
|
||||
if ($type === null && $index === 0 && $event->getFunctionId() === 'printf') {
|
||||
// printf only has the format validated above
|
||||
// don't change the return type
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -100,10 +122,9 @@ class SprintfReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
if ($index === 0 && $type->isSingleStringLiteral()) {
|
||||
if ($type->getSingleStringLiteral()->value === '') {
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidArgument(
|
||||
'Argument 1 of ' . $event->getFunctionId() . ' must not be an empty string',
|
||||
new RedundantFunctionCall(
|
||||
'Calling ' . $event->getFunctionId() . ' with an empty first argument does nothing',
|
||||
$event->getCodeLocation(),
|
||||
$event->getFunctionId(),
|
||||
),
|
||||
$statements_source->getSuppressedIssues(),
|
||||
);
|
||||
@@ -158,17 +179,48 @@ class SprintfReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
$initial_result = $result;
|
||||
|
||||
if ($result === $type->getSingleStringLiteral()->value) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new InvalidArgument(
|
||||
'Argument 1 of ' . $event->getFunctionId()
|
||||
. ' does not contain any placeholders',
|
||||
$event->getCodeLocation(),
|
||||
$event->getFunctionId(),
|
||||
),
|
||||
$statements_source->getSuppressedIssues(),
|
||||
);
|
||||
if (count($call_args) > 1) {
|
||||
// we need to report this here too, since we return early without further validation
|
||||
// otherwise people who have suspended RedundantFunctionCall errors
|
||||
// will not get an error for this
|
||||
IssueBuffer::maybeAdd(
|
||||
new TooManyArguments(
|
||||
'Too many arguments for the number of placeholders in '
|
||||
. $event->getFunctionId(),
|
||||
$event->getCodeLocation(),
|
||||
$event->getFunctionId(),
|
||||
),
|
||||
$statements_source->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
// the same error as above, but we have validated the pattern now
|
||||
if (count($call_args) === 1) {
|
||||
IssueBuffer::maybeAdd(
|
||||
new RedundantFunctionCall(
|
||||
'Using ' . $event->getFunctionId()
|
||||
. ' with a single argument is redundant,'
|
||||
. ' since there are no placeholder params to be substituted',
|
||||
$event->getCodeLocation(),
|
||||
),
|
||||
$statements_source->getSuppressedIssues(),
|
||||
);
|
||||
} else {
|
||||
IssueBuffer::maybeAdd(
|
||||
new RedundantFunctionCall(
|
||||
'Argument 1 of ' . $event->getFunctionId()
|
||||
. ' does not contain any placeholders',
|
||||
$event->getCodeLocation(),
|
||||
),
|
||||
$statements_source->getSuppressedIssues(),
|
||||
);
|
||||
}
|
||||
|
||||
if ($event->getFunctionId() === 'printf') {
|
||||
return Type::getInt(false, strlen($type->getSingleStringLiteral()->value));
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
} catch (ValueError $value_error) {
|
||||
|
||||
2
vendor/vimeo/psalm/src/Psalm/Type/Atomic.php
vendored
2
vendor/vimeo/psalm/src/Psalm/Type/Atomic.php
vendored
@@ -323,7 +323,7 @@ abstract class Atomic implements TypeNode
|
||||
return $analysis_php_version_id !== null ? new TNamedObject($value) : new TScalar();
|
||||
|
||||
case 'null':
|
||||
if ($analysis_php_version_id === null || $analysis_php_version_id >= 8_00_00) {
|
||||
if ($analysis_php_version_id === null || $analysis_php_version_id >= 7_00_00) {
|
||||
return new TNull();
|
||||
}
|
||||
|
||||
|
||||
@@ -424,6 +424,10 @@ class Reconciler
|
||||
{
|
||||
foreach ($new_types as $nk => $type) {
|
||||
if (strpos($nk, '[') || strpos($nk, '->')) {
|
||||
$type = array_values($type);
|
||||
if (!isset($type[0][0])) {
|
||||
continue;
|
||||
}
|
||||
if ($type[0][0] instanceof IsEqualIsset
|
||||
|| $type[0][0] instanceof IsIsset
|
||||
|| $type[0][0] instanceof NonEmpty
|
||||
|
||||
@@ -1359,9 +1359,10 @@ function realpath(string $path) {}
|
||||
*
|
||||
* @param numeric-string $num1
|
||||
* @param numeric-string $num2
|
||||
* @param int|null $scale
|
||||
* @return (PHP_MAJOR_VERSION is 8 ? numeric-string : ($num2 is "0" ? null : numeric-string))
|
||||
*/
|
||||
function bcdiv(string $num1, string $num2, int $scale = 0): ?string {}
|
||||
function bcdiv(string $num1, string $num2, ?int $scale = null): ?string {}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
|
||||
11
vendor/vimeo/psalm/stubs/Php74.phpstub
vendored
Normal file
11
vendor/vimeo/psalm/stubs/Php74.phpstub
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*
|
||||
* @psalm-taint-escape html
|
||||
* @psalm-flow ($string) -> return
|
||||
*
|
||||
* @param null|string|array<array-key,string> $allowed_tags
|
||||
*/
|
||||
function strip_tags(string $string, null|string|array $allowed_tags = null) : string {}
|
||||
@@ -471,13 +471,13 @@ class DOMDocument extends DOMNode implements DOMParentNode
|
||||
public function importNode(DOMNode $node, bool $deep = false) {}
|
||||
|
||||
/**
|
||||
* @return DOMDocument|false
|
||||
* @return bool
|
||||
* @psalm-ignore-falsable-return
|
||||
**/
|
||||
public function load(string $filename, int $options = 0) {}
|
||||
|
||||
/**
|
||||
* @return DOMDocument|false
|
||||
* @return bool
|
||||
* @psalm-ignore-falsable-return
|
||||
*/
|
||||
public function loadXML(string $source, int $options = 0) {}
|
||||
@@ -492,10 +492,10 @@ class DOMDocument extends DOMNode implements DOMParentNode
|
||||
*/
|
||||
public function save(string $filename, int $options = 0) {}
|
||||
|
||||
/** @return DOMDocument|bool */
|
||||
/** @return bool */
|
||||
public function loadHTML(string $source, int $options = 0) {}
|
||||
|
||||
/** @return DOMDocument|bool */
|
||||
/** @return bool */
|
||||
public function loadHTMLFile(string $filename, int $options = 0) {}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,6 +25,7 @@ function simplexml_import_dom(SimpleXMLElement|DOMNode $node, ?string $class_nam
|
||||
|
||||
/**
|
||||
* @implements Traversable<string, SimpleXMLElement>
|
||||
* @psalm-no-seal-properties
|
||||
*/
|
||||
class SimpleXMLElement implements Traversable, Countable
|
||||
{
|
||||
@@ -63,6 +64,8 @@ class SimpleXMLElement implements Traversable, Countable
|
||||
public function __toString(): string {}
|
||||
|
||||
public function count(): int {}
|
||||
|
||||
public function __get(string $name): SimpleXMLElement|SimpleXMLIterator|null {}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user