diff --git a/composer.lock b/composer.lock index 55d1cf38e..4595f9519 100644 --- a/composer.lock +++ b/composer.lock @@ -305,24 +305,24 @@ }, { "name": "composer/semver", - "version": "3.4.2", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", - "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "^1.4", - "symfony/phpunit-bridge": "^4.2 || ^5" + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" }, "type": "library", "extra": { @@ -366,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.2" + "source": "https://github.com/composer/semver/tree/3.4.3" }, "funding": [ { @@ -382,7 +382,7 @@ "type": "tidelift" } ], - "time": "2024-07-12T11:35:52+00:00" + "time": "2024-09-19T14:15:21+00:00" }, { "name": "composer/spdx-licenses", @@ -2020,16 +2020,16 @@ "packages-dev": [ { "name": "phpstan/phpstan", - "version": "1.12.3", + "version": "1.12.4", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009" + "reference": "ffa517cb918591b93acc9b95c0bebdcd0e4538bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0fcbf194ab63d8159bb70d9aa3e1350051632009", - "reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ffa517cb918591b93acc9b95c0bebdcd0e4538bd", + "reference": "ffa517cb918591b93acc9b95c0bebdcd0e4538bd", "shasum": "" }, "require": { @@ -2074,7 +2074,7 @@ "type": "github" } ], - "time": "2024-09-09T08:10:35+00:00" + "time": "2024-09-19T07:58:01+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", diff --git a/phpstan/baseline.neon b/phpstan/baseline.neon index 7f26fa595..dc754784e 100644 --- a/phpstan/baseline.neon +++ b/phpstan/baseline.neon @@ -670,16 +670,6 @@ parameters: count: 1 path: ../src/Composer/Command/ShowCommand.php - - - message: "#^Only booleans are allowed in &&, array\\ given on the right side\\.$#" - count: 1 - path: ../src/Composer/Command/ShowCommand.php - - - - message: "#^Only booleans are allowed in &&, array\\ given on the right side\\.$#" - count: 1 - path: ../src/Composer/Command/ShowCommand.php - - message: "#^Only booleans are allowed in &&, string given on the left side\\.$#" count: 1 @@ -800,11 +790,6 @@ parameters: count: 2 path: ../src/Composer/Command/ShowCommand.php - - - message: "#^Parameter \\#2 \\$literals of method Composer\\\\DependencyResolver\\\\DefaultPolicy\\:\\:selectPreferredPackages\\(\\) expects array\\, array\\ given\\.$#" - count: 1 - path: ../src/Composer/Command/ShowCommand.php - - message: "#^Parameter \\#2 \\.\\.\\.\\$values of function sprintf expects bool\\|float\\|int\\|string\\|null, array\\|string given\\.$#" count: 1 @@ -905,19 +890,9 @@ parameters: count: 1 path: ../src/Composer/Command/UpdateCommand.php - - - message: "#^Call to function in_array\\(\\) requires parameter \\#3 to be set\\.$#" - count: 1 - path: ../src/Composer/Command/UpdateCommand.php - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 3 - path: ../src/Composer/Command/UpdateCommand.php - - - - message: "#^Only booleans are allowed in a negated boolean, array\\ given\\.$#" - count: 1 + count: 2 path: ../src/Composer/Command/UpdateCommand.php - @@ -1095,96 +1070,11 @@ parameters: count: 1 path: ../src/Composer/Console/GithubActionError.php - - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Decisions.php - - - - message: "#^Method Composer\\\\DependencyResolver\\\\Decisions\\:\\:key\\(\\) should return int\\|null but returns int\\|string\\|null\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Decisions.php - - - - message: "#^Only booleans are allowed in a ternary operator condition, Composer\\\\DependencyResolver\\\\Pool\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Decisions.php - - message: "#^Return type \\(array\\{int, Composer\\\\DependencyResolver\\\\Rule\\}\\|false\\) of method Composer\\\\DependencyResolver\\\\Decisions\\:\\:current\\(\\) should be covariant with return type \\(array\\{int, Composer\\\\DependencyResolver\\\\Rule\\}\\) of method Iterator\\\\>\\:\\:current\\(\\)$#" count: 1 path: ../src/Composer/DependencyResolver/Decisions.php - - - message: "#^Only booleans are allowed in &&, string\\|null given on the left side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/DefaultPolicy.php - - - - message: "#^Cannot access offset 'hash' on array\\|false\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/GenericRule.php - - - - message: "#^Cannot access offset 'hash' on array\\|false\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/MultiConflictRule.php - - - - message: "#^Only booleans are allowed in \\|\\|, mixed given on the right side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Pool.php - - - - message: "#^Cannot call method getPackages\\(\\) on Composer\\\\Repository\\\\LockArrayRepository\\|null\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/PoolBuilder.php - - - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/PoolBuilder.php - - - - message: "#^Only booleans are allowed in a negated boolean, array\\ given\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/PoolBuilder.php - - - - message: "#^Only booleans are allowed in an if condition, Composer\\\\EventDispatcher\\\\EventDispatcher\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/PoolBuilder.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/PoolBuilder.php - - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/PoolBuilder.php - - - - message: "#^Parameter \\#4 \\$index of method Composer\\\\DependencyResolver\\\\PoolBuilder\\:\\:removeLoadedPackage\\(\\) expects int, int\\|string given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/PoolBuilder.php - - - - message: "#^Only booleans are allowed in a negated boolean, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/PoolOptimizer.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/PoolOptimizer.php - - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 4 - path: ../src/Composer/DependencyResolver/PoolOptimizer.php - - message: "#^Cannot call method getPrettyString\\(\\) on array\\\\|Composer\\\\Package\\\\BasePackage\\|Composer\\\\Package\\\\Link\\|int\\|string\\.$#" count: 1 @@ -1192,11 +1082,6 @@ parameters: - message: "#^Cannot call method getRepoName\\(\\) on Composer\\\\Repository\\\\RepositoryInterface\\|null\\.$#" - count: 3 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Cannot call method getRepository\\(\\) on Composer\\\\Package\\\\PackageInterface\\|false\\.$#" count: 1 path: ../src/Composer/DependencyResolver/Problem.php @@ -1205,311 +1090,11 @@ parameters: count: 1 path: ../src/Composer/DependencyResolver/Problem.php - - - message: "#^Only booleans are allowed in &&, Composer\\\\DependencyResolver\\\\Pool\\|null given on the left side\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in &&, Composer\\\\Semver\\\\Constraint\\\\ConstraintInterface\\|null given on the right side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in a negated boolean, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in a ternary operator condition, Composer\\\\Semver\\\\Constraint\\\\ConstraintInterface\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in a ternary operator condition, string given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in an if condition, Composer\\\\Package\\\\BasePackage\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 5 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in an if condition, array\\\\> given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in an if condition, int\\<0, max\\> given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Parameter \\#3 \\$subject of function str_replace expects array\\|string, string\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Problem.php - - - - message: "#^Only booleans are allowed in an if condition, Composer\\\\Repository\\\\LockArrayRepository\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Request.php - - - - message: "#^Foreach overwrites \\$literal with its value variable\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Rule.php - - message: "#^Method Composer\\\\DependencyResolver\\\\Rule\\:\\:getReason\\(\\) should return 2\\|3\\|6\\|7\\|10\\|12\\|13\\|14 but returns int\\<0, 255\\>\\.$#" count: 1 path: ../src/Composer/DependencyResolver/Rule.php - - - message: "#^Only booleans are allowed in &&, array\\ given on the left side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Rule.php - - - - message: "#^Only booleans are allowed in &&, array\\ given on the right side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Rule.php - - - - message: "#^Only booleans are allowed in a negated boolean, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Rule.php - - - - message: "#^Only booleans are allowed in an if condition, Composer\\\\Repository\\\\LockArrayRepository\\|null given\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Rule.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Rule.php - - - - message: "#^Parameter \\#1 \\$literal of method Composer\\\\DependencyResolver\\\\Pool\\:\\:literalToPackage\\(\\) expects int, int\\|null given\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Rule.php - - - - message: "#^Parameter \\#1 \\$packages of static method Composer\\\\DependencyResolver\\\\Problem\\:\\:getPackageList\\(\\) expects array\\, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Rule.php - - - - message: "#^Only booleans are allowed in &&, Composer\\\\DependencyResolver\\\\Pool\\|null given on the right side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSet.php - - - - message: "#^Only booleans are allowed in &&, Composer\\\\DependencyResolver\\\\Request\\|null given on the right side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSet.php - - - - message: "#^Only booleans are allowed in &&, Composer\\\\Repository\\\\RepositorySet\\|null given on the left side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSet.php - - - - message: "#^Only booleans are allowed in a negated boolean, Composer\\\\DependencyResolver\\\\Rule\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSetGenerator.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSetGenerator.php - - - - message: "#^Parameter \\#3 \\$reasonData of class Composer\\\\DependencyResolver\\\\GenericRule constructor expects array\\{package\\: Composer\\\\Package\\\\BasePackage\\}\\|array\\{packageName\\: string, constraint\\: Composer\\\\Semver\\\\Constraint\\\\ConstraintInterface\\}\\|Composer\\\\Package\\\\BasePackage\\|Composer\\\\Package\\\\Link\\|int\\|string, array\\{package\\: Composer\\\\Package\\\\BasePackage\\}\\|array\\{packageName\\: string, constraint\\: Composer\\\\Semver\\\\Constraint\\\\ConstraintInterface\\}\\|Composer\\\\Package\\\\BasePackage\\|Composer\\\\Package\\\\Link\\|int\\|string\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSetGenerator.php - - - - message: "#^Parameter \\#4 \\$reasonData of class Composer\\\\DependencyResolver\\\\Rule2Literals constructor expects array\\{package\\: Composer\\\\Package\\\\BasePackage\\}\\|array\\{packageName\\: string, constraint\\: Composer\\\\Semver\\\\Constraint\\\\ConstraintInterface\\}\\|Composer\\\\Package\\\\BasePackage\\|Composer\\\\Package\\\\Link\\|int\\|string, array\\{package\\: Composer\\\\Package\\\\BasePackage\\}\\|array\\{packageName\\: string, constraint\\: Composer\\\\Semver\\\\Constraint\\\\ConstraintInterface\\}\\|Composer\\\\Package\\\\BasePackage\\|Composer\\\\Package\\\\Link\\|int\\|string\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSetGenerator.php - - - - message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSetGenerator.php - - - - message: "#^Return type \\(\\-1\\|0\\|1\\|4\\) of method Composer\\\\DependencyResolver\\\\RuleSetIterator\\:\\:key\\(\\) should be covariant with return type \\(0\\|1\\|4\\) of method Iterator\\\\:\\:key\\(\\)$#" - count: 1 - path: ../src/Composer/DependencyResolver/RuleSetIterator.php - - - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Foreach overwrites \\$literal with its value variable\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in &&, Composer\\\\DependencyResolver\\\\Rule\\|null given on the left side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in &&, int\\<0, max\\> given on the right side\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in &&, mixed given on the left side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in a negated boolean, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in a negated boolean, int given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in an if condition, Composer\\\\DependencyResolver\\\\Rule\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in an if condition, int given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in an if condition, int\\<0, max\\> given\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Only booleans are allowed in an if condition, mixed given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Parameter \\#1 \\$literal of method Composer\\\\DependencyResolver\\\\Decisions\\:\\:decide\\(\\) expects int, int\\|string given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Parameter \\#1 \\$literals of class Composer\\\\DependencyResolver\\\\GenericRule constructor expects list\\, non\\-empty\\-list\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Parameter \\#1 \\$number of function abs expects int, int\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Parameter \\#1 \\$rule of method Composer\\\\DependencyResolver\\\\Problem\\:\\:addRule\\(\\) expects Composer\\\\DependencyResolver\\\\Rule, Composer\\\\DependencyResolver\\\\Rule\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Parameter \\#2 \\$literal of method Composer\\\\DependencyResolver\\\\Solver\\:\\:setPropagateLearn\\(\\) expects int\\|string, int\\|null given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Parameter \\#2 \\$presentMap of class Composer\\\\DependencyResolver\\\\LockTransaction constructor expects array\\, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Short ternary operator is not allowed\\. Use null coalesce operator if applicable or consider using long ternary\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Solver.php - - - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/SolverProblemsException.php - - - - message: "#^Only booleans are allowed in &&, int\\<0, max\\>\\|false given on the left side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/SolverProblemsException.php - - - - message: "#^Only booleans are allowed in &&, int\\<0, max\\>\\|false given on the right side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/SolverProblemsException.php - - - - message: "#^Only booleans are allowed in an if condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/SolverProblemsException.php - - - - message: "#^Only booleans are allowed in an if condition, int\\<0, max\\>\\|false given\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/SolverProblemsException.php - - - - message: "#^Only booleans are allowed in \\|\\|, int\\<0, max\\>\\|false given on the left side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/SolverProblemsException.php - - - - message: "#^Only booleans are allowed in \\|\\|, int\\<0, max\\>\\|false given on the right side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/SolverProblemsException.php - - - - message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Transaction.php - - - - message: "#^Only booleans are allowed in &&, array given on the right side\\.$#" - count: 1 - path: ../src/Composer/DependencyResolver/Transaction.php - - - - message: "#^Only booleans are allowed in a negated boolean, int\\<0, max\\> given\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Transaction.php - - - - message: "#^Only booleans are allowed in \\|\\|, int\\<0, max\\> given on the right side\\.$#" - count: 2 - path: ../src/Composer/DependencyResolver/Transaction.php - - message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#" count: 1 @@ -2857,7 +2442,7 @@ parameters: - message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#" - count: 2 + count: 1 path: ../src/Composer/Repository/ComposerRepository.php - diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index b7b957057..14c9a4c32 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -817,7 +817,8 @@ EOT $pool = $repositorySet->createPoolForPackage($name); } $matches = $pool->whatProvides($name, $constraint); - foreach ($matches as $index => $package) { + $literals = []; + foreach ($matches as $package) { // avoid showing the 9999999-dev alias if the default branch has no branch-alias set if ($package instanceof AliasPackage && $package->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { $package = $package->getAliasOf(); @@ -829,11 +830,12 @@ EOT } $versions[$package->getPrettyVersion()] = $package->getVersion(); - $matches[$index] = $package->getId(); + $literals[] = $package->getId(); } // select preferred package according to policy rules - if (null === $matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, $matches)) { + if (null === $matchedPackage && \count($literals) > 0) { + $preferred = $policy->selectPreferredPackages($pool, $literals); $matchedPackage = $pool->literalToPackage($preferred[0]); } diff --git a/src/Composer/DependencyResolver/Decisions.php b/src/Composer/DependencyResolver/Decisions.php index 9a5c9c235..599110750 100644 --- a/src/Composer/DependencyResolver/Decisions.php +++ b/src/Composer/DependencyResolver/Decisions.php @@ -28,7 +28,7 @@ class Decisions implements \Iterator, \Countable /** @var array */ protected $decisionMap; /** - * @var array + * @var array */ protected $decisionQueue = []; @@ -69,12 +69,12 @@ class Decisions implements \Iterator, \Countable public function decided(int $literalOrPackageId): bool { - return !empty($this->decisionMap[abs($literalOrPackageId)]); + return ($this->decisionMap[abs($literalOrPackageId)] ?? 0) !== 0; } public function undecided(int $literalOrPackageId): bool { - return empty($this->decisionMap[abs($literalOrPackageId)]); + return ($this->decisionMap[abs($literalOrPackageId)] ?? 0) === 0; } public function decidedInstall(int $literalOrPackageId): bool @@ -94,7 +94,7 @@ class Decisions implements \Iterator, \Countable return 0; } - public function decisionRule(int $literalOrPackageId): ?Rule + public function decisionRule(int $literalOrPackageId): Rule { $packageId = abs($literalOrPackageId); @@ -104,7 +104,7 @@ class Decisions implements \Iterator, \Countable } } - return null; + throw new \LogicException('Did not find a decision rule using '.$literalOrPackageId); } /** @@ -219,7 +219,7 @@ class Decisions implements \Iterator, \Countable ksort($decisionMap); $str = '['; foreach ($decisionMap as $packageId => $level) { - $str .= (($pool) ? $pool->literalToPackage($packageId) : $packageId).':'.$level.','; + $str .= ($pool !== null ? $pool->literalToPackage($packageId) : $packageId).':'.$level.','; } $str .= ']'; diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index 2635de9ae..590187026 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -30,7 +30,7 @@ class DefaultPolicy implements PolicyInterface private $preferLowest; /** @var array|null */ private $preferredVersions; - /** @var array>> */ + /** @var array>> */ private $preferredPackageResultCachePerPool; /** @var array> */ private $sortingCachePerPool; @@ -68,9 +68,8 @@ class DefaultPolicy implements PolicyInterface } /** - * @param int[] $literals - * @param string $requiredPackage - * @return int[] + * @param non-empty-list $literals + * @return non-empty-list */ public function selectPreferredPackages(Pool $pool, array $literals, ?string $requiredPackage = null): array { @@ -118,8 +117,8 @@ class DefaultPolicy implements PolicyInterface } /** - * @param int[] $literals - * @return array + * @param non-empty-list $literals + * @return non-empty-array> */ protected function groupLiteralsByName(Pool $pool, array $literals): array { @@ -164,7 +163,7 @@ class DefaultPolicy implements PolicyInterface // for replacers not replacing each other, put a higher prio on replacing // packages with the same vendor as the required package - if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) { + if ($requiredPackage !== null && false !== ($pos = strpos($requiredPackage, '/'))) { $requiredVendor = substr($requiredPackage, 0, $pos); $aIsSameVendor = strpos($a->getName(), $requiredVendor) === 0; @@ -205,8 +204,8 @@ class DefaultPolicy implements PolicyInterface } /** - * @param int[] $literals - * @return int[] + * @param list $literals + * @return list */ protected function pruneToBestVersion(Pool $pool, array $literals): array { @@ -252,8 +251,8 @@ class DefaultPolicy implements PolicyInterface * * If no package is a local alias, nothing happens * - * @param int[] $literals - * @return int[] + * @param list $literals + * @return list */ protected function pruneRemoteAliases(Pool $pool, array $literals): array { diff --git a/src/Composer/DependencyResolver/GenericRule.php b/src/Composer/DependencyResolver/GenericRule.php index c4b2f981a..64dd7a215 100644 --- a/src/Composer/DependencyResolver/GenericRule.php +++ b/src/Composer/DependencyResolver/GenericRule.php @@ -47,6 +47,9 @@ class GenericRule extends Rule public function getHash() { $data = unpack('ihash', (string) hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', implode(',', $this->literals), true)); + if (false === $data) { + throw new \RuntimeException('Failed unpacking: '.implode(', ', $this->literals)); + } return $data['hash']; } diff --git a/src/Composer/DependencyResolver/MultiConflictRule.php b/src/Composer/DependencyResolver/MultiConflictRule.php index 05fedc207..a61094755 100644 --- a/src/Composer/DependencyResolver/MultiConflictRule.php +++ b/src/Composer/DependencyResolver/MultiConflictRule.php @@ -19,11 +19,11 @@ namespace Composer\DependencyResolver; */ class MultiConflictRule extends Rule { - /** @var list */ + /** @var non-empty-list */ protected $literals; /** - * @param list $literals + * @param non-empty-list $literals */ public function __construct(array $literals, $reason, $reasonData) { @@ -40,7 +40,7 @@ class MultiConflictRule extends Rule } /** - * @return list + * @return non-empty-list */ public function getLiterals(): array { @@ -53,6 +53,9 @@ class MultiConflictRule extends Rule public function getHash() { $data = unpack('ihash', (string) hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', 'c:'.implode(',', $this->literals), true)); + if (false === $data) { + throw new \RuntimeException('Failed unpacking: '.implode(', ', $this->literals)); + } return $data['hash']; } diff --git a/src/Composer/DependencyResolver/PolicyInterface.php b/src/Composer/DependencyResolver/PolicyInterface.php index 928e7e0a9..b4511d091 100644 --- a/src/Composer/DependencyResolver/PolicyInterface.php +++ b/src/Composer/DependencyResolver/PolicyInterface.php @@ -26,8 +26,8 @@ interface PolicyInterface public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator): bool; /** - * @param int[] $literals - * @return int[] + * @param non-empty-list $literals + * @return non-empty-list */ public function selectPreferredPackages(Pool $pool, array $literals, ?string $requiredPackage = null): array; } diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index d3fbc521f..241acf97b 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -95,7 +95,7 @@ class PoolBuilder */ private $loadedPerRepo = []; /** - * @var BasePackage[] + * @var array */ private $packages = []; /** @@ -201,10 +201,14 @@ class PoolBuilder { $this->restrictedPackagesList = $request->getRestrictedPackages() !== null ? array_flip($request->getRestrictedPackages()) : null; - if ($request->getUpdateAllowList()) { + if (\count($request->getUpdateAllowList()) > 0) { $this->updateAllowList = $request->getUpdateAllowList(); $this->warnAboutNonMatchingUpdateAllowList($request); + if (null === $request->getLockedRepository()) { + throw new \LogicException('No lock repo present and yet a partial update was requested.'); + } + foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) { if (!$this->isUpdateAllowed($lockedPackage)) { // remember which packages we skipped loading remote content for in this partial update @@ -271,7 +275,7 @@ class PoolBuilder } } - while (!empty($this->packagesToLoad)) { + while (\count($this->packagesToLoad) > 0) { $this->loadPackagesMarkedForLoading($request, $repositories); } @@ -303,7 +307,7 @@ class PoolBuilder } } - if ($this->eventDispatcher) { + if ($this->eventDispatcher !== null) { $prePoolCreateEvent = new PrePoolCreateEvent( PluginEvents::PRE_POOL_CREATE, $repositories, @@ -413,7 +417,7 @@ class PoolBuilder $this->packagesToLoad = []; foreach ($repositories as $repoIndex => $repository) { - if (empty($packageBatch)) { + if (0 === \count($packageBatch)) { break; } @@ -499,7 +503,7 @@ class PoolBuilder if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) { $skippedRootRequires = $this->getSkippedRootRequires($request, $require); - if ($request->getUpdateAllowTransitiveRootDependencies() || !$skippedRootRequires) { + if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) { $this->unlockPackage($request, $repositories, $require); $this->markPackageNameForLoading($request, $require, $linkConstraint); } else { @@ -528,7 +532,7 @@ class PoolBuilder if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) { $skippedRootRequires = $this->getSkippedRootRequires($request, $replace); - if ($request->getUpdateAllowTransitiveRootDependencies() || !$skippedRootRequires) { + if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) { $this->unlockPackage($request, $repositories, $replace); // the replaced package only needs to be loaded if something else requires it $this->markPackageNameForLoadingIfRequired($request, $replace); @@ -615,6 +619,10 @@ class PoolBuilder private function warnAboutNonMatchingUpdateAllowList(Request $request): void { + if (null === $request->getLockedRepository()) { + throw new \LogicException('No lock repo present and yet a partial update was requested.'); + } + foreach ($this->updateAllowList as $pattern) { $matchedPlatformPackage = false; diff --git a/src/Composer/DependencyResolver/PoolOptimizer.php b/src/Composer/DependencyResolver/PoolOptimizer.php index c53891fb6..3de9e037b 100644 --- a/src/Composer/DependencyResolver/PoolOptimizer.php +++ b/src/Composer/DependencyResolver/PoolOptimizer.php @@ -207,7 +207,7 @@ class PoolOptimizer $groupHashParts[] = 'require:' . (string) $requireConstraint; } - if ($package->getReplaces()) { + if (\count($package->getReplaces()) > 0) { foreach ($package->getReplaces() as $link) { if (CompilingMatcher::match($link->getConstraint(), Constraint::OP_EQ, $package->getVersion())) { // Use the same hash part as the regular require hash because that's what the replacement does @@ -224,7 +224,7 @@ class PoolOptimizer } } - if (!$groupHashParts) { + if (0 === \count($groupHashParts)) { continue; } @@ -371,7 +371,7 @@ class PoolOptimizer */ private function optimizeImpossiblePackagesAway(Request $request, Pool $pool): void { - if (count($request->getLockedPackages()) === 0) { + if (\count($request->getLockedPackages()) === 0) { return; } diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index c54fab1af..5576845e9 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -80,7 +80,7 @@ class Problem // TODO doesn't this entirely defeat the purpose of the problem sections? what's the point of sections? $reasons = array_merge(...array_reverse($this->reasons)); - if (count($reasons) === 1) { + if (\count($reasons) === 1) { reset($reasons); $rule = current($reasons); @@ -93,7 +93,7 @@ class Problem $constraint = $reasonData['constraint']; $packages = $pool->whatProvides($packageName, $constraint); - if (count($packages) === 0) { + if (\count($packages) === 0) { return "\n ".implode(self::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $packageName, $constraint)); } } @@ -188,7 +188,7 @@ class Problem if (!$isVerbose) { $versions = self::condenseVersionList($versions, 1); } - if (count($versions) > 1) { + if (\count($versions) > 1) { // remove the s from requires/conflicts to correct grammar $message = Preg::replace('{^(%s%s (?:require|conflict))s}', '$1', $message); $result[] = sprintf($message, $package, '['.implode(', ', $versions).']'); @@ -276,7 +276,7 @@ class Problem $ext = substr($packageName, 4); $msg = "- Root composer.json requires PHP extension ".$packageName.self::constraintToText($constraint).' but '; - $version = self::getPlatformPackageVersion($pool, $packageName, phpversion($ext) ?: '0'); + $version = self::getPlatformPackageVersion($pool, $packageName, phpversion($ext) === false ? '0' : phpversion($ext)); if (null === $version) { $providersStr = self::getProvidersList($repositorySet, $packageName, 5); if ($providersStr !== null) { @@ -337,7 +337,8 @@ class Problem // first check if the actual requested package is found in normal conditions // if so it must mean it is rejected by another constraint than the one given here - if ($packages = $repositorySet->findPackages($packageName, $constraint)) { + $packages = $repositorySet->findPackages($packageName, $constraint); + if (\count($packages) > 0) { $rootReqs = $repositorySet->getRootRequires(); if (isset($rootReqs[$packageName])) { $filtered = array_filter($packages, static function ($p) use ($rootReqs, $packageName): bool { @@ -358,7 +359,7 @@ class Problem } } - if ($lockedPackage) { + if ($lockedPackage !== null) { $fixedConstraint = new Constraint('==', $lockedPackage->getVersion()); $filtered = array_filter($packages, static function ($p) use ($fixedConstraint): bool { return $fixedConstraint->matches(new Constraint('==', $p->getVersion())); @@ -372,7 +373,7 @@ class Problem return !$p->getRepository() instanceof LockArrayRepository; }); - if (!$nonLockedPackages) { + if (0 === \count($nonLockedPackages)) { return ["- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose, $pool, $constraint).' in the lock file but not in remote repositories, make sure you avoid updating this package to keep the one from the lock file.']; } @@ -380,9 +381,11 @@ class Problem } // check if the package is found when bypassing stability checks - if ($packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) { + $packages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES); + if (\count($packages) > 0) { // we must first verify if a valid package would be found in a lower priority repository - if ($allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) { + $allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES); + if (\count($allReposPackages) > 0) { return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'minimum-stability', $constraint); } @@ -390,9 +393,11 @@ class Problem } // check if the package is found when bypassing the constraint and stability checks - if ($packages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES)) { + $packages = $repositorySet->findPackages($packageName, null, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES); + if (\count($packages) > 0) { // we must first verify if a valid package would be found in a lower priority repository - if ($allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES)) { + $allReposPackages = $repositorySet->findPackages($packageName, $constraint, RepositorySet::ALLOW_SHADOWED_REPOSITORIES); + if (\count($allReposPackages) > 0) { return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'constraint', $constraint); } @@ -441,12 +446,12 @@ class Problem foreach ($packages as $package) { $prepared[$package->getName()]['name'] = $package->getPrettyName(); $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion().($package instanceof AliasPackage ? ' (alias of '.$package->getAliasOf()->getPrettyVersion().')' : ''); - if ($pool && $constraint) { + if ($pool !== null && $constraint !== null) { foreach ($pool->getRemovedVersions($package->getName(), $constraint) as $version => $prettyVersion) { $prepared[$package->getName()]['versions'][$version] = $prettyVersion; } } - if ($pool && $useRemovedVersionGroup) { + if ($pool !== null && $useRemovedVersionGroup) { foreach ($pool->getRemovedVersionsByPackage(spl_object_hash($package)) as $version => $prettyVersion) { $prepared[$package->getName()]['versions'][$version] = $prettyVersion; } @@ -482,7 +487,7 @@ class Problem { $available = $pool->whatProvides($packageName); - if (count($available)) { + if (\count($available) > 0) { $selected = null; foreach ($available as $pkg) { if ($pkg->getRepository() instanceof PlatformRepository) { @@ -507,7 +512,7 @@ class Problem $version = $selected->getPrettyVersion(); $extra = $selected->getExtra(); if ($selected instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) { - $version .= '; ' . str_replace('Package ', '', $selected->getDescription()); + $version .= '; ' . str_replace('Package ', '', (string) $selected->getDescription()); } } else { return null; @@ -568,8 +573,8 @@ class Problem } /** - * @param PackageInterface[] $higherRepoPackages - * @param PackageInterface[] $allReposPackages + * @param non-empty-array $higherRepoPackages + * @param non-empty-array $allReposPackages * @return array{0: string, 1: string} */ private static function computeCheckForLowerPrioRepo(Pool $pool, bool $isVerbose, string $packageName, array $higherRepoPackages, array $allReposPackages, string $reason, ?ConstraintInterface $constraint = null): array @@ -586,7 +591,9 @@ class Problem } } - if ($higherRepoPackages) { + assert(null !== $nextRepo); + + if (\count($higherRepoPackages) > 0) { $topPackage = reset($higherRepoPackages); if ($topPackage instanceof RootPackageInterface) { return [ @@ -634,7 +641,7 @@ class Problem return ' ' . $constraint->getPrettyString() . ' (exact version match: ' . (count($versions) > 1 ? implode(', ', array_slice($versions, 0, -1)) . ' or ' . end($versions) : $versions[0]) . ')'; } - return $constraint ? ' '.$constraint->getPrettyString() : ''; + return $constraint !== null ? ' '.$constraint->getPrettyString() : ''; } private static function getProvidersList(RepositorySet $repositorySet, string $packageName, int $maxProviders): ?string @@ -642,7 +649,7 @@ class Problem $providers = $repositorySet->getProviders($packageName); if (\count($providers) > 0) { $providersStr = implode(array_map(static function ($p): string { - $description = $p['description'] ? ' '.substr($p['description'], 0, 100) : ''; + $description = $p['description'] !== '' ? ' '.substr($p['description'], 0, 100) : ''; return ' - '.$p['name'].$description."\n"; }, count($providers) > $maxProviders + 1 ? array_slice($providers, 0, $maxProviders) : $providers)); diff --git a/src/Composer/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index 300093f04..b11f4e1f2 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -190,7 +190,7 @@ class Request } /** - * @return array + * @return ($packageIds is true ? array : array) * * @TODO look into removing the packageIds option, the only place true is used * is for the installed map in the solver problems. @@ -201,7 +201,7 @@ class Request { $presentMap = []; - if ($this->lockedRepository) { + if ($this->lockedRepository !== null) { foreach ($this->lockedRepository->getPackages() as $package) { $presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package; } @@ -215,7 +215,7 @@ class Request } /** - * @return BasePackage[] + * @return array */ public function getFixedPackagesMap(): array { diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index d65164154..8dde02b37 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -153,7 +153,7 @@ abstract class Rule if (PlatformRepository::isPlatformPackage($this->getReasonData()->getTarget())) { return false; } - if ($request->getLockedRepository()) { + if ($request->getLockedRepository() !== null) { foreach ($request->getLockedRepository()->getPackages() as $package) { if ($package->getName() === $this->getReasonData()->getTarget()) { if ($pool->isUnacceptableFixedOrLockedPackage($package)) { @@ -176,7 +176,7 @@ abstract class Rule if (PlatformRepository::isPlatformPackage($this->getReasonData()['packageName'])) { return false; } - if ($request->getLockedRepository()) { + if ($request->getLockedRepository() !== null) { foreach ($request->getLockedRepository()->getPackages() as $package) { if ($package->getName() === $this->getReasonData()['packageName']) { if ($pool->isUnacceptableFixedOrLockedPackage($package)) { @@ -215,7 +215,7 @@ abstract class Rule return $package2; case self::RULE_PACKAGE_REQUIRES: - $sourceLiteral = array_shift($literals); + $sourceLiteral = $literals[0]; $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral)); return $sourcePackage; @@ -240,14 +240,14 @@ abstract class Rule $constraint = $reasonData['constraint']; $packages = $pool->whatProvides($packageName, $constraint); - if (!$packages) { + if (0 === \count($packages)) { return 'No package found to satisfy root composer.json require '.$packageName.' '.$constraint->getPrettyString(); } $packagesNonAlias = array_values(array_filter($packages, static function ($p): bool { return !($p instanceof AliasPackage); })); - if (count($packagesNonAlias) === 1) { + if (\count($packagesNonAlias) === 1) { $package = $packagesNonAlias[0]; if ($request->isLockedPackage($package)) { return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion()." and an update of this package was not requested."; @@ -305,6 +305,7 @@ abstract class Rule return $package2->getPrettyString().' conflicts with '.$conflictTarget.'.'; case self::RULE_PACKAGE_REQUIRES: + assert(\count($literals) > 0); $sourceLiteral = array_shift($literals); $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral)); $reasonData = $this->getReasonData(); @@ -315,7 +316,7 @@ abstract class Rule } $text = $reasonData->getPrettyString($sourcePackage); - if ($requires) { + if (\count($requires) > 0) { $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose, $reasonData->getConstraint()) . '.'; } else { $targetName = $reasonData->getTarget(); @@ -333,19 +334,18 @@ abstract class Rule $package = $pool->literalToPackage($literal); $packageNames[$package->getName()] = true; } + unset($literal); $replacedName = $this->getReasonData(); - if (count($packageNames) > 1) { - $reason = null; - + if (\count($packageNames) > 1) { if (!isset($packageNames[$replacedName])) { - $reason = 'They '.(count($literals) === 2 ? 'both' : 'all').' replace '.$replacedName.' and thus cannot coexist.'; + $reason = 'They '.(\count($literals) === 2 ? 'both' : 'all').' replace '.$replacedName.' and thus cannot coexist.'; } else { $replacerNames = $packageNames; unset($replacerNames[$replacedName]); $replacerNames = array_keys($replacerNames); - if (count($replacerNames) === 1) { + if (\count($replacerNames) === 1) { $reason = $replacerNames[0] . ' replaces '; } else { $reason = '['.implode(', ', $replacerNames).'] replace '; @@ -363,7 +363,7 @@ abstract class Rule } } - if ($installedPackages && $removablePackages) { + if (\count($installedPackages) > 0 && \count($removablePackages) > 0) { return $this->formatPackagesUnique($pool, $removablePackages, $isVerbose, null, true).' cannot be installed as that would require removing '.$this->formatPackagesUnique($pool, $installedPackages, $isVerbose, null, true).'. '.$reason; } @@ -381,7 +381,7 @@ abstract class Rule // } $learnedString = ' (conflict analysis result)'; - if (count($literals) === 1) { + if (\count($literals) === 1) { $ruleText = $pool->literalToPrettyString($literals[0], $installedMap); } else { $groups = []; @@ -397,7 +397,7 @@ abstract class Rule } $ruleTexts = []; foreach ($groups as $group => $packages) { - $ruleTexts[] = $group . (count($packages) > 1 ? ' one of' : '').' ' . $this->formatPackagesUnique($pool, $packages, $isVerbose); + $ruleTexts[] = $group . (\count($packages) > 1 ? ' one of' : '').' ' . $this->formatPackagesUnique($pool, $packages, $isVerbose); } $ruleText = implode(' | ', $ruleTexts); @@ -439,14 +439,13 @@ abstract class Rule } /** - * @param array $packages An array containing packages or literals + * @param array $literalsOrPackages An array containing packages or literals */ - protected function formatPackagesUnique(Pool $pool, array $packages, bool $isVerbose, ?ConstraintInterface $constraint = null, bool $useRemovedVersionGroup = false): string + protected function formatPackagesUnique(Pool $pool, array $literalsOrPackages, bool $isVerbose, ?ConstraintInterface $constraint = null, bool $useRemovedVersionGroup = false): string { - foreach ($packages as $index => $package) { - if (!\is_object($package)) { - $packages[$index] = $pool->literalToPackage($package); - } + $packages = []; + foreach ($literalsOrPackages as $package) { + $packages[] = \is_object($package) ? $package : $pool->literalToPackage($package); } return Problem::getPackageList($packages, $isVerbose, $pool, $constraint, $useRemovedVersionGroup); diff --git a/src/Composer/DependencyResolver/Rule2Literals.php b/src/Composer/DependencyResolver/Rule2Literals.php index 17bfaf8ce..33d0ed0be 100644 --- a/src/Composer/DependencyResolver/Rule2Literals.php +++ b/src/Composer/DependencyResolver/Rule2Literals.php @@ -43,7 +43,7 @@ class Rule2Literals extends Rule } /** - * @return list + * @return non-empty-list */ public function getLiterals(): array { diff --git a/src/Composer/DependencyResolver/RuleSet.php b/src/Composer/DependencyResolver/RuleSet.php index 4a406238a..cca9eb123 100644 --- a/src/Composer/DependencyResolver/RuleSet.php +++ b/src/Composer/DependencyResolver/RuleSet.php @@ -179,7 +179,7 @@ class RuleSet implements \IteratorAggregate, \Countable foreach ($this->rules as $type => $rules) { $string .= str_pad(self::TYPES[$type], 8, ' ') . ": "; foreach ($rules as $rule) { - $string .= ($repositorySet && $request && $pool ? $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose) : $rule)."\n"; + $string .= ($repositorySet !== null && $request !== null && $pool !== null ? $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose) : $rule)."\n"; } $string .= "\n\n"; } diff --git a/src/Composer/DependencyResolver/RuleSetGenerator.php b/src/Composer/DependencyResolver/RuleSetGenerator.php index 69d119134..08c874ff7 100644 --- a/src/Composer/DependencyResolver/RuleSetGenerator.php +++ b/src/Composer/DependencyResolver/RuleSetGenerator.php @@ -56,7 +56,7 @@ class RuleSetGenerator * * @phpstan-param ReasonData $reasonData */ - protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData = null): ?Rule + protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData): ?Rule { $literals = [-$package->id]; @@ -77,7 +77,7 @@ class RuleSetGenerator * The rule is (A|B|C) with A, B and C different packages. If the given * set of packages is empty an impossible rule is generated. * - * @param BasePackage[] $packages The set of packages to choose from + * @param non-empty-array $packages The set of packages to choose from * @param Rule::RULE_* $reason A RULE_* constant describing the reason for * generating this rule * @param mixed $reasonData Additional data like the root require or fix request info @@ -109,7 +109,7 @@ class RuleSetGenerator * * @phpstan-param ReasonData $reasonData */ - protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData = null): ?Rule + protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData): ?Rule { // ignore self conflict if ($issuer === $provider) { @@ -120,7 +120,7 @@ class RuleSetGenerator } /** - * @param BasePackage[] $packages + * @param non-empty-array $packages * @param Rule::RULE_* $reason A RULE_* constant * @param mixed $reasonData * @@ -151,7 +151,7 @@ class RuleSetGenerator */ private function addRule($type, ?Rule $newRule = null): void { - if (!$newRule) { + if (null === $newRule) { return; } @@ -276,7 +276,7 @@ class RuleSetGenerator } $packages = $this->pool->whatProvides($packageName, $constraint); - if ($packages) { + if (\count($packages) > 0) { foreach ($packages as $package) { $this->addRulesForPackage($package, $platformRequirementFilter); } @@ -307,7 +307,7 @@ class RuleSetGenerator public function getRulesFor(Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): RuleSet { - $platformRequirementFilter = $platformRequirementFilter ?: PlatformRequirementFilterFactory::ignoreNothing(); + $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing(); $this->addRulesForRequest($request, $platformRequirementFilter); diff --git a/src/Composer/DependencyResolver/RuleSetIterator.php b/src/Composer/DependencyResolver/RuleSetIterator.php index 2bf67f55b..3b8383d47 100644 --- a/src/Composer/DependencyResolver/RuleSetIterator.php +++ b/src/Composer/DependencyResolver/RuleSetIterator.php @@ -14,7 +14,7 @@ namespace Composer\DependencyResolver; /** * @author Nils Adermann - * @implements \Iterator + * @implements \Iterator */ class RuleSetIterator implements \Iterator { diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 373e8325d..b8aa847d1 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -43,7 +43,7 @@ class Solver /** @var int */ protected $propagateIndex; - /** @var mixed[] */ + /** @var array, int}> */ protected $branches = []; /** @var Problem[] */ protected $problems = []; @@ -109,7 +109,7 @@ class Solver $conflict = $this->decisions->decisionRule($literal); - if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) { + if (RuleSet::TYPE_PACKAGE === $conflict->getType()) { $problem = new Problem(); $problem->addRule($rule); @@ -164,7 +164,7 @@ class Solver $constraint = $platformRequirementFilter->filterConstraint($packageName, $constraint); } - if (!$this->pool->whatProvides($packageName, $constraint)) { + if (0 === \count($this->pool->whatProvides($packageName, $constraint))) { $problem = new Problem(); $problem->addRule(new GenericRule([], Rule::RULE_ROOT_REQUIRE, ['packageName' => $packageName, 'constraint' => $constraint])); $this->problems[] = $problem; @@ -174,7 +174,7 @@ class Solver public function solve(Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): LockTransaction { - $platformRequirementFilter = $platformRequirementFilter ?: PlatformRequirementFilterFactory::ignoreNothing(); + $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing(); $this->setupFixedMap($request); @@ -199,7 +199,7 @@ class Solver $this->io->writeError('', true, IOInterface::DEBUG); $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE); - if ($this->problems) { + if (\count($this->problems) > 0) { throw new SolverProblemsException($this->problems, $this->learnedPool); } @@ -227,7 +227,7 @@ class Solver $this->propagateIndex++; - if ($conflict) { + if ($conflict !== null) { return $conflict; } } @@ -257,7 +257,7 @@ class Solver $this->propagateIndex = \count($this->decisions); } - while (!empty($this->branches) && $this->branches[\count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) { + while (\count($this->branches) > 0 && $this->branches[\count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) { array_pop($this->branches); } } @@ -274,10 +274,8 @@ class Solver * rule (always unit) and re-propagate. * * returns the new solver level or 0 if unsolvable - * - * @param string|int $literal */ - private function setPropagateLearn(int $level, $literal, Rule $rule): int + private function setPropagateLearn(int $level, int $literal, Rule $rule): int { $level++; @@ -291,7 +289,9 @@ class Solver } if ($level === 1) { - return $this->analyzeUnsolvable($rule); + $this->analyzeUnsolvable($rule); + + return 0; } // conflict @@ -322,7 +322,7 @@ class Solver } /** - * @param int[] $decisionQueue + * @param non-empty-list $decisionQueue */ private function selectAndInstall(int $level, array $decisionQueue, Rule $rule): int { @@ -332,7 +332,7 @@ class Solver $selectedLiteral = array_shift($literals); // if there are multiple candidates, then branch - if (\count($literals)) { + if (\count($literals) > 0) { $this->branches[] = [$literals, $level]; } @@ -349,7 +349,8 @@ class Solver $num = 0; $l1num = 0; $seen = []; - $learnedLiterals = [null]; + $learnedLiteral = null; + $otherLearnedLiterals = []; $decisionId = \count($this->decisions); @@ -382,7 +383,7 @@ class Solver $num++; } else { // not level1 or conflict level, add to new rule - $learnedLiterals[] = $literal; + $otherLearnedLiterals[] = $literal; if ($l > $ruleLevel) { $ruleLevel = $l; @@ -423,16 +424,14 @@ class Solver if ($literal < 0) { $this->testFlagLearnedPositiveLiteral = true; } - $learnedLiterals[0] = -$literal; + $learnedLiteral = -$literal; - if (!$l1num) { + if (0 === $l1num) { break 2; } - foreach ($learnedLiterals as $i => $learnedLiteral) { - if ($i !== 0) { - unset($seen[abs($learnedLiteral)]); - } + foreach ($otherLearnedLiterals as $otherLiteral) { + unset($seen[abs($otherLiteral)]); } // only level 1 marks left $l1num++; @@ -442,24 +441,24 @@ class Solver $rule = $decision[Decisions::DECISION_REASON]; if ($rule instanceof MultiConflictRule) { - // there is only ever exactly one positive decision in a multiconflict rule - foreach ($rule->getLiterals() as $literal) { - if (!isset($seen[abs($literal)]) && $this->decisions->satisfy(-$literal)) { + // there is only ever exactly one positive decision in a MultiConflictRule + foreach ($rule->getLiterals() as $ruleLiteral) { + if (!isset($seen[abs($ruleLiteral)]) && $this->decisions->satisfy(-$ruleLiteral)) { $this->learnedPool[\count($this->learnedPool) - 1][] = $rule; - $l = $this->decisions->decisionLevel($literal); + $l = $this->decisions->decisionLevel($ruleLiteral); if (1 === $l) { $l1num++; } elseif ($level === $l) { $num++; } else { // not level1 or conflict level, add to new rule - $learnedLiterals[] = $literal; + $otherLearnedLiterals[] = $ruleLiteral; if ($l > $ruleLevel) { $ruleLevel = $l; } } - $seen[abs($literal)] = true; + $seen[abs($ruleLiteral)] = true; break; } } @@ -475,15 +474,16 @@ class Solver $why = \count($this->learnedPool) - 1; - if (null === $learnedLiterals[0]) { + if (null === $learnedLiteral) { throw new SolverBugException( "Did not find a learnable literal in analyzed rule $analyzedRule." ); } - $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why); + array_unshift($otherLearnedLiterals, $learnedLiteral); + $newRule = new GenericRule($otherLearnedLiterals, Rule::RULE_LEARNED, $why); - return [$learnedLiterals[0], $ruleLevel, $newRule, $why]; + return [$learnedLiteral, $ruleLevel, $newRule, $why]; } /** @@ -516,7 +516,7 @@ class Solver $problem->addRule($conflictRule); } - private function analyzeUnsolvable(Rule $conflictRule): int + private function analyzeUnsolvable(Rule $conflictRule): void { $problem = new Problem(); $problem->addRule($conflictRule); @@ -539,10 +539,10 @@ class Solver } foreach ($this->decisions as $decision) { - $literal = $decision[Decisions::DECISION_LITERAL]; + $decisionLiteral = $decision[Decisions::DECISION_LITERAL]; // skip literals that are not in this rule - if (!isset($seen[abs($literal)])) { + if (!isset($seen[abs($decisionLiteral)])) { continue; } @@ -552,7 +552,6 @@ class Solver $this->analyzeUnsolvableRule($problem, $why, $ruleSeen); $literals = $why->getLiterals(); - foreach ($literals as $literal) { // skip the one true literal if ($this->decisions->satisfy($literal)) { @@ -561,8 +560,6 @@ class Solver $seen[abs($literal)] = true; } } - - return 0; } private function runSat(): void @@ -586,9 +583,7 @@ class Solver if (1 === $level) { $conflictRule = $this->propagate($level); if (null !== $conflictRule) { - if ($this->analyzeUnsolvable($conflictRule)) { - continue; - } + $this->analyzeUnsolvable($conflictRule); return; } @@ -612,7 +607,7 @@ class Solver } } - if ($noneSatisfied && \count($decisionQueue)) { + if ($noneSatisfied && \count($decisionQueue) > 0) { // if any of the options in the decision queue are fixed, only use those $prunedQueue = []; foreach ($decisionQueue as $literal) { @@ -620,12 +615,12 @@ class Solver $prunedQueue[] = $literal; } } - if (!empty($prunedQueue)) { + if (\count($prunedQueue) > 0) { $decisionQueue = $prunedQueue; } } - if ($noneSatisfied && \count($decisionQueue)) { + if ($noneSatisfied && \count($decisionQueue) > 0) { $oLevel = $level; $level = $this->selectAndInstall($level, $decisionQueue, $rule); @@ -719,7 +714,7 @@ class Solver } // minimization step - if (\count($this->branches)) { + if (\count($this->branches) > 0) { $lastLiteral = null; $lastLevel = null; $lastBranchIndex = 0; @@ -729,7 +724,7 @@ class Solver [$literals, $l] = $this->branches[$i]; foreach ($literals as $offset => $literal) { - if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) { + if ($literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) { $lastLiteral = $literal; $lastBranchIndex = $i; $lastBranchOffset = $offset; @@ -738,7 +733,8 @@ class Solver } } - if ($lastLiteral) { + if ($lastLiteral !== null) { + assert($lastLevel !== null); unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]); $level = $lastLevel; diff --git a/src/Composer/DependencyResolver/SolverProblemsException.php b/src/Composer/DependencyResolver/SolverProblemsException.php index 5870c0cae..bd76e4fa3 100644 --- a/src/Composer/DependencyResolver/SolverProblemsException.php +++ b/src/Composer/DependencyResolver/SolverProblemsException.php @@ -38,7 +38,7 @@ class SolverProblemsException extends \RuntimeException $this->problems = $problems; $this->learnedPool = $learnedPool; - parent::__construct('Failed resolving dependencies with '.count($problems).' problems, call getPrettyString to get formatted details', self::ERROR_DEPENDENCY_RESOLUTION_FAILED); + parent::__construct('Failed resolving dependencies with '.\count($problems).' problems, call getPrettyString to get formatted details', self::ERROR_DEPENDENCY_RESOLUTION_FAILED); } public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, bool $isVerbose, bool $isDevExtraction = false): string @@ -63,11 +63,11 @@ class SolverProblemsException extends \RuntimeException } $hints = []; - if (!$isDevExtraction && (strpos($text, 'could not be found') || strpos($text, 'no matching package found'))) { + if (!$isDevExtraction && (str_contains($text, 'could not be found') || str_contains($text, 'no matching package found'))) { $hints[] = "Potential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n see for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead for further common problems."; } - if (!empty($missingExtensions)) { + if (\count($missingExtensions) > 0) { $hints[] = $this->createExtensionHint($missingExtensions); } @@ -75,17 +75,17 @@ class SolverProblemsException extends \RuntimeException $hints[] = "Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions."; } - if (strpos($text, 'found composer-plugin-api[2.0.0] but it does not match') && strpos($text, '- ocramius/package-versions')) { + if (str_contains($text, 'found composer-plugin-api[2.0.0] but it does not match') && str_contains($text, '- ocramius/package-versions')) { $hints[] = "ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4.\nIf you can not upgrade PHP you can require composer/package-versions-deprecated to resolve this with PHP 7.0+."; } if (!class_exists('PHPUnit\Framework\TestCase', false)) { - if (strpos($text, 'found composer-plugin-api[2.0.0] but it does not match')) { + if (str_contains($text, 'found composer-plugin-api[2.0.0] but it does not match')) { $hints[] = "You are using Composer 2, which some of your plugins seem to be incompatible with. Make sure you update your plugins or report a plugin-issue to ask them to support Composer 2."; } } - if ($hints) { + if (\count($hints) > 0) { $text .= "\n" . implode("\n\n", $hints); } diff --git a/src/Composer/DependencyResolver/Transaction.php b/src/Composer/DependencyResolver/Transaction.php index ef6860c11..3443dd768 100644 --- a/src/Composer/DependencyResolver/Transaction.php +++ b/src/Composer/DependencyResolver/Transaction.php @@ -123,7 +123,7 @@ class Transaction $visited = []; $processed = []; - while (!empty($stack)) { + while (\count($stack) > 0) { $package = array_pop($stack); if (isset($processed[spl_object_hash($package)])) { @@ -283,17 +283,18 @@ class Transaction continue; } - $isDownloadsModifyingPlugin = $package->getType() === 'composer-plugin' && ($extra = $package->getExtra()) && isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === true; + $extra = $package->getExtra(); + $isDownloadsModifyingPlugin = $package->getType() === 'composer-plugin' && isset($extra['plugin-modifies-downloads']) && $extra['plugin-modifies-downloads'] === true; // is this a downloads modifying plugin or a dependency of one? - if ($isDownloadsModifyingPlugin || count(array_intersect($package->getNames(), $dlModifyingPluginRequires))) { + if ($isDownloadsModifyingPlugin || \count(array_intersect($package->getNames(), $dlModifyingPluginRequires)) > 0) { // get the package's requires, but filter out any platform requirements $requires = array_filter(array_keys($package->getRequires()), static function ($req): bool { return !PlatformRepository::isPlatformPackage($req); }); // is this a plugin with no meaningful dependencies? - if ($isDownloadsModifyingPlugin && !count($requires)) { + if ($isDownloadsModifyingPlugin && 0 === \count($requires)) { // plugins with no dependencies go to the very front array_unshift($dlModifyingPluginsNoDeps, $op); } else { @@ -311,14 +312,14 @@ class Transaction $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer'; // is this a plugin or a dependency of a plugin? - if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) { + if ($isPlugin || \count(array_intersect($package->getNames(), $pluginRequires)) > 0) { // get the package's requires, but filter out any platform requirements $requires = array_filter(array_keys($package->getRequires()), static function ($req): bool { return !PlatformRepository::isPlatformPackage($req); }); // is this a plugin with no meaningful dependencies? - if ($isPlugin && !count($requires)) { + if ($isPlugin && 0 === \count($requires)) { // plugins with no dependencies go to the very front array_unshift($pluginsNoDeps, $op); } else { diff --git a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php index 8cb366247..cfa86acf9 100644 --- a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php +++ b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php @@ -226,6 +226,7 @@ class DefaultPolicyTest extends TestCase $pool = $this->repositorySet->createPoolForPackage('A', $this->repoLocked); $packages = $pool->whatProvides('a', new Constraint('=', '2.1.9999999.9999999-dev')); + self::assertNotEmpty($packages); $literals = []; foreach ($packages as $package) { $literals[] = $package->getId();