Merge branch 'feature/phpstan-2.0.x' into 'master'
PHPStan 2.0.x See merge request tt-rss/tt-rss!74
This commit is contained in:
@@ -235,7 +235,7 @@ class API extends Handler {
|
||||
}
|
||||
|
||||
function updateArticle(): bool {
|
||||
$article_ids = explode(",", clean($_REQUEST["article_ids"]));
|
||||
$article_ids = array_filter(explode(",", clean($_REQUEST["article_ids"] ?? "")));
|
||||
$mode = (int) clean($_REQUEST["mode"]);
|
||||
$data = clean($_REQUEST["data"] ?? "");
|
||||
$field_raw = (int)clean($_REQUEST["field"]);
|
||||
@@ -300,10 +300,9 @@ class API extends Handler {
|
||||
}
|
||||
|
||||
function getArticle(): bool {
|
||||
$article_ids = explode(',', clean($_REQUEST['article_id'] ?? ''));
|
||||
$article_ids = array_filter(explode(',', clean($_REQUEST['article_id'] ?? '')));
|
||||
$sanitize_content = self::_param_to_bool($_REQUEST['sanitize'] ?? true);
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
if (count($article_ids)) {
|
||||
$entries = ORM::for_table('ttrss_entries')
|
||||
->table_alias('e')
|
||||
@@ -550,26 +549,22 @@ class API extends Handler {
|
||||
|
||||
/* Virtual feeds */
|
||||
|
||||
$vfeeds = PluginHost::getInstance()->get_feeds(Feeds::CATEGORY_SPECIAL);
|
||||
foreach (PluginHost::getInstance()->get_feeds(Feeds::CATEGORY_SPECIAL) as $feed) {
|
||||
if (!implements_interface($feed['sender'], 'IVirtualFeed'))
|
||||
continue;
|
||||
|
||||
if (is_array($vfeeds)) {
|
||||
foreach ($vfeeds as $feed) {
|
||||
if (!implements_interface($feed['sender'], 'IVirtualFeed'))
|
||||
continue;
|
||||
/** @var IVirtualFeed $feed['sender'] */
|
||||
$unread = $feed['sender']->get_unread($feed['id']);
|
||||
|
||||
/** @var IVirtualFeed $feed['sender'] */
|
||||
$unread = $feed['sender']->get_unread($feed['id']);
|
||||
if ($unread || !$unread_only) {
|
||||
$row = [
|
||||
'id' => PluginHost::pfeed_to_feed_id($feed['id']),
|
||||
'title' => $feed['title'],
|
||||
'unread' => $unread,
|
||||
'cat_id' => Feeds::CATEGORY_SPECIAL,
|
||||
];
|
||||
|
||||
if ($unread || !$unread_only) {
|
||||
$row = [
|
||||
'id' => PluginHost::pfeed_to_feed_id($feed['id']),
|
||||
'title' => $feed['title'],
|
||||
'unread' => $unread,
|
||||
'cat_id' => Feeds::CATEGORY_SPECIAL,
|
||||
];
|
||||
|
||||
array_push($feeds, $row);
|
||||
}
|
||||
array_push($feeds, $row);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,7 +691,6 @@ class API extends Handler {
|
||||
if (!$is_cat && is_numeric($feed_id) && $feed_id < PLUGIN_FEED_BASE_INDEX && $feed_id > LABEL_BASE_INDEX) {
|
||||
$pfeed_id = PluginHost::feed_to_pfeed_id($feed_id);
|
||||
|
||||
/** @var IVirtualFeed|false $handler */
|
||||
$handler = PluginHost::getInstance()->get_feed_handler($pfeed_id);
|
||||
|
||||
if ($handler) {
|
||||
@@ -858,7 +852,7 @@ class API extends Handler {
|
||||
|
||||
array_push($headlines, $headline_row);
|
||||
}
|
||||
} else if (is_numeric($result) && $result == -1) {
|
||||
} else if ($result == -1) {
|
||||
$headlines_header['first_id_changed'] = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -264,25 +264,21 @@ class Counters {
|
||||
array_push($ret, $cv);
|
||||
}
|
||||
|
||||
$feeds = PluginHost::getInstance()->get_feeds(Feeds::CATEGORY_SPECIAL);
|
||||
foreach (PluginHost::getInstance()->get_feeds(Feeds::CATEGORY_SPECIAL) as $feed) {
|
||||
if (!implements_interface($feed['sender'], 'IVirtualFeed'))
|
||||
continue;
|
||||
|
||||
if (is_array($feeds)) {
|
||||
foreach ($feeds as $feed) {
|
||||
/** @var IVirtualFeed $feed['sender'] */
|
||||
/** @var Plugin&IVirtualFeed $feed['sender'] */
|
||||
|
||||
if (!implements_interface($feed['sender'], 'IVirtualFeed'))
|
||||
continue;
|
||||
$cv = [
|
||||
"id" => PluginHost::pfeed_to_feed_id($feed['id']),
|
||||
"counter" => $feed['sender']->get_unread($feed['id'])
|
||||
];
|
||||
|
||||
$cv = [
|
||||
"id" => PluginHost::pfeed_to_feed_id($feed['id']),
|
||||
"counter" => $feed['sender']->get_unread($feed['id'])
|
||||
];
|
||||
if (method_exists($feed['sender'], 'get_total'))
|
||||
$cv["auxcounter"] = $feed['sender']->get_total($feed['id']);
|
||||
|
||||
if (method_exists($feed['sender'], 'get_total'))
|
||||
$cv["auxcounter"] = $feed['sender']->get_total($feed['id']);
|
||||
|
||||
array_push($ret, $cv);
|
||||
}
|
||||
array_push($ret, $cv);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
@@ -77,7 +77,7 @@ class Debug {
|
||||
*/
|
||||
public static function map_loglevel(int $level) : int {
|
||||
if (in_array($level, self::ALL_LOG_LEVELS)) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
/** @phpstan-ignore return.type (yes it is a Debug::LOG_* value) */
|
||||
return $level;
|
||||
} else {
|
||||
user_error("Passed invalid debug log level: $level", E_USER_WARNING);
|
||||
|
||||
@@ -163,7 +163,7 @@ class Digest
|
||||
$article_labels = Article::_get_labels($line["ref_id"], $user_id);
|
||||
$article_labels_formatted = "";
|
||||
|
||||
if (is_array($article_labels) && count($article_labels) > 0) {
|
||||
if (count($article_labels) > 0) {
|
||||
$article_labels_formatted = implode(", ", array_map(fn($a) => $a[1], $article_labels));
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||
$links = $this->elem->getElementsByTagName("link");
|
||||
|
||||
foreach ($links as $link) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
if ($link->hasAttribute("href") &&
|
||||
(!$link->hasAttribute("rel")
|
||||
|| $link->getAttribute("rel") == "alternate"
|
||||
@@ -181,7 +180,6 @@ class FeedItem_Atom extends FeedItem_Common {
|
||||
$encs = [];
|
||||
|
||||
foreach ($links as $link) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
if ($link->hasAttribute("href") && $link->hasAttribute("rel")) {
|
||||
$base = $this->xpath->evaluate("string(ancestor-or-self::*[@xml:base][1]/@xml:base)", $link);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class FeedItem_RSS extends FeedItem_Common {
|
||||
$links = $this->xpath->query("atom:link", $this->elem);
|
||||
|
||||
foreach ($links as $link) {
|
||||
if ($link && $link->hasAttribute("href") &&
|
||||
if ($link->hasAttribute("href") &&
|
||||
(!$link->hasAttribute("rel")
|
||||
|| $link->getAttribute("rel") == "alternate"
|
||||
|| $link->getAttribute("rel") == "standout")) {
|
||||
|
||||
@@ -103,8 +103,6 @@ class Feeds extends Handler_Protected {
|
||||
$qfh_ret = [];
|
||||
|
||||
if (!$cat_view && is_numeric($feed) && $feed < PLUGIN_FEED_BASE_INDEX && $feed > LABEL_BASE_INDEX) {
|
||||
|
||||
/** @var IVirtualFeed|false $handler */
|
||||
$handler = PluginHost::getInstance()->get_feed_handler(
|
||||
PluginHost::feed_to_pfeed_id($feed));
|
||||
|
||||
@@ -246,7 +244,7 @@ class Feeds extends Handler_Protected {
|
||||
$label_cache = json_decode($label_cache, true);
|
||||
|
||||
if ($label_cache) {
|
||||
if ($label_cache["no-labels"] ?? 0 == 1)
|
||||
if (($label_cache["no-labels"] ?? 0) == 1)
|
||||
$labels = [];
|
||||
else
|
||||
$labels = $label_cache;
|
||||
@@ -936,15 +934,10 @@ class Feeds extends Handler_Protected {
|
||||
|
||||
if ($is_cat) {
|
||||
return self::_get_cat_unread($n_feed, $owner_uid);
|
||||
} else if(is_numeric($feed) && $feed < PLUGIN_FEED_BASE_INDEX && $feed > LABEL_BASE_INDEX) { // virtual Feed
|
||||
} else if (is_numeric($feed) && $feed < PLUGIN_FEED_BASE_INDEX && $feed > LABEL_BASE_INDEX) { // virtual Feed
|
||||
$feed_id = PluginHost::feed_to_pfeed_id($feed);
|
||||
$handler = PluginHost::getInstance()->get_feed_handler($feed_id);
|
||||
if (implements_interface($handler, 'IVirtualFeed')) {
|
||||
/** @var IVirtualFeed $handler */
|
||||
return $handler->get_unread($feed_id);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return $handler ? $handler->get_unread($feed_id) : 0;
|
||||
} else if ($n_feed == Feeds::FEED_RECENTLY_READ) {
|
||||
return 0;
|
||||
// tags
|
||||
@@ -1067,7 +1060,7 @@ class Feeds extends Handler_Protected {
|
||||
if (!$url) return ["code" => 2];
|
||||
|
||||
PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_PRE_SUBSCRIBE,
|
||||
/** @phpstan-ignore-next-line */
|
||||
/** @phpstan-ignore closure.unusedUse, closure.unusedUse, closure.unusedUse */
|
||||
function ($result) use (&$url, &$auth_login, &$auth_pass) {
|
||||
// arguments are updated inside the hook (if needed)
|
||||
},
|
||||
|
||||
@@ -54,8 +54,6 @@ class Handler_Public extends Handler {
|
||||
PluginHost::feed_to_pfeed_id((int)$feed));
|
||||
|
||||
if ($handler) {
|
||||
// 'get_headlines' is implemented by the plugin.
|
||||
// @phpstan-ignore-next-line
|
||||
$qfh_ret = $handler->get_headlines(PluginHost::feed_to_pfeed_id((int)$feed), $params);
|
||||
} else {
|
||||
user_error("Failed to find handler for plugin feed ID: $feed", E_USER_ERROR);
|
||||
|
||||
@@ -76,7 +76,7 @@ abstract class Plugin {
|
||||
*
|
||||
* @return string */
|
||||
function __($msgid) {
|
||||
/** @var Plugin $this -- this is a strictly template-related hack */
|
||||
// this is a strictly template-related hack
|
||||
return _dgettext(PluginHost::object_to_domain($this), $msgid);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ abstract class Plugin {
|
||||
*
|
||||
* @return string */
|
||||
function _ngettext($singular, $plural, $number) {
|
||||
/** @var Plugin $this -- this is a strictly template-related hack */
|
||||
// this is a strictly template-related hack
|
||||
return _dngettext(PluginHost::object_to_domain($this), $singular, $plural, $number);
|
||||
}
|
||||
|
||||
|
||||
@@ -386,7 +386,7 @@ class PluginHost {
|
||||
* @param PluginHost::HOOK_* $type
|
||||
*/
|
||||
function del_hook(string $type, Plugin $sender): void {
|
||||
if (is_array($this->hooks[$type])) {
|
||||
if (array_key_exists($type, $this->hooks)) {
|
||||
foreach (array_keys($this->hooks[$type]) as $prio) {
|
||||
$key = array_search($sender, $this->hooks[$type][$prio]);
|
||||
|
||||
@@ -589,7 +589,7 @@ class PluginHost {
|
||||
}
|
||||
}
|
||||
|
||||
/** @return array<string, array{'description': string, 'suffix': string, 'arghelp': string, 'class': Plugin}>> command type -> details array */
|
||||
/** @return array<string, array{'description': string, 'suffix': string, 'arghelp': string, 'class': Plugin}> command type -> details array */
|
||||
function get_commands() {
|
||||
return $this->commands;
|
||||
}
|
||||
@@ -782,12 +782,21 @@ class PluginHost {
|
||||
return $this->feeds[$cat_id] ?? [];
|
||||
}
|
||||
|
||||
// convert feed_id (e.g. -129) to pfeed_id first
|
||||
/**
|
||||
* convert feed_id (e.g. -129) to pfeed_id first
|
||||
*
|
||||
* @return (Plugin&IVirtualFeed)|null
|
||||
*/
|
||||
function get_feed_handler(int $pfeed_id): ?Plugin {
|
||||
foreach ($this->feeds as $cat) {
|
||||
foreach ($cat as $feed) {
|
||||
if ($feed['id'] == $pfeed_id) {
|
||||
return $feed['sender'];
|
||||
if (implements_interface($feed['sender'], 'IVirtualFeed')) {
|
||||
/** @var Plugin&IVirtualFeed $feed['sender'] */
|
||||
return $feed['sender'];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,8 +240,7 @@ class Pref_Feeds extends Handler_Protected {
|
||||
/**
|
||||
* Uncategorized is a special case.
|
||||
*
|
||||
* Define a minimal array shape to help PHPStan with the type of $cat['items']
|
||||
* @var array{items: array<int, array<string, mixed>>} $cat
|
||||
* @var array{id: string, bare_id: int, auxcounter: int, name: string, items: array<int, array<string, mixed>>, type: 'category', checkbox: bool, unread: int, child_unread: int}
|
||||
*/
|
||||
$cat = [
|
||||
'id' => 'CAT:0',
|
||||
|
||||
@@ -115,9 +115,6 @@ class Pref_Filters extends Handler_Protected {
|
||||
$glue = $filter['match_any_rule'] ? " OR " : " AND ";
|
||||
$scope_qpart = join($glue, $scope_qparts);
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
if (!$scope_qpart) $scope_qpart = "true";
|
||||
|
||||
$rv = array();
|
||||
|
||||
//while ($found < $limit && $offset < $limit * 1000 && time() - $started < ini_get("max_execution_time") * 0.7) {
|
||||
@@ -714,7 +711,6 @@ class Pref_Filters extends Handler_Protected {
|
||||
}
|
||||
|
||||
function editrule(): void {
|
||||
/** @var array<int, int|string> */
|
||||
$feed_ids = explode(",", clean($_REQUEST["ids"]));
|
||||
|
||||
print json_encode([
|
||||
|
||||
@@ -177,7 +177,7 @@ class Pref_Prefs extends Handler_Protected {
|
||||
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
|
||||
|
||||
if (implements_interface($authenticator, "IAuthModule2")) {
|
||||
/** @var IAuthModule2 $authenticator */
|
||||
/** @var Plugin&IAuthModule2 $authenticator */
|
||||
print format_notice($authenticator->change_password($_SESSION["uid"], $old_pw, $new_pw));
|
||||
} else {
|
||||
print "ERROR: ".format_error("Function not supported by authentication module.");
|
||||
@@ -976,7 +976,7 @@ class Pref_Prefs extends Handler_Protected {
|
||||
|
||||
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
|
||||
|
||||
/** @var Auth_Internal|false $authenticator -- this is only here to make check_password() visible to static analyzer */
|
||||
/** @var Auth_Internal|null $authenticator -- this is only here to make check_password() visible to static analyzer */
|
||||
if ($authenticator->check_password($_SESSION["uid"], $password)) {
|
||||
if (UserHelper::enable_otp($_SESSION["uid"], $otp_check)) {
|
||||
print "OK";
|
||||
@@ -991,7 +991,7 @@ class Pref_Prefs extends Handler_Protected {
|
||||
function otpdisable(): void {
|
||||
$password = clean($_REQUEST["password"]);
|
||||
|
||||
/** @var Auth_Internal|false $authenticator -- this is only here to make check_password() visible to static analyzer */
|
||||
/** @var Auth_Internal|null $authenticator -- this is only here to make check_password() visible to static analyzer */
|
||||
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
|
||||
|
||||
if ($authenticator->check_password($_SESSION["uid"], $password)) {
|
||||
@@ -1316,14 +1316,8 @@ class Pref_Prefs extends Handler_Protected {
|
||||
|
||||
function updateLocalPlugins(): void {
|
||||
if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN) {
|
||||
$plugins = explode(",", $_REQUEST["plugins"] ?? "");
|
||||
|
||||
if ($plugins !== false) {
|
||||
$plugins = array_filter($plugins, 'strlen');
|
||||
}
|
||||
|
||||
$plugins = array_filter(explode(",", $_REQUEST["plugins"] ?? ""), "strlen");
|
||||
$root_dir = Config::get_self_dir();
|
||||
|
||||
$rv = [];
|
||||
|
||||
if ($plugins) {
|
||||
|
||||
@@ -50,7 +50,7 @@ class UserHelper {
|
||||
*/
|
||||
public static function map_access_level(int $level) : int {
|
||||
if (in_array($level, self::ACCESS_LEVELS)) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
/** @phpstan-ignore return.type (yes it is a UserHelper::ACCESS_LEVEL_* value) */
|
||||
return $level;
|
||||
} else {
|
||||
user_error("Passed invalid user access level: $level", E_USER_WARNING);
|
||||
@@ -503,7 +503,6 @@ class UserHelper {
|
||||
|
||||
return $authenticator->check_password($owner_uid, $password);
|
||||
} else {
|
||||
/** @var Auth_Internal|false $authenticator -- this is only here to make check_password() visible to static analyzer */
|
||||
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
|
||||
|
||||
if ($authenticator &&
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"guzzlehttp/guzzle": "^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "1.10.3",
|
||||
"phpstan/phpstan": "2.0.1",
|
||||
"phpunit/phpunit": "9.5.16",
|
||||
"phpunit/php-code-coverage": "^9.2"
|
||||
}
|
||||
|
||||
23
composer.lock
generated
23
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "478a27f2e837c92757db206b443c67a4",
|
||||
"content-hash": "f071cb2cab2cf7d4ef32c4eb7655e350",
|
||||
"packages": [
|
||||
{
|
||||
"name": "beberlei/assert",
|
||||
@@ -1781,20 +1781,20 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.10.3",
|
||||
"version": "2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "5419375b5891add97dc74be71e6c1c34baaddf64"
|
||||
"reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/5419375b5891add97dc74be71e6c1c34baaddf64",
|
||||
"reference": "5419375b5891add97dc74be71e6c1c34baaddf64",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d",
|
||||
"reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8.0"
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
@@ -1819,8 +1819,11 @@
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://phpstan.org/user-guide/getting-started",
|
||||
"forum": "https://github.com/phpstan/phpstan/discussions",
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.10.3"
|
||||
"security": "https://github.com/phpstan/phpstan/security/policy",
|
||||
"source": "https://github.com/phpstan/phpstan-src"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1830,13 +1833,9 @@
|
||||
{
|
||||
"url": "https://github.com/phpstan",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-02-25T14:47:13+00:00"
|
||||
"time": "2024-11-11T15:43:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
||||
@@ -2,40 +2,38 @@
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $trace
|
||||
*/
|
||||
function format_backtrace($trace): string {
|
||||
function format_backtrace(array $trace): string {
|
||||
$rv = "";
|
||||
$idx = 1;
|
||||
|
||||
if (is_array($trace)) {
|
||||
foreach ($trace as $e) {
|
||||
if (isset($e["file"]) && isset($e["line"])) {
|
||||
$fmt_args = [];
|
||||
foreach ($trace as $e) {
|
||||
if (isset($e["file"]) && isset($e["line"])) {
|
||||
$fmt_args = [];
|
||||
|
||||
if (is_array($e["args"] ?? false)) {
|
||||
foreach ($e["args"] as $a) {
|
||||
if (is_object($a)) {
|
||||
array_push($fmt_args, "{" . get_class($a) . "}");
|
||||
} else if (is_array($a)) {
|
||||
array_push($fmt_args, "[" . truncate_string(json_encode($a), 256, "...")) . "]";
|
||||
} else if (is_resource($a)) {
|
||||
array_push($fmt_args, truncate_string(get_resource_type($a), 256, "..."));
|
||||
} else if (is_string($a)) {
|
||||
array_push($fmt_args, truncate_string($a, 256, "..."));
|
||||
}
|
||||
if (is_array($e["args"] ?? false)) {
|
||||
foreach ($e["args"] as $a) {
|
||||
if (is_object($a)) {
|
||||
array_push($fmt_args, "{" . get_class($a) . "}");
|
||||
} else if (is_array($a)) {
|
||||
array_push($fmt_args, "[" . truncate_string(json_encode($a), 256, "...")) . "]";
|
||||
} else if (is_resource($a)) {
|
||||
array_push($fmt_args, truncate_string(get_resource_type($a), 256, "..."));
|
||||
} else if (is_string($a)) {
|
||||
array_push($fmt_args, truncate_string($a, 256, "..."));
|
||||
}
|
||||
}
|
||||
|
||||
$filename = str_replace(dirname(__DIR__) . "/", "", $e["file"]);
|
||||
|
||||
$rv .= sprintf("%d. %s(%s): %s(%s)\n",
|
||||
$idx,
|
||||
$filename,
|
||||
$e["line"],
|
||||
$e["function"],
|
||||
implode(", ", $fmt_args));
|
||||
|
||||
$idx++;
|
||||
}
|
||||
|
||||
$filename = str_replace(dirname(__DIR__) . "/", "", $e["file"]);
|
||||
|
||||
$rv .= sprintf("%d. %s(%s): %s(%s)\n",
|
||||
$idx,
|
||||
$filename,
|
||||
$e["line"],
|
||||
$e["function"],
|
||||
implode(", ", $fmt_args));
|
||||
|
||||
$idx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
// create a list like "en" => 0.8
|
||||
$langs = array_combine($lang_parse[1], $lang_parse[4]);
|
||||
|
||||
/** @phpstan-ignore function.alreadyNarrowedType (PHP 7.4 will return false if array_value has an issue) */
|
||||
if (is_array($langs)) {
|
||||
// set default to 1 for any without q factor
|
||||
foreach ($langs as $lang => $val) {
|
||||
|
||||
@@ -39,16 +39,14 @@
|
||||
|
||||
<?php
|
||||
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
|
||||
if (method_exists($p, "get_login_js")) {
|
||||
$script = $p->get_login_js();
|
||||
$script = $p->get_login_js();
|
||||
|
||||
if ($script) {
|
||||
echo "try {
|
||||
$script
|
||||
} catch (e) {
|
||||
console.warn('failed to initialize plugin JS: $n', e);
|
||||
}";
|
||||
}
|
||||
if ($script) {
|
||||
echo "try {
|
||||
$script
|
||||
} catch (e) {
|
||||
console.warn('failed to initialize plugin JS: $n', e);
|
||||
}";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
21
index.php
21
index.php
@@ -36,8 +36,9 @@
|
||||
<style type="text/css">
|
||||
<?php
|
||||
foreach (PluginHost::getInstance()->get_plugins() as $p) {
|
||||
if (method_exists($p, "get_css")) {
|
||||
echo $p->get_css();
|
||||
$css = $p->get_css();
|
||||
if ($css) {
|
||||
echo $css;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -73,16 +74,14 @@
|
||||
<script type="text/javascript">
|
||||
<?php
|
||||
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
|
||||
if (method_exists($p, "get_js")) {
|
||||
$script = $p->get_js();
|
||||
$script = $p->get_js();
|
||||
|
||||
if ($script) {
|
||||
echo "try {
|
||||
$script
|
||||
} catch (e) {
|
||||
console.warn('failed to initialize plugin JS: $n', e);
|
||||
}";
|
||||
}
|
||||
if ($script) {
|
||||
echo "try {
|
||||
$script
|
||||
} catch (e) {
|
||||
console.warn('failed to initialize plugin JS: $n', e);
|
||||
}";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
14
phpstan.neon
14
phpstan.neon
@@ -5,8 +5,18 @@ parameters:
|
||||
maximumNumberOfProcesses: 4
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
ignoreErrors:
|
||||
- '#Constant.*\b(SUBSTRING_FOR_DATE|SCHEMA_VERSION|SELF_USER_AGENT|LABEL_BASE_INDEX|PLUGIN_FEED_BASE_INDEX)\b.*not found#'
|
||||
- '#Comparison operation ">" between int<1, max> and 0 is always true.#'
|
||||
# set_include_path detection issue
|
||||
- message: '#"(autoload|colors|config|errorhandler|login_form|sessions)\.php"#'
|
||||
identifier: requireOnce.fileNotFound
|
||||
|
||||
# undetected as DOMElement
|
||||
- '#Call to an undefined method DOMNode::#'
|
||||
- '#Access to an undefined property DOMNode::#'
|
||||
- '#expects DOMElement, DOMNode given#'
|
||||
|
||||
# allow passing a 'strlen' string, etc. as the array_filter callback
|
||||
- "/Parameter #2 \\$callback of function array_filter expects .+ '.+' given/"
|
||||
|
||||
- message: '##'
|
||||
paths:
|
||||
- lib/*
|
||||
|
||||
16
prefs.php
16
prefs.php
@@ -64,16 +64,14 @@
|
||||
<script type="text/javascript">
|
||||
<?php
|
||||
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
|
||||
if (method_exists($p, "get_prefs_js")) {
|
||||
$script = $p->get_prefs_js();
|
||||
$script = $p->get_prefs_js();
|
||||
|
||||
if ($script) {
|
||||
echo "try {
|
||||
$script
|
||||
} catch (e) {
|
||||
console.warn('failed to initialize plugin JS: $n', e);
|
||||
}";
|
||||
}
|
||||
if ($script) {
|
||||
echo "try {
|
||||
$script
|
||||
} catch (e) {
|
||||
console.warn('failed to initialize plugin JS: $n', e);
|
||||
}";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
}
|
||||
|
||||
if (isset($options["daemon"])) {
|
||||
// @phpstan-ignore-next-line
|
||||
// @phpstan-ignore while.alwaysTrue (single process daemon will always run)
|
||||
while (true) {
|
||||
$quiet = (isset($options["quiet"])) ? "--quiet" : "";
|
||||
$log = isset($options['log']) ? '--log '.$options['log'] : '';
|
||||
|
||||
5
vendor/bin/phpstan
vendored
Normal file → Executable file
5
vendor/bin/phpstan
vendored
Normal file → Executable file
@@ -112,9 +112,8 @@ if (PHP_VERSION_ID < 80000) {
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan');
|
||||
exit(0);
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan');
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/phpstan/phpstan/phpstan';
|
||||
return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan';
|
||||
|
||||
5
vendor/bin/phpstan.phar
vendored
Normal file → Executable file
5
vendor/bin/phpstan.phar
vendored
Normal file → Executable file
@@ -112,9 +112,8 @@ if (PHP_VERSION_ID < 80000) {
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar');
|
||||
exit(0);
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar');
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar';
|
||||
return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar';
|
||||
|
||||
2
vendor/composer/autoload_psr4.php
vendored
2
vendor/composer/autoload_psr4.php
vendored
@@ -11,7 +11,7 @@ return array(
|
||||
'chillerlan\\QRCode\\' => array($vendorDir . '/chillerlan/php-qrcode/src'),
|
||||
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
|
||||
'Soundasleep\\' => array($vendorDir . '/soundasleep/html2text/src'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
|
||||
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
||||
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src/Prophecy'),
|
||||
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
|
||||
|
||||
4
vendor/composer/autoload_static.php
vendored
4
vendor/composer/autoload_static.php
vendored
@@ -176,8 +176,8 @@ class ComposerStaticInit19fc2ff1c0f9a92279c7979386bb2056
|
||||
),
|
||||
'Psr\\Http\\Message\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||
1 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||
),
|
||||
'Psr\\Http\\Client\\' =>
|
||||
array (
|
||||
|
||||
23
vendor/composer/installed.json
vendored
23
vendor/composer/installed.json
vendored
@@ -1288,26 +1288,26 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.10.3",
|
||||
"version_normalized": "1.10.3.0",
|
||||
"version": "2.0.1",
|
||||
"version_normalized": "2.0.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "5419375b5891add97dc74be71e6c1c34baaddf64"
|
||||
"reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/5419375b5891add97dc74be71e6c1c34baaddf64",
|
||||
"reference": "5419375b5891add97dc74be71e6c1c34baaddf64",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d",
|
||||
"reference": "ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8.0"
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
},
|
||||
"time": "2023-02-25T14:47:13+00:00",
|
||||
"time": "2024-11-11T15:43:04+00:00",
|
||||
"bin": [
|
||||
"phpstan",
|
||||
"phpstan.phar"
|
||||
@@ -1329,8 +1329,11 @@
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://phpstan.org/user-guide/getting-started",
|
||||
"forum": "https://github.com/phpstan/phpstan/discussions",
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"source": "https://github.com/phpstan/phpstan/tree/1.10.3"
|
||||
"security": "https://github.com/phpstan/phpstan/security/policy",
|
||||
"source": "https://github.com/phpstan/phpstan-src"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1340,10 +1343,6 @@
|
||||
{
|
||||
"url": "https://github.com/phpstan",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../phpstan/phpstan"
|
||||
|
||||
10
vendor/composer/installed.php
vendored
10
vendor/composer/installed.php
vendored
@@ -3,7 +3,7 @@
|
||||
'name' => '__root__',
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => 'df489df309dc831b357a9cc36fe72ad5a99d22e0',
|
||||
'reference' => '6273e26ea463e2762f2d736455f4912de7171cfa',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -13,7 +13,7 @@
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => 'df489df309dc831b357a9cc36fe72ad5a99d22e0',
|
||||
'reference' => '6273e26ea463e2762f2d736455f4912de7171cfa',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -184,9 +184,9 @@
|
||||
'dev_requirement' => true,
|
||||
),
|
||||
'phpstan/phpstan' => array(
|
||||
'pretty_version' => '1.10.3',
|
||||
'version' => '1.10.3.0',
|
||||
'reference' => '5419375b5891add97dc74be71e6c1c34baaddf64',
|
||||
'pretty_version' => '2.0.1',
|
||||
'version' => '2.0.1.0',
|
||||
'reference' => 'ab4e9b4415a5fc9e4d27f7fe16c8bc9d067dcd6d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../phpstan/phpstan',
|
||||
'aliases' => array(),
|
||||
|
||||
46
vendor/phpstan/phpstan/README.md
vendored
46
vendor/phpstan/phpstan/README.md
vendored
@@ -24,50 +24,56 @@ can be checked before you run the actual line.
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://coders.thecodingmachine.com/phpstan"><img src="https://i.imgur.com/kQhNOTP.png" alt="TheCodingMachine" width="247" height="64"></a>
|
||||
<a href="https://coders.thecodingmachine.com/phpstan"><img src="website/src/images/sponsor/tcm.png" alt="TheCodingMachine" width="247" height="64"></a>
|
||||
|
||||
<a href="https://packagist.com/?utm_source=phpstan&utm_medium=readme&utm_campaign=sponsorlogo"><img src="https://i.imgur.com/B2T63Do.png" alt="Private Packagist" width="283" height="64"></a>
|
||||
<a href="https://packagist.com/?utm_source=phpstan&utm_medium=readme&utm_campaign=sponsorlogo"><img src="website/src/images/sponsor/packagist.png" alt="Private Packagist" width="283" height="64"></a>
|
||||
<br>
|
||||
<a href="https://careers.tuigroup.com/jobs/"><img src="https://i.imgur.com/uw5rAlR.png" alt="Musement" width="247" height="49"></a>
|
||||
<a href="https://www.cdn77.com/"><img src="website/src/images/sponsor/cdn77.png" alt="CDN77" width="283" height="64"></a>
|
||||
|
||||
<a href="https://blackfire.io/docs/introduction?utm_source=phpstan&utm_medium=github_readme&utm_campaign=logo"><img src="https://i.imgur.com/zR8rsqk.png" alt="Blackfire.io" width="254" height="64"></a>
|
||||
<a href="https://blackfire.io/docs/introduction?utm_source=phpstan&utm_medium=github_readme&utm_campaign=logo"><img src="website/src/images/sponsor/blackfire.png" alt="Blackfire.io" width="254" height="64"></a>
|
||||
<br>
|
||||
<a href="https://www.iodigital.com/"><img src="https://i.imgur.com/fJlw1n9.png" alt="iO" width="254" height="65"></a>
|
||||
<a href="https://www.iodigital.com/"><img src="website/src/images/sponsor/io.png" alt="iO" width="254" height="65"></a>
|
||||
|
||||
<a href="https://jobs.ticketswap.com/"><img src="https://i.imgur.com/lhzcutK.png" alt="TicketSwap" width="269" height="64"></a>
|
||||
<a href="https://www.fame.fi/"><img src="website/src/images/sponsor/fame.png" alt="Fame Helsinki" width="283" height="64"></a>
|
||||
<br>
|
||||
<a href="https://www.startupjobs.cz/startup/shipmonk"><img src="https://i.imgur.com/bAC47za.jpg" alt="ShipMonk" width="290" height="64"></a>
|
||||
<a href="https://www.startupjobs.cz/startup/shipmonk"><img src="website/src/images/sponsor/shipmonk.jpg" alt="ShipMonk" width="290" height="64"></a>
|
||||
|
||||
<a href="https://togetter.com/"><img src="https://i.imgur.com/x9n5cj3.png" alt="Togetter" width="283" height="64"></a>
|
||||
<a href="https://togetter.com/"><img src="website/src/images/sponsor/togetter.png" alt="Togetter" width="283" height="64"></a>
|
||||
<br>
|
||||
<a href="https://join.rightcapital.com/?utm_source=phpstan&utm_medium=github&utm_campaign=sponsorship"><img src="https://i.imgur.com/1AhB5tW.png" alt="RightCapital" width="283" height="64"></a>
|
||||
<a href="https://join.rightcapital.com/?utm_source=phpstan&utm_medium=github&utm_campaign=sponsorship"><img src="website/src/images/sponsor/rightcapital.png" alt="RightCapital" width="283" height="64"></a>
|
||||
|
||||
<a href="https://www.contentkingapp.com/?ref=php-developer&utm_source=phpstan&utm_medium=referral&utm_campaign=sponsorship"><img src="https://i.imgur.com/HHhbPGN.png" alt="ContentKing" width="283" height="64"></a>
|
||||
<a href="https://www.contentkingapp.com/?ref=php-developer&utm_source=phpstan&utm_medium=referral&utm_campaign=sponsorship"><img src="website/src/images/sponsor/contentking.png" alt="ContentKing" width="283" height="64"></a>
|
||||
<br>
|
||||
<a href="https://zol.fr?utm_source=phpstan"><img src="https://i.imgur.com/dzDgd4s.png" alt="ZOL" width="283" height="64"></a>
|
||||
<a href="https://zol.fr?utm_source=phpstan"><img src="website/src/images/sponsor/zol.png" alt="ZOL" width="283" height="64"></a>
|
||||
|
||||
<a href="https://www.psyonix.com/"><img src="https://i.imgur.com/p8svxQZ.png" alt="Psyonix" width="254" height="65"></a>
|
||||
<a href="https://www.edgenext.com/"><img src="website/src/images/sponsor/edgenext.png" alt="EdgeNext" width="283" height="64"></a>
|
||||
<br>
|
||||
<a href="https://www.shopware.com/en/"><img src="https://i.imgur.com/L4X5w9s.png" alt="Shopware" width="284" height="64"></a>
|
||||
<a href="https://www.shopware.com/en/"><img src="website/src/images/sponsor/shopware.png" alt="Shopware" width="284" height="64"></a>
|
||||
|
||||
<a href="https://craftcms.com/"><img src="https://i.imgur.com/xJWThke.png" alt="Craft CMS" width="283" height="64"></a>
|
||||
<a href="https://craftcms.com/"><img src="website/src/images/sponsor/craftcms.png" alt="Craft CMS" width="283" height="64"></a>
|
||||
<br>
|
||||
<a href="https://www.worksome.com/"><img src="https://i.imgur.com/TQKSwOl.png" alt="Worksome" width="283" height="64"></a>
|
||||
<a href="https://www.worksome.com/"><img src="website/src/images/sponsor/worksome.png" alt="Worksome" width="283" height="64"></a>
|
||||
|
||||
<a href="https://www.campoint.net/"><img src="https://i.imgur.com/fR6eMUm.png" alt="campoint AG" width="283" height="64"></a>
|
||||
<a href="https://www.campoint.net/"><img src="website/src/images/sponsor/campoint.png" alt="campoint AG" width="283" height="64"></a>
|
||||
<br>
|
||||
<a href="https://www.crisp.nl/"><img src="https://i.imgur.com/jRJyPve.png" alt="Crisp.nl" width="283" height="64"></a>
|
||||
<a href="https://www.crisp.nl/"><img src="website/src/images/sponsor/crisp.png" alt="Crisp.nl" width="283" height="64"></a>
|
||||
|
||||
<a href="https://inviqa.com/"><img src="https://i.imgur.com/G99rj45.png" alt="Inviqa" width="254" height="65"></a>
|
||||
<a href="https://inviqa.com/"><img src="website/src/images/sponsor/inviqa.png" alt="Inviqa" width="254" height="65"></a>
|
||||
<br>
|
||||
<a href="https://www.cdn77.com/"><img src="https://i.imgur.com/Oo3wA3m.png" alt="CDN77" width="283" height="64"></a>
|
||||
<a href="https://www.getresponse.com/"><img src="website/src/images/sponsor/getresponse.png" alt="GetResponse" width="283" height="64"></a>
|
||||
|
||||
<a href="https://www.shoptet.cz/"><img src="website/src/images/sponsor/shoptet.png" alt="Shoptet" width="283" height="64"></a>
|
||||
<br>
|
||||
<a href="https://route4me.com/"><img src="website/src/images/sponsor/route4me.png" alt="Route4Me: Route Optimizer and Route Planner Software" width="283" height="64"></a>
|
||||
|
||||
<a href="https://jobs.ticketswap.com/"><img src="website/src/images/sponsor/ticketswap.png" alt="TicketSwap" width="269" height="64"></a>
|
||||
|
||||
|
||||
[**You can now sponsor my open-source work on PHPStan through GitHub Sponsors.**](https://github.com/sponsors/ondrejmirtes)
|
||||
|
||||
Does GitHub already have your 💳? Do you use PHPStan to find 🐛 before they reach production? [Send a couple of 💸 a month my way too.](https://github.com/sponsors/ondrejmirtes) Thank you!
|
||||
|
||||
One-time donations [through PayPal](https://paypal.me/phpstan) are also accepted. To request an invoice, [contact me](mailto:ondrej@mirtes.cz) through e-mail.
|
||||
One-time donations [through Revolut.me](https://revolut.me/ondrejmirtes) are also accepted. To request an invoice, [contact me](mailto:ondrej@mirtes.cz) through e-mail.
|
||||
|
||||
## Documentation
|
||||
|
||||
|
||||
338
vendor/phpstan/phpstan/UPGRADING.md
vendored
Normal file
338
vendor/phpstan/phpstan/UPGRADING.md
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
Upgrading from PHPStan 1.x to 2.0
|
||||
=================================
|
||||
|
||||
## PHP version requirements
|
||||
|
||||
PHPStan now requires PHP 7.4 or newer to run.
|
||||
|
||||
## Upgrading guide for end users
|
||||
|
||||
The best way to get ready for upgrade to PHPStan 2.0 is to update to the **latest PHPStan 1.12 release**
|
||||
and enable [**Bleeding Edge**](https://phpstan.org/blog/what-is-bleeding-edge). This will enable the new rules and behaviours that 2.0 turns on for all users.
|
||||
|
||||
Also make sure to install and enable [`phpstan/phpstan-deprecation-rules`](https://github.com/phpstan/phpstan-deprecation-rules).
|
||||
|
||||
Once you get to a green build with no deprecations showed on latest PHPStan 1.12.x with Bleeding Edge enabled, you can update all your related PHPStan dependencies to 2.0 in `composer.json`:
|
||||
|
||||
```json
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^2.0",
|
||||
"phpstan/phpstan-doctrine": "^2.0",
|
||||
"phpstan/phpstan-nette": "^2.0",
|
||||
"phpstan/phpstan-phpunit": "^2.0",
|
||||
"phpstan/phpstan-strict-rules": "^2.0",
|
||||
"phpstan/phpstan-symfony": "^2.0",
|
||||
"phpstan/phpstan-webmozart-assert": "^2.0",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Don't forget to update [3rd party PHPStan extensions](https://phpstan.org/user-guide/extension-library) as well.
|
||||
|
||||
After changing your `composer.json`, run `composer update 'phpstan/*' -W`.
|
||||
|
||||
It's up to you whether you go through the new reported errors or if you just put them all to the [baseline](https://phpstan.org/user-guide/baseline) ;) Everyone who's on PHPStan 1.12 should be able to upgrade to PHPStan 2.0.
|
||||
|
||||
### Noteworthy changes to code analysis
|
||||
|
||||
* [**Enhancements in handling parameters passed by reference**](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference)
|
||||
* [**Validate inline PHPDoc `@var` tag type**](https://phpstan.org/blog/phpstan-1-10-comes-with-lie-detector#validate-inline-phpdoc-%40var-tag-type)
|
||||
* [**List type enforced**](https://phpstan.org/blog/phpstan-1-9-0-with-phpdoc-asserts-list-type#list-type)
|
||||
* **Always `true` conditions always reported**: previously reported only with phpstan-strict-rules, this is now always reported.
|
||||
|
||||
### Removed option `checkMissingIterableValueType`
|
||||
|
||||
It's strongly recommended to add the missing array typehints.
|
||||
|
||||
If you want to continue ignoring missing typehints from arrays, add `missingType.iterableValue` error identifier to your `ignoreErrors`:
|
||||
|
||||
```neon
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
identifier: missingType.iterableValue
|
||||
```
|
||||
|
||||
### Removed option `checkGenericClassInNonGenericObjectType`
|
||||
|
||||
It's strongly recommended to add the missing generic typehints.
|
||||
|
||||
If you want to continue ignoring missing typehints from generics, add `missingType.generics` error identifier to your `ignoreErrors`:
|
||||
|
||||
```neon
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
identifier: missingType.generics
|
||||
```
|
||||
|
||||
### Removed `checkAlwaysTrue*` options
|
||||
|
||||
These options have been removed because PHPStan now always behaves as if these were set to `true`:
|
||||
|
||||
* `checkAlwaysTrueCheckTypeFunctionCall`
|
||||
* `checkAlwaysTrueInstanceof`
|
||||
* `checkAlwaysTrueStrictComparison`
|
||||
* `checkAlwaysTrueLooseComparison`
|
||||
|
||||
### Removed option `excludes_analyse`
|
||||
|
||||
It has been replaced with [`excludePaths`](https://phpstan.org/user-guide/ignoring-errors#excluding-whole-files).
|
||||
|
||||
### Paths in `excludePaths` and `ignoreErrors` have to be a valid file path or a fnmatch pattern
|
||||
|
||||
If you are excluding a file path that might not exist but you still want to have it in `excludePaths`, append `(?)`:
|
||||
|
||||
```neon
|
||||
parameters:
|
||||
excludePaths:
|
||||
- tests/*/data/*
|
||||
- src/broken
|
||||
- node_modules (?) # optional path, might not exist
|
||||
```
|
||||
|
||||
If you have the same situation in `ignoreErrors` (ignoring an error in a path that might not exist), use `reportUnmatchedIgnoredErrors: false`.
|
||||
|
||||
```neon
|
||||
parameters:
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
```
|
||||
|
||||
Appending `(?)` in `ignoreErrors` is not supported.
|
||||
|
||||
### Changes in 1st party PHPStan extensions
|
||||
|
||||
* [phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine)
|
||||
* Removed config parameter `searchOtherMethodsForQueryBuilderBeginning` (extension now behaves as when this was set to `true`)
|
||||
* Removed config parameter `queryBuilderFastAlgorithm` (extension now behaves as when this was set to `false`)
|
||||
* [phpstan-symfony](https://github.com/phpstan/phpstan-symfony)
|
||||
* Removed legacy options with `_` in the name
|
||||
* `container_xml_path` -> use `containerXmlPath`
|
||||
* `constant_hassers` -> use `constantHassers`
|
||||
* `console_application_loader` -> use `consoleApplicationLoader`
|
||||
|
||||
### Minor backward compatibility breaks
|
||||
|
||||
* Removed unused config parameter `cache.nodesByFileCountMax`
|
||||
* Removed unused config parameter `memoryLimitFile`
|
||||
* Removed unused feature toggle `disableRuntimeReflectionProvider`
|
||||
* Removed unused config parameter `staticReflectionClassNamePatterns`
|
||||
* Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead
|
||||
* Remove `tempResultCachePath` config parameter, use `resultCachePath` instead
|
||||
* `additionalConfigFiles` config parameter must be a list
|
||||
|
||||
## Upgrading guide for extension developers
|
||||
|
||||
> [!NOTE]
|
||||
> Please switch to PHPStan 2.0 in a new major version of your extension. It's not feasible to try to support both PHPStan 1.x and PHPStan 2.x with the same extension code.
|
||||
>
|
||||
> You can definitely get closer to supporting PHPStan 2.0 without increasing major version by solving reported deprecations and other issues by analysing your extension code with PHPStan & phpstan-deprecation-rules & Bleeding Edge, but the final leap and solving backward incompatibilities should be done by requiring `"phpstan/phpstan": "^2.0"` in your `composer.json`, and releasing a new major version.
|
||||
|
||||
### PHPStan now uses nikic/php-parser v5
|
||||
|
||||
See [UPGRADING](https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md) guide for PHP-Parser.
|
||||
|
||||
The most notable change is how `throw` statement is represented. Previously, `throw` statements like `throw $e;` were represented using the `Stmt\Throw_` class, while uses inside other expressions (such as `$x ?? throw $e`) used the `Expr\Throw_` class.
|
||||
|
||||
Now, `throw $e;` is represented as a `Stmt\Expression` that contains an `Expr\Throw_`. The
|
||||
`Stmt\Throw_` class has been removed.
|
||||
|
||||
### PHPStan now uses phpstan/phpdoc-parser v2
|
||||
|
||||
See [UPGRADING](https://github.com/phpstan/phpdoc-parser/blob/2.0.x/UPGRADING.md) guide for phpstan/phpdoc-parser.
|
||||
|
||||
### Returning plain strings as errors no longer supported, use RuleErrorBuilder
|
||||
|
||||
Identifiers are also required in custom rules.
|
||||
|
||||
Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder)
|
||||
|
||||
**Before**:
|
||||
|
||||
```php
|
||||
return ['My error'];
|
||||
```
|
||||
|
||||
**After**:
|
||||
|
||||
```php
|
||||
return [
|
||||
RuleErrorBuilder::message('My error')
|
||||
->identifier('my.error')
|
||||
->build(),
|
||||
];
|
||||
```
|
||||
|
||||
### Deprecate various `instanceof *Type` in favour of new methods on `Type` interface
|
||||
|
||||
Learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated)
|
||||
|
||||
### Removed deprecated `ParametersAcceptorSelector::selectSingle()`
|
||||
|
||||
Use [`ParametersAcceptorSelector::selectFromArgs()`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ParametersAcceptorSelector.html#_selectFromArgs) instead. It should be used in most places where `selectSingle()` was previously used, like dynamic return type extensions.
|
||||
|
||||
**Before**:
|
||||
|
||||
```php
|
||||
$defaultReturnType = ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType();
|
||||
```
|
||||
|
||||
**After**:
|
||||
|
||||
```php
|
||||
$defaultReturnType = ParametersAcceptorSelector::selectFromArgs(
|
||||
$scope,
|
||||
$functionCall->getArgs(),
|
||||
$functionReflection->getVariants()
|
||||
)->getReturnType();
|
||||
```
|
||||
|
||||
If you're analysing function or method body itself and you're using one of the following methods, ask for `getParameters()` and `getReturnType()` directly on the reflection object:
|
||||
|
||||
* [InClassMethodNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InClassMethodNode.html)
|
||||
* [InFunctionNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InFunctionNode.html)
|
||||
* [FunctionReturnStatementsNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.FunctionReturnStatementsNode.html)
|
||||
* [MethodReturnStatementsNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.MethodReturnStatementsNode.html)
|
||||
* [Scope::getFunction()](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.Scope.html#_getFunction)
|
||||
|
||||
**Before**:
|
||||
|
||||
```php
|
||||
$function = $node->getFunctionReflection();
|
||||
$returnType = ParametersAcceptorSelector::selectSingle($function->getVariants())->getReturnType();
|
||||
```
|
||||
|
||||
**After**:
|
||||
|
||||
```php
|
||||
$returnType = $node->getFunctionReflection()->getReturnType();
|
||||
```
|
||||
|
||||
### Changed `TypeSpecifier::create()` and `SpecifiedTypes` constructor parameters
|
||||
|
||||
[`PHPStan\Analyser\TypeSpecifier::create()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.TypeSpecifier.html#_create) now accepts (all parameters are required):
|
||||
|
||||
* `Expr $expr`
|
||||
* `Type $type`
|
||||
* `TypeSpecifierContext $context`
|
||||
* `Scope $scope`
|
||||
|
||||
If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by this method), call `setAlwaysOverwriteTypes()` and `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::create()`). These methods return a new object (SpecifiedTypes is immutable).
|
||||
|
||||
[`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) constructor now accepts:
|
||||
|
||||
* `array $sureTypes`
|
||||
* `array $sureNotTypes`
|
||||
|
||||
If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by the constructor), call `setAlwaysOverwriteTypes()` and `setRootExpr()`. These methods return a new object (SpecifiedTypes is immutable).
|
||||
|
||||
### `ConstantArrayType` no longer extends `ArrayType`
|
||||
|
||||
`Type::getArrays()` now returns `list<ArrayType|ConstantArrayType>`.
|
||||
|
||||
Using `$type instanceof ArrayType` is [being deprecated anyway](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) so the impact of this change should be minimal.
|
||||
|
||||
### Changed `TypeSpecifier::specifyTypesInCondition()`
|
||||
|
||||
This method no longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable).
|
||||
|
||||
### Node attributes `parent`, `previous`, `next` are no longer available
|
||||
|
||||
Learn more: https://phpstan.org/blog/preprocessing-ast-for-custom-rules
|
||||
|
||||
### Removed config parameter `scopeClass`
|
||||
|
||||
As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtension`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.ExpressionTypeResolverExtension.html) interface instead and register it as a service.
|
||||
|
||||
### Removed `PHPStan\Broker\Broker`
|
||||
|
||||
Use [`PHPStan\Reflection\ReflectionProvider`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ReflectionProvider.html) instead.
|
||||
|
||||
`BrokerAwareExtension` was also removed. Ask for `ReflectionProvider` in the extension constructor instead.
|
||||
|
||||
Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createReflectionProvider()`.
|
||||
|
||||
### List type is enabled for everyone
|
||||
|
||||
Removed static methods from `AccessoryArrayListType` class:
|
||||
|
||||
* `isListTypeEnabled()`
|
||||
* `setListTypeEnabled()`
|
||||
* `intersectWith()`
|
||||
|
||||
Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::intersect($type, new AccessoryArrayListType())`.
|
||||
|
||||
### Minor backward compatibility breaks
|
||||
|
||||
* Classes that were previously `@final` were made `final`
|
||||
* Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required
|
||||
* Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required
|
||||
* ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties)
|
||||
* `Type::getSmallerType()`, `Type::getSmallerOrEqualType()`, `Type::getGreaterType()`, `Type::getGreaterOrEqualType()`, `Type::isSmallerThan()`, `Type::isSmallerThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument.
|
||||
* `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument.
|
||||
* Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes)
|
||||
* Remove `ArrayType::generalizeKeys()`
|
||||
* Remove `ArrayType::count()`, use `Type::getArraySize()` instead
|
||||
* Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead
|
||||
* Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead
|
||||
* Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead
|
||||
* Remove unused `PHPStanTestCase::$useStaticReflectionProvider`
|
||||
* Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead
|
||||
* Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead
|
||||
* Remove `AnalysisResult::getInternalErrors()`, use `getInternalErrorObjects()` instead
|
||||
* Remove `ConstantReflection::getValue()`, use `getValueExpr()` instead. To get `Type` from `Expr`, use `Scope::getType()` or `InitializerExprTypeResolver::getType()`
|
||||
* Remove `PropertyTag::getType()`, use `getReadableType()` / `getWritableType()` instead
|
||||
* Remove `GenericTypeVariableResolver`, use [`Type::getTemplateType()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getTemplateType) instead
|
||||
* Rename `Type::isClassStringType()` to `Type::isClassString()`
|
||||
* Remove `Scope::isSpecified()`, use `hasExpressionType()` instead
|
||||
* Remove `ConstantArrayType::isEmpty()`, use `isIterableAtLeastOnce()->no()` instead
|
||||
* Remove `ConstantArrayType::getNextAutoIndex()`
|
||||
* Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type`
|
||||
* Use `getFirstIterable*Type` and `getLastIterable*Type` instead
|
||||
* Remove `ConstantArrayType::generalizeToArray()`
|
||||
* Remove `ConstantArrayType::findTypeAndMethodName()`, use `findTypeAndMethodNames()` instead
|
||||
* Remove `ConstantArrayType::removeLast()`, use [`Type::popArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_popArray) instead
|
||||
* Remove `ConstantArrayType::removeFirst()`, use [`Type::shiftArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_shiftArray) instead
|
||||
* Remove `ConstantArrayType::reverse()`, use [`Type::reverseArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_reverseArray) instead
|
||||
* Remove `ConstantArrayType::chunk()`, use [`Type::chunkArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_chunkArray) instead
|
||||
* Remove `ConstantArrayType::slice()`, use [`Type::sliceArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_sliceArray) instead
|
||||
* Made `TypeUtils` thinner by removing methods:
|
||||
* Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead
|
||||
* Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead
|
||||
* Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead
|
||||
* Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize)
|
||||
* Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead
|
||||
* Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead
|
||||
* Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead
|
||||
* Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead
|
||||
* Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead
|
||||
* Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead
|
||||
* Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer `bool`
|
||||
* Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list<int>`, no longer `int`
|
||||
* Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead
|
||||
* `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool`
|
||||
* Remove `FunctionReflection::isFinal()`
|
||||
* [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html)
|
||||
* Remove `__set_state()` on objects that should not be serialized in cache
|
||||
* Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts `string`
|
||||
* `LevelsTestCase::dataTopics()` data provider made static
|
||||
* `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint
|
||||
* Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html)
|
||||
* Remove `CompoundType::isAcceptedWithReasonBy()`, `CompoundType::isAcceptedBy()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html)
|
||||
Remove `Type::isSuperTypeOfWithReason()`, `Type:isSuperTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html)
|
||||
* Remove `CompoundType::isSubTypeOfWithReasonBy()`, `CompoundType::isSubTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html)
|
||||
* Remove `TemplateType::isValidVarianceWithReason()`, changed `TemplateType::isValidVariance()` return type to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html)
|
||||
* `RuleLevelHelper::accepts()` return type changed from `bool` to [`RuleLevelHelperAcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html)
|
||||
* Changes around `ClassConstantReflection`
|
||||
* Class `ClassConstantReflection` removed from BC promise, renamed to `RealClassConstantReflection`
|
||||
* Interface `ConstantReflection` renamed to `ClassConstantReflection`
|
||||
* Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection`
|
||||
* Interface `GlobalConstantReflection` renamed to `ConstantReflection`
|
||||
* Renamed interfaces and classes from `*WithPhpDocs` to `Extended*`
|
||||
* `ParametersAcceptorWithPhpDocs` -> `ExtendedParametersAcceptor`
|
||||
* `ParameterReflectionWithPhpDocs` -> `ExtendedParameterReflection`
|
||||
* `FunctionVariantWithPhpDocs` -> `ExtendedFunctionVariant`
|
||||
* `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null`
|
||||
* Class `PHPStan\Node\ClassMethod` (accessible from `ClassMethodsNode`) is no longer an AST node
|
||||
* Call `PHPStan\Node\ClassMethod::getNode()` to access the original AST node
|
||||
60
vendor/phpstan/phpstan/bootstrap.php
vendored
60
vendor/phpstan/phpstan/bootstrap.php
vendored
@@ -3,12 +3,17 @@
|
||||
namespace PHPStan;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use function class_exists;
|
||||
use const PHP_VERSION_ID;
|
||||
|
||||
final class PharAutoloader
|
||||
{
|
||||
/** @var ClassLoader */
|
||||
private static $composerAutoloader;
|
||||
|
||||
/** @var bool */
|
||||
private static $polyfillsLoaded = false;
|
||||
|
||||
final public static function loadClass(string $class): void {
|
||||
if (!extension_loaded('phar') || defined('__PHPSTAN_RUNNING__')) {
|
||||
return;
|
||||
@@ -23,10 +28,7 @@ final class PharAutoloader
|
||||
self::$composerAutoloader = require 'phar://' . __DIR__ . '/phpstan.phar/vendor/autoload.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/async/src/functions_include.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise-stream/src/functions_include.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise-timer/src/functions_include.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise/src/functions_include.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/ringcentral/psr7/src/functions_include.php';
|
||||
}
|
||||
self::$composerAutoloader->loadClass($class);
|
||||
|
||||
@@ -40,6 +42,58 @@ final class PharAutoloader
|
||||
throw new \Exception('Phar wrapper is not registered. Please review your php.ini settings.');
|
||||
}
|
||||
|
||||
if (!self::$polyfillsLoaded) {
|
||||
self::$polyfillsLoaded = true;
|
||||
|
||||
if (
|
||||
PHP_VERSION_ID < 80000
|
||||
&& empty($GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e'])
|
||||
&& !class_exists(\Symfony\Polyfill\Php80\Php80::class, false)
|
||||
) {
|
||||
$GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e'] = true;
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/Php80.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/bootstrap.php';
|
||||
}
|
||||
|
||||
if (
|
||||
empty($GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a'])
|
||||
&& !class_exists(\Symfony\Polyfill\Mbstring\Mbstring::class, false)
|
||||
) {
|
||||
$GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a'] = true;
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/Mbstring.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/bootstrap.php';
|
||||
}
|
||||
|
||||
if (
|
||||
empty($GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38'])
|
||||
&& !class_exists(\Symfony\Polyfill\Intl\Normalizer\Normalizer::class, false)
|
||||
) {
|
||||
$GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38'] = true;
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/Normalizer.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/bootstrap.php';
|
||||
}
|
||||
|
||||
if (
|
||||
!extension_loaded('intl')
|
||||
&& empty($GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8'])
|
||||
&& !class_exists(\Symfony\Polyfill\Intl\Grapheme\Grapheme::class, false)
|
||||
) {
|
||||
$GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8'] = true;
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/Grapheme.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/bootstrap.php';
|
||||
}
|
||||
|
||||
if (
|
||||
PHP_VERSION_ID < 80100
|
||||
&& empty ($GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f'])
|
||||
&& !class_exists(\Symfony\Polyfill\Php81\Php81::class, false)
|
||||
) {
|
||||
$GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f'] = true;
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/Php81.php';
|
||||
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/bootstrap.php';
|
||||
}
|
||||
}
|
||||
|
||||
$filename = str_replace('\\', DIRECTORY_SEPARATOR, $class);
|
||||
if (strpos($class, 'PHPStan\\BetterReflection\\') === 0) {
|
||||
$filename = substr($filename, strlen('PHPStan\\BetterReflection\\'));
|
||||
|
||||
9
vendor/phpstan/phpstan/composer.json
vendored
9
vendor/phpstan/phpstan/composer.json
vendored
@@ -4,7 +4,7 @@
|
||||
"license": ["MIT"],
|
||||
"keywords": ["dev", "static analysis"],
|
||||
"require": {
|
||||
"php": "^7.2|^8.0"
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
@@ -15,5 +15,12 @@
|
||||
],
|
||||
"autoload": {
|
||||
"files": ["bootstrap.php"]
|
||||
},
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"forum": "https://github.com/phpstan/phpstan/discussions",
|
||||
"source": "https://github.com/phpstan/phpstan-src",
|
||||
"docs": "https://phpstan.org/user-guide/getting-started",
|
||||
"security": "https://github.com/phpstan/phpstan/security/policy"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
vendor/phpstan/phpstan/phpstan.phar
vendored
BIN
vendor/phpstan/phpstan/phpstan.phar
vendored
Binary file not shown.
26
vendor/phpstan/phpstan/phpstan.phar.asc
vendored
26
vendor/phpstan/phpstan/phpstan.phar.asc
vendored
@@ -1,16 +1,16 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCgAdFiEE0yaA1ZV9xxFr4pwUzxoQjQ565yAFAmP6H1oACgkQzxoQjQ56
|
||||
5yCVhxAAlXqhfvKCITSAJjkaIhncEBHpT5Ogby65BX1O5+SkKyc/OO7JnjlN8cLB
|
||||
DKbJpdc8P2Dbfo/uBHVR5YiNX5CWYzgdMzCpLQI20Ffa7qkeRbA5ZS2AfdIfLqhD
|
||||
PswlQIYxg0F3lj0L+joTxfBiHgmR5wnOUx1sLXnEbqGtFzzGstPGDg9gjKKh5EnO
|
||||
g207jrm1we05+k3kKzr233/ENvQD6bBWLr2yngyMoirOuDpurAuPjkBL7vN6PDbx
|
||||
DlyGDazsgU/R7aE2FtqmFC8KIU/BgnpbCSWTHBEJAqtncHbwTgneyEm+88lT6cUt
|
||||
YM72Rh1+QTvS3WgJ/q7AQRik2aE83Kz2rc3XOl1ADd45J3Oan1rqQXdnKtH6qZeT
|
||||
wMk6PE8SQPJ8NMHy3LT048PfMOakAtgBL5xonbVqX0IFAvKAMRijwBCNKat2yRsB
|
||||
0VGnoeH7klf1fSSo0xOD20Pd0uIILAWZlBjb2e/1NRytFQkokAr1bsLD/VJHiNYh
|
||||
lPQ4OztCT/uumJOAgTKm10T56CK1u0VxhIVtQ+/NkTvAwrmpX0KKqbYPP/1hZqVO
|
||||
vFaWJR4iLFNt+il7dlv56jmTAneUrGrWkQdVFbz5FVpqz7abIo+/cevbSSndFZCI
|
||||
K1mn42aFdYXSqVTFpkzeOQeJPPysEYDysFk7ClhE+F48HN7WAtw=
|
||||
=A7BG
|
||||
iQIzBAABCgAdFiEEynwsejDI6OEnSoR2UcZzBf/C5cAFAmcyJeMACgkQUcZzBf/C
|
||||
5cCV0A//Sg3/cyjMFpusDfq8uk57ADL2jerPD4oPRG9/smKWf14pAsWwk7PQOcQe
|
||||
zb2f+YW1tEouiyc/+RQoc+Xkv2om2N7RwaH4C7/dNnV6HYEsQS3U5cP4le/d32U6
|
||||
0wtu0Se6FieFEc5Z/wEZzbGZCa3xToIFXIC8awNvZO6p5JGB29dWeIZgbmpHHN/6
|
||||
yIxBGom0PYIf5My+J9nTlM0hYICKKGzU4NdCQzFVdenA/YCdXwr8lvec1ZwKcb2z
|
||||
Y6sJWaBvYIGPg4ej5oVuEm/vUx4NXnKpmn5Up+wOXRjzoS6ZcduO9gxCwgJ8Uh1r
|
||||
MzdTbeopFh/ZIw7HgoG32BS1yZWjBFzW5MUwCzugil9Q6wfkc5hCWFG0DvKbhZK3
|
||||
6rCPqfJQ//8C+870Ej+rX6nndn93KHp696dRjiSDFVnB3kFOUcHhFYdaSzdaWZ2x
|
||||
E26PwyI4NBIynS153EIo2S1poIAWsAXQTWaFyRqrUq+QkeioxdKJr7UVtmZJcqH3
|
||||
v5lytzJwYvmYk57CjCoJDWwY6y1b7YN1zkjzlNozlcvbF4ftzIIXZW5CcOeg1Dij
|
||||
jZEOhVnEygbCvYcXCn3RSC5OZe0wz/B5EuT4HnLpeyyE+tLg2evqfJXqwagwRZoL
|
||||
EiMpKZlYY2kEdgezzefYH1ElCvmjaa5BRTlXYswVW/G7KKJ6fq8=
|
||||
=lVJA
|
||||
-----END PGP SIGNATURE-----
|
||||
|
||||
Reference in New Issue
Block a user