1
0
Fork 0

Update phpstan and add composer/pcre extensions (#12045)

* Update phpstan and add composer/pcre extensions
* Update baseline (1516)
pull/11995/head
Jordi Boggiano 2024-07-25 16:28:25 +02:00 committed by GitHub
parent 029dda0b43
commit 7504685a2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 128 additions and 250 deletions

View File

@ -38,7 +38,7 @@
"symfony/finder": "^5.4 || ^6.0 || ^7",
"symfony/process": "^5.4 || ^6.0 || ^7",
"react/promise": "^2.8 || ^3",
"composer/pcre": "^2.1 || ^3.1",
"composer/pcre": "^2.2 || ^3.2",
"symfony/polyfill-php73": "^1.24",
"symfony/polyfill-php80": "^1.24",
"symfony/polyfill-php81": "^1.24",
@ -46,7 +46,7 @@
},
"require-dev": {
"symfony/phpunit-bridge": "^6.4.1 || ^7.0.1",
"phpstan/phpstan": "^1.11.0",
"phpstan/phpstan": "^1.11.8",
"phpstan/phpstan-phpunit": "^1.4.0",
"phpstan/phpstan-deprecation-rules": "^1.2.0",
"phpstan/phpstan-strict-rules": "^1.6.0",

62
composer.lock generated
View File

@ -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": "6a83e69e5c06f06ecba7db6c83213f9d",
"content-hash": "715b9529f60660d59b08b12c74c828c6",
"packages": [
{
"name": "composer/ca-bundle",
@ -226,30 +226,38 @@
},
{
"name": "composer/pcre",
"version": "2.1.3",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "540af382c97b83c628227d5f87cf56466d476191"
"reference": "0e455b78ac53637929b29d5ab5bf3c978329c1eb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/540af382c97b83c628227d5f87cf56466d476191",
"reference": "540af382c97b83c628227d5f87cf56466d476191",
"url": "https://api.github.com/repos/composer/pcre/zipball/0e455b78ac53637929b29d5ab5bf3c978329c1eb",
"reference": "0e455b78ac53637929b29d5ab5bf3c978329c1eb",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<1.11.8"
},
"require-dev": {
"phpstan/phpstan": "^1.3",
"phpstan/phpstan": "^1.11.8",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^5"
"phpunit/phpunit": "^8 || ^9"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.x-dev"
},
"phpstan": {
"includes": [
"extension.neon"
]
}
},
"autoload": {
@ -277,7 +285,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/2.1.3"
"source": "https://github.com/composer/pcre/tree/2.2.0"
},
"funding": [
{
@ -293,20 +301,20 @@
"type": "tidelift"
}
],
"time": "2024-03-19T09:03:05+00:00"
"time": "2024-07-25T09:28:32+00:00"
},
{
"name": "composer/semver",
"version": "3.4.1",
"version": "3.4.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "8536c1b9103405bcbd310c69e7a5739a1c2b1f0b"
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/8536c1b9103405bcbd310c69e7a5739a1c2b1f0b",
"reference": "8536c1b9103405bcbd310c69e7a5739a1c2b1f0b",
"url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6",
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6",
"shasum": ""
},
"require": {
@ -358,7 +366,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.4.1"
"source": "https://github.com/composer/semver/tree/3.4.2"
},
"funding": [
{
@ -374,7 +382,7 @@
"type": "tidelift"
}
],
"time": "2024-07-12T09:13:09+00:00"
"time": "2024-07-12T11:35:52+00:00"
},
{
"name": "composer/spdx-licenses",
@ -2012,16 +2020,16 @@
"packages-dev": [
{
"name": "phpstan/phpstan",
"version": "1.11.7",
"version": "1.11.8",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "52d2bbfdcae7f895915629e4694e9497d0f8e28d"
"reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/52d2bbfdcae7f895915629e4694e9497d0f8e28d",
"reference": "52d2bbfdcae7f895915629e4694e9497d0f8e28d",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec",
"reference": "6adbd118e6c0515dd2f36b06cde1d6da40f1b8ec",
"shasum": ""
},
"require": {
@ -2066,7 +2074,7 @@
"type": "github"
}
],
"time": "2024-07-06T11:17:41+00:00"
"time": "2024-07-24T07:01:22+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@ -2218,22 +2226,22 @@
},
{
"name": "phpstan/phpstan-symfony",
"version": "1.4.5",
"version": "1.4.6",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-symfony.git",
"reference": "1bd7c339f622dfb5a1a97dcaf1a862734eabfa1d"
"reference": "e909a075d69e0d4db262ac3407350ae2c6b6ab5f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/1bd7c339f622dfb5a1a97dcaf1a862734eabfa1d",
"reference": "1bd7c339f622dfb5a1a97dcaf1a862734eabfa1d",
"url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/e909a075d69e0d4db262ac3407350ae2c6b6ab5f",
"reference": "e909a075d69e0d4db262ac3407350ae2c6b6ab5f",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.11"
"phpstan/phpstan": "^1.11.7"
},
"conflict": {
"symfony/framework-bundle": "<3.0"
@ -2284,9 +2292,9 @@
"description": "Symfony Framework extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-symfony/issues",
"source": "https://github.com/phpstan/phpstan-symfony/tree/1.4.5"
"source": "https://github.com/phpstan/phpstan-symfony/tree/1.4.6"
},
"time": "2024-06-26T12:19:42+00:00"
"time": "2024-07-16T11:48:54+00:00"
},
{
"name": "symfony/phpunit-bridge",

View File

@ -182,14 +182,9 @@ parameters:
-
message: "#^Parameter \\#1 \\$string of function rawurlencode expects string, string\\|null given\\.$#"
count: 15
count: 8
path: ../src/Composer/Util/Git.php
-
message: "#^Parameter \\#1 \\$string of function rawurlencode expects string, string\\|null given\\.$#"
count: 2
path: ../src/Composer/Util/Hg.php
-
message: "#^Parameter \\#1 \\$multi_handle of function curl_multi_add_handle expects CurlMultiHandle, resource\\|null given\\.$#"
count: 1

View File

@ -130,11 +130,6 @@ parameters:
count: 1
path: ../src/Composer/Autoload/ClassLoader.php
-
message: "#^Casting to bool something that's already bool\\.$#"
count: 2
path: ../src/Composer/Cache.php
-
message: "#^Only booleans are allowed in a negated boolean, int\\<0, 50\\> given\\.$#"
count: 1
@ -975,11 +970,6 @@ parameters:
count: 2
path: ../src/Composer/Config.php
-
message: "#^Casting to bool something that's already bool\\.$#"
count: 1
path: ../src/Composer/Config.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
@ -1570,11 +1560,6 @@ parameters:
count: 1
path: ../src/Composer/Downloader/DownloadManager.php
-
message: "#^Method Composer\\\\Downloader\\\\FileDownloader\\:\\:getDistPath\\(\\) should return string but returns array\\<string, string\\>\\|string\\.$#"
count: 1
path: ../src/Composer/Downloader/FileDownloader.php
-
message: "#^Strict comparison using \\=\\=\\= between null and Composer\\\\Util\\\\Http\\\\Response\\|string will always evaluate to false\\.$#"
count: 1
@ -1860,11 +1845,6 @@ parameters:
count: 1
path: ../src/Composer/EventDispatcher/EventDispatcher.php
-
message: "#^Casting to bool something that's already bool\\.$#"
count: 1
path: ../src/Composer/EventDispatcher/EventDispatcher.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
@ -2067,7 +2047,7 @@ parameters:
-
message: "#^Casting to bool something that's already bool\\.$#"
count: 11
count: 1
path: ../src/Composer/Installer.php
-
@ -2130,11 +2110,6 @@ parameters:
count: 2
path: ../src/Composer/Installer/BinaryInstaller.php
-
message: "#^Only booleans are allowed in an if condition, string\\|null given\\.$#"
count: 1
path: ../src/Composer/Installer/BinaryInstaller.php
-
message: "#^Parameter \\#1 \\$binPath of method Composer\\\\Installer\\\\BinaryInstaller\\:\\:installFullBinaries\\(\\) expects string, string\\|false given\\.$#"
count: 1
@ -2160,11 +2135,6 @@ parameters:
count: 1
path: ../src/Composer/Installer/BinaryInstaller.php
-
message: "#^Parameter \\#2 \\$subject of static method Composer\\\\Pcre\\\\Preg\\:\\:isMatch\\(\\) expects string, string\\|false given\\.$#"
count: 1
path: ../src/Composer/Installer/BinaryInstaller.php
-
message: "#^Property Composer\\\\Installer\\\\BinaryInstaller\\:\\:\\$binDir \\(string\\) does not accept string\\|false\\.$#"
count: 1
@ -2410,16 +2380,6 @@ parameters:
count: 1
path: ../src/Composer/Package/AliasPackage.php
-
message: "#^Call to function method_exists\\(\\) with Closure\\(SplFileInfo\\)\\: bool and 'bindTo' will always evaluate to true\\.$#"
count: 1
path: ../src/Composer/Package/Archiver/ArchivableFilesFinder.php
-
message: "#^Parameter \\#1 \\$path of method Composer\\\\Util\\\\Filesystem\\:\\:normalizePath\\(\\) expects string, string\\|false given\\.$#"
count: 1
path: ../src/Composer/Package/Archiver/ArchivableFilesFinder.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 3
@ -2930,11 +2890,6 @@ parameters:
count: 1
path: ../src/Composer/Plugin/PostFileDownloadEvent.php
-
message: "#^Casting to bool something that's already bool\\.$#"
count: 1
path: ../src/Composer/Question/StrictConfirmationQuestion.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 2
@ -3240,11 +3195,6 @@ parameters:
count: 1
path: ../src/Composer/Repository/PearRepository.php
-
message: "#^Call to an undefined method object\\:\\:getVersion\\(\\)\\.$#"
count: 1
path: ../src/Composer/Repository/PlatformRepository.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
@ -3405,11 +3355,6 @@ parameters:
-
message: "#^Only booleans are allowed in &&, string given on the left side\\.$#"
count: 3
path: ../src/Composer/Repository/Vcs/GitDriver.php
-
message: "#^Only booleans are allowed in a negated boolean, string given\\.$#"
count: 1
path: ../src/Composer/Repository/Vcs/GitDriver.php
@ -3525,7 +3470,7 @@ parameters:
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 5
count: 4
path: ../src/Composer/Repository/Vcs/GitLabDriver.php
-
@ -3648,11 +3593,6 @@ parameters:
count: 2
path: ../src/Composer/Repository/Vcs/SvnDriver.php
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 1
path: ../src/Composer/Repository/Vcs/SvnDriver.php
-
message: "#^Method Composer\\\\Repository\\\\Vcs\\\\SvnDriver\\:\\:getRootIdentifier\\(\\) should return string but returns string\\|false\\.$#"
count: 1
@ -3663,26 +3603,11 @@ parameters:
count: 1
path: ../src/Composer/Repository/Vcs/SvnDriver.php
-
message: "#^Only booleans are allowed in &&, string given on the left side\\.$#"
count: 4
path: ../src/Composer/Repository/Vcs/SvnDriver.php
-
message: "#^Only booleans are allowed in &&, string\\|false given on the right side\\.$#"
count: 1
path: ../src/Composer/Repository/Vcs/SvnDriver.php
-
message: "#^Only booleans are allowed in a negated boolean, string given\\.$#"
count: 1
path: ../src/Composer/Repository/Vcs/SvnDriver.php
-
message: "#^Only booleans are allowed in an if condition, string given\\.$#"
count: 3
path: ../src/Composer/Repository/Vcs/SvnDriver.php
-
message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#"
count: 1
@ -3903,16 +3828,6 @@ parameters:
count: 1
path: ../src/Composer/Util/ConfigValidator.php
-
message: "#^Only booleans are allowed in a negated boolean, int given\\.$#"
count: 1
path: ../src/Composer/Util/ErrorHandler.php
-
message: "#^Only booleans are allowed in an if condition, Composer\\\\IO\\\\IOInterface\\|null given\\.$#"
count: 1
path: ../src/Composer/Util/ErrorHandler.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
@ -3923,26 +3838,11 @@ parameters:
count: 1
path: ../src/Composer/Util/Git.php
-
message: "#^Only booleans are allowed in &&, string given on the right side\\.$#"
count: 1
path: ../src/Composer/Util/Git.php
-
message: "#^Only booleans are allowed in &&, string\\|false given on the left side\\.$#"
count: 1
path: ../src/Composer/Util/Git.php
-
message: "#^Only booleans are allowed in &&, string\\|null given on the left side\\.$#"
count: 1
path: ../src/Composer/Util/Git.php
-
message: "#^Only booleans are allowed in an if condition, int\\<0, max\\>\\|false given\\.$#"
count: 1
path: ../src/Composer/Util/Git.php
-
message: "#^Only booleans are allowed in an if condition, string\\|false given\\.$#"
count: 2
@ -3950,7 +3850,7 @@ parameters:
-
message: "#^Parameter \\#1 \\$str of function rawurlencode expects string, string\\|null given\\.$#"
count: 15
count: 8
path: ../src/Composer/Util/Git.php
-
@ -3998,11 +3898,6 @@ parameters:
count: 2
path: ../src/Composer/Util/GitLab.php
-
message: "#^Parameter \\#1 \\$str of function rawurlencode expects string, string\\|null given\\.$#"
count: 2
path: ../src/Composer/Util/Hg.php
-
message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1
@ -4703,11 +4598,6 @@ parameters:
count: 2
path: ../src/bootstrap.php
-
message: "#^Call to method RecursiveDirectoryIterator\\:\\:getSubPathname\\(\\) with incorrect case\\: getSubPathName$#"
count: 1
path: ../tests/Composer/Test/AllFunctionalTest.php
-
message: "#^Method Composer\\\\Test\\\\AllFunctionalTest\\:\\:cleanOutput\\(\\) should return string but returns string\\|false\\.$#"
count: 1
@ -4723,26 +4613,11 @@ parameters:
count: 1
path: ../tests/Composer/Test/AllFunctionalTest.php
-
message: "#^Only booleans are allowed in \\|\\|, string given on the right side\\.$#"
count: 1
path: ../tests/Composer/Test/AllFunctionalTest.php
-
message: "#^Only numeric types are allowed in \\-, int\\<0, max\\>\\|false given on the left side\\.$#"
count: 3
path: ../tests/Composer/Test/AllFunctionalTest.php
-
message: "#^Parameter \\#1 \\$string of function substr expects string, string\\|false given\\.$#"
count: 1
path: ../tests/Composer/Test/AllFunctionalTest.php
-
message: "#^Parameter \\#2 \\$subject of static method Composer\\\\Pcre\\\\Preg\\:\\:split\\(\\) expects string, string\\|false given\\.$#"
count: 1
path: ../tests/Composer/Test/AllFunctionalTest.php
-
message: "#^Dynamic call to static method Composer\\\\Test\\\\TestCase\\:\\:ensureDirectoryExistsAndClear\\(\\)\\.$#"
count: 1

View File

@ -4,6 +4,7 @@ includes:
- ../vendor/phpstan/phpstan-deprecation-rules/rules.neon
- ../vendor/phpstan/phpstan-strict-rules/rules.neon
- ../vendor/phpstan/phpstan-symfony/extension.neon
- ../vendor/composer/pcre/extension.neon
- ../vendor/phpstan/phpstan-symfony/rules.neon
# TODO when requiring php 7.4+ we can use this
#- ../vendor/staabm/phpstan-todo-by/extension.neon

View File

@ -291,7 +291,7 @@ EOT
$source = $this->config->getSourceOfValue($settingKey);
if (Preg::isMatch('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
if (!isset($matches[1]) || $matches[1] === '') {
if (!isset($matches[1])) {
$value = $data['repositories'] ?? [];
} else {
if (!isset($data['repositories'][$matches[1]])) {

View File

@ -468,8 +468,6 @@ EOT
private function parseAuthorString(string $author): array
{
if (Preg::isMatch('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'"()]+)(?:\s+<(?P<email>.+?)>)?$/u', $author, $match)) {
assert(is_string($match['name']));
if (null !== $match['email'] && !$this->isValidEmail($match['email'])) {
throw new \InvalidArgumentException('Invalid email "'.$match['email'].'"');
}

View File

@ -120,6 +120,7 @@ class Compiler
->notPath('/bin\/(jsonlint|validate-json|simple-phpunit|phpstan|phpstan\.phar)(\.bat)?$/')
->notPath('justinrainbow/json-schema/demo/')
->notPath('justinrainbow/json-schema/dist/')
->notPath('composer/pcre/extension.neon')
->notPath('composer/LICENSE')
->exclude('Tests')
->exclude('tests')

View File

@ -255,7 +255,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
}
$headRef = $match[1];
if (!Preg::isMatchAllStrictGroups('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
if (!Preg::isMatchAllStrictGroups('{^'.preg_quote($headRef).' refs/heads/(.+)$}mi', $refs, $matches)) {
// not on a branch, we are either on a not-modified tag or some sort of detached head, so skip this
return null;
}

View File

@ -213,7 +213,7 @@ class BinaryInstaller
$binDir = ProcessExecutor::escape(dirname($binPath));
$binFile = basename($binPath);
$binContents = file_get_contents($bin, false, null, 0, 500);
$binContents = (string) file_get_contents($bin, false, null, 0, 500);
// For php files, we generate a PHP proxy instead of a shell one,
// which allows calling the proxy with a custom php process
if (Preg::isMatch('{^(#!.*\r?\n)?[\r\n\t ]*<\?php}', $binContents, $match)) {
@ -224,7 +224,7 @@ class BinaryInstaller
$globalsCode = '$GLOBALS[\'_composer_bin_dir\'] = __DIR__;'."\n";
$phpunitHack1 = $phpunitHack2 = '';
// Don't expose autoload path when vendor dir was not set in custom installers
if ($this->vendorDir) {
if ($this->vendorDir !== null) {
// ensure comparisons work accurately if the CWD is a symlink, as $link is realpath'd already
$vendorDirReal = realpath($this->vendorDir);
if ($vendorDirReal === false) {
@ -242,7 +242,7 @@ class BinaryInstaller
$data = str_replace(\'__DIR__\', var_export(dirname($this->realpath), true), $data);
$data = str_replace(\'__FILE__\', var_export($this->realpath, true), $data);';
}
if (trim((string) $match[0]) !== '<?php') {
if (trim($match[0]) !== '<?php') {
$streamHint = ' using a stream wrapper to prevent the shebang from being output on PHP<8'."\n *";
$streamProxyCode = <<<STREAMPROXY
if (PHP_VERSION_ID < 80000) {

View File

@ -56,9 +56,12 @@ class Runtime
}
/**
* @param class-string $class
* @template T of object
* @param mixed[] $arguments
*
* @phpstan-param class-string<T> $class
* @phpstan-return T
*
* @throws \ReflectionException
*/
public function construct(string $class, array $arguments = []): object

View File

@ -350,16 +350,18 @@ class PlatformRepository extends ArrayRepository
break;
case 'imagick':
// @phpstan-ignore staticMethod.dynamicCall (called like this for mockability)
$imageMagickVersion = $this->runtime->construct('Imagick')->getVersion();
// 6.x: ImageMagick 6.2.9 08/24/06 Q16 http://www.imagemagick.org
// 7.x: ImageMagick 7.0.8-34 Q16 x86_64 2019-03-23 https://imagemagick.org
Preg::match('/^ImageMagick (?<version>[\d.]+)(?:-(?<patch>\d+))?/', $imageMagickVersion['versionString'], $matches);
if (Preg::isMatch('/^ImageMagick (?<version>[\d.]+)(?:-(?<patch>\d+))?/', $imageMagickVersion['versionString'], $matches)) {
$version = $matches['version'];
if (isset($matches['patch'])) {
$version .= '.'.$matches['patch'];
}
$this->addLibrary($name.'-imagemagick', $version, null, ['imagick']);
}
break;
case 'ldap':

View File

@ -153,7 +153,7 @@ class GitDriver extends VcsDriver
$resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
$this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
if (!trim($content)) {
if (trim($content) === '') {
return null;
}
@ -182,9 +182,9 @@ class GitDriver extends VcsDriver
$this->tags = [];
$this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
foreach ($output = $this->process->splitLines($output) as $tag) {
if ($tag && Preg::isMatch('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
$this->tags[$match[2]] = (string) $match[1];
foreach ($this->process->splitLines($output) as $tag) {
if ($tag !== '' && Preg::isMatch('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
$this->tags[$match[2]] = $match[1];
}
}
}
@ -202,7 +202,7 @@ class GitDriver extends VcsDriver
$this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
foreach ($this->process->splitLines($output) as $branch) {
if ($branch && !Preg::isMatch('{^ *[^/]+/HEAD }', $branch)) {
if ($branch !== '' && !Preg::isMatch('{^ *[^/]+/HEAD }', $branch)) {
if (Preg::isMatchStrictGroups('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match) && $match[1][0] !== '-') {
$branches[$match[1]] = $match[2];
}

View File

@ -63,8 +63,6 @@ class GitHubDriver extends VcsDriver
throw new \InvalidArgumentException(sprintf('The GitHub repository URL %s is invalid.', $this->url));
}
assert(is_string($match[3]));
assert(is_string($match[4]));
$this->owner = $match[3];
$this->repository = $match[4];
$this->originUrl = strtolower($match[1] ?? (string) $match[2]);

View File

@ -97,8 +97,6 @@ class GitLabDriver extends VcsDriver
throw new \InvalidArgumentException(sprintf('The GitLab repository URL %s is invalid. It must be the HTTP URL of a GitLab project.', $this->url));
}
assert(is_string($match['parts']));
assert(is_string($match['repo']));
$guessedDomain = $match['domain'] ?? (string) $match['domain2'];
$configuredDomains = $this->config->get('gitlab-domains');
$urlParts = explode('/', $match['parts']);
@ -115,7 +113,7 @@ class GitLabDriver extends VcsDriver
if (is_string($protocol = $this->config->get('gitlab-protocol'))) {
// https treated as a synonym for http.
if (!in_array($protocol, ['git', 'http', 'https'])) {
if (!in_array($protocol, ['git', 'http', 'https'], true)) {
throw new \RuntimeException('gitlab-protocol must be one of git, http.');
}
$this->protocol = $protocol === 'git' ? 'ssh' : 'http';
@ -566,8 +564,6 @@ class GitLabDriver extends VcsDriver
return false;
}
assert(is_string($match['parts']));
assert(is_string($match['repo']));
$scheme = $match['scheme'];
$guessedDomain = $match['domain'] ?? (string) $match['domain2'];
$urlParts = explode('/', $match['parts']);

View File

@ -177,8 +177,7 @@ class SvnDriver extends VcsDriver
{
$identifier = '/' . trim($identifier, '/') . '/';
Preg::match('{^(.+?)(@\d+)?/$}', $identifier, $match);
if (!empty($match[2])) {
if (Preg::isMatch('{^(.+?)(@\d+)?/$}', $identifier, $match) && $match[2] !== null) {
$path = $match[1];
$rev = $match[2];
} else {
@ -189,7 +188,7 @@ class SvnDriver extends VcsDriver
try {
$resource = $path.$file;
$output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
if (!trim($output)) {
if ('' === trim($output)) {
return null;
}
} catch (\RuntimeException $e) {
@ -206,8 +205,7 @@ class SvnDriver extends VcsDriver
{
$identifier = '/' . trim($identifier, '/') . '/';
Preg::match('{^(.+?)(@\d+)?/$}', $identifier, $match);
if (null !== $match[2] && null !== $match[1]) {
if (Preg::isMatch('{^(.+?)(@\d+)?/$}', $identifier, $match) && null !== $match[2]) {
$path = $match[1];
$rev = $match[2];
} else {
@ -217,7 +215,7 @@ class SvnDriver extends VcsDriver
$output = $this->execute('svn info', $this->baseUrl . $path . $rev);
foreach ($this->process->splitLines($output) as $line) {
if ($line && Preg::isMatchStrictGroups('{^Last Changed Date: ([^(]+)}', $line, $match)) {
if ($line !== '' && Preg::isMatchStrictGroups('{^Last Changed Date: ([^(]+)}', $line, $match)) {
return new \DateTimeImmutable($match[1], new \DateTimeZone('UTC'));
}
}
@ -235,12 +233,11 @@ class SvnDriver extends VcsDriver
if ($this->tagsPath !== false) {
$output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
if ($output) {
if ($output !== '') {
$lastRev = 0;
foreach ($this->process->splitLines($output) as $line) {
$line = trim($line);
if ($line && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
if (isset($match[1], $match[2])) {
if ($line !== '' && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
if ($match[2] === './') {
$lastRev = (int) $match[1];
} else {
@ -253,7 +250,6 @@ class SvnDriver extends VcsDriver
}
}
}
}
$this->tags = $tags;
}
@ -276,11 +272,11 @@ class SvnDriver extends VcsDriver
}
$output = $this->execute('svn ls --verbose', $trunkParent);
if ($output) {
if ($output !== '') {
foreach ($this->process->splitLines($output) as $line) {
$line = trim($line);
if ($line && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
if (isset($match[1], $match[2]) && $match[2] === './') {
if ($line !== '' && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
if ($match[2] === './') {
$branches['trunk'] = $this->buildIdentifier(
'/' . $this->trunkPath,
(int) $match[1]
@ -295,12 +291,11 @@ class SvnDriver extends VcsDriver
if ($this->branchesPath !== false) {
$output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
if ($output) {
if ($output !== '') {
$lastRev = 0;
foreach ($this->process->splitLines(trim($output)) as $line) {
$line = trim($line);
if ($line && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
if (isset($match[1], $match[2])) {
if ($line !== '' && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
if ($match[2] === './') {
$lastRev = (int) $match[1];
} else {
@ -313,7 +308,6 @@ class SvnDriver extends VcsDriver
}
}
}
}
$this->branches = $branches;
}

View File

@ -40,7 +40,7 @@ class ErrorHandler
$isDeprecationNotice = $level === E_DEPRECATED || $level === E_USER_DEPRECATED;
// error code is not included in error_reporting
if (!$isDeprecationNotice && !(error_reporting() & $level)) {
if (!$isDeprecationNotice && 0 === (error_reporting() & $level)) {
return true;
}
@ -53,7 +53,7 @@ class ErrorHandler
throw new \ErrorException($message, 0, $level, $file, $line);
}
if (self::$io) {
if (self::$io !== null) {
self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
if (self::$io->isVerbose()) {
self::$io->writeError('<warning>Stack trace:</warning>');

View File

@ -69,6 +69,7 @@ class Git
$protocols = $this->config->get('github-protocols');
// public github, autoswitch protocols
// @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
if (Preg::isMatchStrictGroups('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
$messages = [];
foreach ($protocols as $protocol) {
@ -104,7 +105,9 @@ class Git
if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $commandOutput, $cwd)) {
$errorMsg = $this->process->getErrorOutput();
// private github repository without ssh key access, try https with auth
// @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
if (Preg::isMatchStrictGroups('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)
// @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
|| Preg::isMatchStrictGroups('{^https?://' . self::getGitHubDomainsRegex($this->config) . '/(.*?)(?:\.git)?$}i', $url, $match)
) {
if (!$this->io->hasAuthentication($match[1])) {
@ -127,6 +130,7 @@ class Git
$credentials = [rawurlencode($auth['username']), rawurlencode($auth['password'])];
$errorMsg = $this->process->getErrorOutput();
}
// @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
} elseif (Preg::isMatchStrictGroups('{^https://(bitbucket\.org)/(.*?)(?:\.git)?$}i', $url, $match)) { //bitbucket oauth
$bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
@ -172,7 +176,9 @@ class Git
$errorMsg = $this->process->getErrorOutput();
}
} elseif (
// @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
Preg::isMatchStrictGroups('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?\.git)$}i', $url, $match)
// @phpstan-ignore composerPcre.maybeUnsafeStrictGroups
|| Preg::isMatchStrictGroups('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}i', $url, $match)
) {
if ($match[1] === 'git') {
@ -191,9 +197,9 @@ class Git
if ($this->io->hasAuthentication($match[2])) {
$auth = $this->io->getAuthentication($match[2]);
if ($auth['password'] === 'private-token' || $auth['password'] === 'oauth2' || $auth['password'] === 'gitlab-ci-token') {
$authUrl = $match[1] . '://' . rawurlencode($auth['password']) . ':' . rawurlencode($auth['username']) . '@' . $match[2] . '/' . $match[3]; // swap username and password
$authUrl = $match[1] . '://' . rawurlencode($auth['password']) . ':' . rawurlencode((string) $auth['username']) . '@' . $match[2] . '/' . $match[3]; // swap username and password
} else {
$authUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . '/' . $match[3];
$authUrl = $match[1] . '://' . rawurlencode((string) $auth['username']) . ':' . rawurlencode((string) $auth['password']) . '@' . $match[2] . '/' . $match[3];
}
$command = $commandCallable($authUrl);
@ -201,11 +207,11 @@ class Git
return;
}
$credentials = [rawurlencode($auth['username']), rawurlencode($auth['password'])];
$credentials = [rawurlencode((string) $auth['username']), rawurlencode((string) $auth['password'])];
$errorMsg = $this->process->getErrorOutput();
}
} elseif ($this->isAuthenticationFailure($url, $match)) { // private non-github/gitlab/bitbucket repo that failed to authenticate
if (strpos($match[2], '@')) {
} elseif (null !== ($match = $this->getAuthenticationFailure($url))) { // private non-github/gitlab/bitbucket repo that failed to authenticate
if (str_contains($match[2], '@')) {
[$authParts, $match[2]] = explode('@', $match[2], 2);
}
@ -214,8 +220,8 @@ class Git
$auth = $this->io->getAuthentication($match[2]);
} elseif ($this->io->isInteractive()) {
$defaultUsername = null;
if (isset($authParts) && $authParts) {
if (false !== strpos($authParts, ':')) {
if (isset($authParts) && $authParts !== '') {
if (str_contains($authParts, ':')) {
[$defaultUsername, ] = explode(':', $authParts, 2);
} else {
$defaultUsername = $authParts;
@ -232,7 +238,7 @@ class Git
}
if (null !== $auth) {
$authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
$authUrl = $match[1] . rawurlencode((string) $auth['username']) . ':' . rawurlencode((string) $auth['password']) . '@' . $match[2] . $match[3];
$command = $commandCallable($authUrl);
if (0 === $this->process->execute($command, $commandOutput, $cwd)) {
@ -243,7 +249,7 @@ class Git
return;
}
$credentials = [rawurlencode($auth['username']), rawurlencode($auth['password'])];
$credentials = [rawurlencode((string) $auth['username']), rawurlencode((string) $auth['password'])];
$errorMsg = $this->process->getErrorOutput();
}
}
@ -262,7 +268,7 @@ class Git
public function syncMirror(string $url, string $dir): bool
{
if (Platform::getEnv('COMPOSER_DISABLE_NETWORK') && Platform::getEnv('COMPOSER_DISABLE_NETWORK') !== 'prime') {
if ((bool) Platform::getEnv('COMPOSER_DISABLE_NETWORK') && Platform::getEnv('COMPOSER_DISABLE_NETWORK') !== 'prime') {
$this->io->writeError('<warning>Aborting git mirror sync of '.$url.' as network is disabled</warning>');
return false;
@ -357,13 +363,12 @@ class Git
}
/**
* @param array<mixed> $match
* @param-out array<int|string, string> $match
* @return array<int, string>|null
*/
private function isAuthenticationFailure(string $url, array &$match): bool
private function getAuthenticationFailure(string $url): ?array
{
if (!Preg::isMatchStrictGroups('{^(https?://)([^/]+)(.*)$}i', $url, $match)) {
return false;
return null;
}
$authFailures = [
@ -377,11 +382,11 @@ class Git
$errorOutput = $this->process->getErrorOutput();
foreach ($authFailures as $authFailure) {
if (strpos($errorOutput, $authFailure) !== false) {
return true;
return $match;
}
}
return false;
return null;
}
public function getMirrorDefaultBranch(string $url, string $dir, bool $isLocalPathRepository): ?string
@ -405,7 +410,7 @@ class Git
$lines = $this->process->splitLines($output);
foreach ($lines as $line) {
if (Preg::match('{^\s*HEAD branch:\s(.+)\s*$}m', $line, $matches) > 0) {
if (Preg::isMatch('{^\s*HEAD branch:\s(.+)\s*$}m', $line, $matches)) {
return $matches[1];
}
}

View File

@ -60,17 +60,17 @@ class Hg
// Try with the authentication information available
if (
Preg::isMatch('{^(?P<proto>ssh|https?)://(?:(?P<user>[^:@]+)(?::(?P<pass>[^:@]+))?@)?(?P<host>[^/]+)(?P<path>/.*)?}mi', $url, $matches)
&& $this->io->hasAuthentication((string) $matches['host'])
&& $this->io->hasAuthentication($matches['host'])
) {
if ($matches['proto'] === 'ssh') {
$user = '';
if ($matches['user'] !== '' && $matches['user'] !== null) {
if ($matches['user'] !== null) {
$user = rawurlencode($matches['user']) . '@';
}
$authenticatedUrl = $matches['proto'] . '://' . $user . $matches['host'] . $matches['path'];
} else {
$auth = $this->io->getAuthentication((string) $matches['host']);
$authenticatedUrl = $matches['proto'] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $matches['host'] . $matches['path'];
$auth = $this->io->getAuthentication($matches['host']);
$authenticatedUrl = $matches['proto'] . '://' . rawurlencode((string) $auth['username']) . ':' . rawurlencode((string) $auth['password']) . '@' . $matches['host'] . $matches['path'];
}
$command = $commandCallable($authenticatedUrl);

View File

@ -78,7 +78,7 @@ class AllFunctionalTest extends TestCase
$ri = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($ri as $file) {
$targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
$targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathname();
if ($file->isDir()) {
$fs->ensureDirectoryExists($targetPath);
} else {
@ -89,7 +89,7 @@ class AllFunctionalTest extends TestCase
$proc = new Process([PHP_BINARY, '-dphar.readonly=0', './bin/compile'], $target);
$exitcode = $proc->run();
if ($exitcode !== 0 || trim($proc->getOutput())) {
if ($exitcode !== 0 || trim($proc->getOutput()) !== '') {
$this->fail($proc->getOutput());
}
@ -136,7 +136,9 @@ class AllFunctionalTest extends TestCase
$line++;
}
if ($expected[$i] === '%') {
Preg::isMatchStrictGroups('{%(.+?)%}', substr($expected, $i), $match);
if (!Preg::isMatchStrictGroups('{%(.+?)%}', substr($expected, $i), $match)) {
throw new \LogicException('Failed to match %...% in '.substr($expected, $i));
}
$regex = $match[1];
if (Preg::isMatch('{'.$regex.'}', substr($output, $j), $match)) {
@ -146,7 +148,7 @@ class AllFunctionalTest extends TestCase
} else {
$this->fail(
'Failed to match pattern '.$regex.' at line '.$line.' / abs offset '.$i.': '
.substr($output, $j, min(strpos($output, "\n", $j) - $j, 100)).PHP_EOL.PHP_EOL.
.substr($output, $j, min(((int) strpos($output, "\n", $j)) - $j, 100)).PHP_EOL.PHP_EOL.
'Output:'.PHP_EOL.$output
);
}
@ -154,8 +156,8 @@ class AllFunctionalTest extends TestCase
if ($expected[$i] !== $output[$j]) {
$this->fail(
'Output does not match expectation at line '.$line.' / abs offset '.$i.': '.PHP_EOL
.'-'.substr($expected, $i, min(strpos($expected, "\n", $i) - $i, 100)).PHP_EOL
.'+'.substr($output, $j, min(strpos($output, "\n", $j) - $j, 100)).PHP_EOL.PHP_EOL
.'-'.substr($expected, $i, min(((int) strpos($expected, "\n", $i)) - $i, 100)).PHP_EOL
.'+'.substr($output, $j, min(((int) strpos($output, "\n", $j)) - $j, 100)).PHP_EOL.PHP_EOL
.'Output:'.PHP_EOL.$output
);
}
@ -195,7 +197,7 @@ class AllFunctionalTest extends TestCase
*/
private function parseTestFile(string $file): array
{
$tokens = Preg::split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file), -1, PREG_SPLIT_DELIM_CAPTURE);
$tokens = Preg::split('#(?:^|\n*)--([A-Z-]+)--\n#', (string) file_get_contents($file), -1, PREG_SPLIT_DELIM_CAPTURE);
$data = [];
$section = null;