1
0
Fork 0

Fix many PHPStan errors in DependencyResolver namespace (#12121)

pull/12129/head
Jordi Boggiano 2024-09-21 13:53:33 +02:00 committed by GitHub
parent 3a2a18175d
commit 6b81140f81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 179 additions and 575 deletions

26
composer.lock generated
View File

@ -305,24 +305,24 @@
}, },
{ {
"name": "composer/semver", "name": "composer/semver",
"version": "3.4.2", "version": "3.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/semver.git", "url": "https://github.com/composer/semver.git",
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^5.3.2 || ^7.0 || ^8.0" "php": "^5.3.2 || ^7.0 || ^8.0"
}, },
"require-dev": { "require-dev": {
"phpstan/phpstan": "^1.4", "phpstan/phpstan": "^1.11",
"symfony/phpunit-bridge": "^4.2 || ^5" "symfony/phpunit-bridge": "^3 || ^7"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@ -366,7 +366,7 @@
"support": { "support": {
"irc": "ircs://irc.libera.chat:6697/composer", "irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues", "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": [ "funding": [
{ {
@ -382,7 +382,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-07-12T11:35:52+00:00" "time": "2024-09-19T14:15:21+00:00"
}, },
{ {
"name": "composer/spdx-licenses", "name": "composer/spdx-licenses",
@ -2020,16 +2020,16 @@
"packages-dev": [ "packages-dev": [
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "1.12.3", "version": "1.12.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009" "reference": "ffa517cb918591b93acc9b95c0bebdcd0e4538bd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/0fcbf194ab63d8159bb70d9aa3e1350051632009", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/ffa517cb918591b93acc9b95c0bebdcd0e4538bd",
"reference": "0fcbf194ab63d8159bb70d9aa3e1350051632009", "reference": "ffa517cb918591b93acc9b95c0bebdcd0e4538bd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2074,7 +2074,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-09-09T08:10:35+00:00" "time": "2024-09-19T07:58:01+00:00"
}, },
{ {
"name": "phpstan/phpstan-deprecation-rules", "name": "phpstan/phpstan-deprecation-rules",

View File

@ -670,16 +670,6 @@ parameters:
count: 1 count: 1
path: ../src/Composer/Command/ShowCommand.php path: ../src/Composer/Command/ShowCommand.php
-
message: "#^Only booleans are allowed in &&, array\\<Composer\\\\Package\\\\BasePackage\\|int\\> given on the right side\\.$#"
count: 1
path: ../src/Composer/Command/ShowCommand.php
-
message: "#^Only booleans are allowed in &&, array\\<int\\> 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\\.$#" message: "#^Only booleans are allowed in &&, string given on the left side\\.$#"
count: 1 count: 1
@ -800,11 +790,6 @@ parameters:
count: 2 count: 2
path: ../src/Composer/Command/ShowCommand.php path: ../src/Composer/Command/ShowCommand.php
-
message: "#^Parameter \\#2 \\$literals of method Composer\\\\DependencyResolver\\\\DefaultPolicy\\:\\:selectPreferredPackages\\(\\) expects array\\<int\\>, array\\<Composer\\\\Package\\\\BasePackage\\|int\\> 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\\.$#" message: "#^Parameter \\#2 \\.\\.\\.\\$values of function sprintf expects bool\\|float\\|int\\|string\\|null, array\\|string given\\.$#"
count: 1 count: 1
@ -905,19 +890,9 @@ parameters:
count: 1 count: 1
path: ../src/Composer/Command/UpdateCommand.php 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\\.$#" message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 3 count: 2
path: ../src/Composer/Command/UpdateCommand.php
-
message: "#^Only booleans are allowed in a negated boolean, array\\<string\\> given\\.$#"
count: 1
path: ../src/Composer/Command/UpdateCommand.php path: ../src/Composer/Command/UpdateCommand.php
- -
@ -1095,96 +1070,11 @@ parameters:
count: 1 count: 1
path: ../src/Composer/Console/GithubActionError.php 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\\<mixed,array\\<int, Composer\\\\DependencyResolver\\\\Rule\\|int\\>\\>\\:\\:current\\(\\)$#" 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\\<mixed,array\\<int, Composer\\\\DependencyResolver\\\\Rule\\|int\\>\\>\\:\\:current\\(\\)$#"
count: 1 count: 1
path: ../src/Composer/DependencyResolver/Decisions.php 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\\<string\\> 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\\<string\\> 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\\<int, string\\> given\\.$#"
count: 1
path: ../src/Composer/DependencyResolver/PoolOptimizer.php
-
message: "#^Only booleans are allowed in an if condition, array\\<Composer\\\\Package\\\\Link\\> 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\\<string, Composer\\\\Package\\\\BasePackage\\|Composer\\\\Semver\\\\Constraint\\\\ConstraintInterface\\|string\\>\\|Composer\\\\Package\\\\BasePackage\\|Composer\\\\Package\\\\Link\\|int\\|string\\.$#" message: "#^Cannot call method getPrettyString\\(\\) on array\\<string, Composer\\\\Package\\\\BasePackage\\|Composer\\\\Semver\\\\Constraint\\\\ConstraintInterface\\|string\\>\\|Composer\\\\Package\\\\BasePackage\\|Composer\\\\Package\\\\Link\\|int\\|string\\.$#"
count: 1 count: 1
@ -1192,11 +1082,6 @@ parameters:
- -
message: "#^Cannot call method getRepoName\\(\\) on Composer\\\\Repository\\\\RepositoryInterface\\|null\\.$#" 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 count: 1
path: ../src/Composer/DependencyResolver/Problem.php path: ../src/Composer/DependencyResolver/Problem.php
@ -1205,311 +1090,11 @@ parameters:
count: 1 count: 1
path: ../src/Composer/DependencyResolver/Problem.php 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\\<Composer\\\\Package\\\\BasePackage\\> 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\\<Composer\\\\Package\\\\BasePackage\\> given\\.$#"
count: 5
path: ../src/Composer/DependencyResolver/Problem.php
-
message: "#^Only booleans are allowed in an if condition, array\\<Composer\\\\Package\\\\PackageInterface\\> given\\.$#"
count: 1
path: ../src/Composer/DependencyResolver/Problem.php
-
message: "#^Only booleans are allowed in an if condition, array\\<string, array\\<string, string\\>\\> 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\\>\\.$#" message: "#^Method Composer\\\\DependencyResolver\\\\Rule\\:\\:getReason\\(\\) should return 2\\|3\\|6\\|7\\|10\\|12\\|13\\|14 but returns int\\<0, 255\\>\\.$#"
count: 1 count: 1
path: ../src/Composer/DependencyResolver/Rule.php path: ../src/Composer/DependencyResolver/Rule.php
-
message: "#^Only booleans are allowed in &&, array\\<int, Composer\\\\Package\\\\BasePackage\\> given on the left side\\.$#"
count: 1
path: ../src/Composer/DependencyResolver/Rule.php
-
message: "#^Only booleans are allowed in &&, array\\<int, Composer\\\\Package\\\\BasePackage\\> given on the right side\\.$#"
count: 1
path: ../src/Composer/DependencyResolver/Rule.php
-
message: "#^Only booleans are allowed in a negated boolean, array\\<Composer\\\\Package\\\\BasePackage\\> 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\\<int, Composer\\\\Package\\\\BasePackage\\> 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\\<Composer\\\\Package\\\\PackageInterface\\>, array\\<Composer\\\\Package\\\\BasePackage\\|int\\> 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\\<Composer\\\\Package\\\\BasePackage\\> 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\\<int,Composer\\\\DependencyResolver\\\\Rule\\>\\:\\: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\\<Composer\\\\Package\\\\BasePackage\\> 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\\<Composer\\\\DependencyResolver\\\\Problem\\> 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\\<int\\>, non\\-empty\\-list\\<int\\|null\\> 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\\<string, Composer\\\\Package\\\\BasePackage\\>, array\\<int\\|string, Composer\\\\Package\\\\BasePackage\\> 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\\<int, string\\> 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\\.$#" message: "#^Call to function array_search\\(\\) requires parameter \\#3 to be set\\.$#"
count: 1 count: 1
@ -2857,7 +2442,7 @@ parameters:
- -
message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#" message: "#^Only booleans are allowed in a negated boolean, mixed given\\.$#"
count: 2 count: 1
path: ../src/Composer/Repository/ComposerRepository.php path: ../src/Composer/Repository/ComposerRepository.php
- -

View File

@ -817,7 +817,8 @@ EOT
$pool = $repositorySet->createPoolForPackage($name); $pool = $repositorySet->createPoolForPackage($name);
} }
$matches = $pool->whatProvides($name, $constraint); $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 // 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) { if ($package instanceof AliasPackage && $package->getVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) {
$package = $package->getAliasOf(); $package = $package->getAliasOf();
@ -829,11 +830,12 @@ EOT
} }
$versions[$package->getPrettyVersion()] = $package->getVersion(); $versions[$package->getPrettyVersion()] = $package->getVersion();
$matches[$index] = $package->getId(); $literals[] = $package->getId();
} }
// select preferred package according to policy rules // 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]); $matchedPackage = $pool->literalToPackage($preferred[0]);
} }

View File

@ -28,7 +28,7 @@ class Decisions implements \Iterator, \Countable
/** @var array<int, int> */ /** @var array<int, int> */
protected $decisionMap; protected $decisionMap;
/** /**
* @var array<array{0: int, 1: Rule}> * @var array<int, array{0: int, 1: Rule}>
*/ */
protected $decisionQueue = []; protected $decisionQueue = [];
@ -69,12 +69,12 @@ class Decisions implements \Iterator, \Countable
public function decided(int $literalOrPackageId): bool 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 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 public function decidedInstall(int $literalOrPackageId): bool
@ -94,7 +94,7 @@ class Decisions implements \Iterator, \Countable
return 0; return 0;
} }
public function decisionRule(int $literalOrPackageId): ?Rule public function decisionRule(int $literalOrPackageId): Rule
{ {
$packageId = abs($literalOrPackageId); $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); ksort($decisionMap);
$str = '['; $str = '[';
foreach ($decisionMap as $packageId => $level) { foreach ($decisionMap as $packageId => $level) {
$str .= (($pool) ? $pool->literalToPackage($packageId) : $packageId).':'.$level.','; $str .= ($pool !== null ? $pool->literalToPackage($packageId) : $packageId).':'.$level.',';
} }
$str .= ']'; $str .= ']';

View File

@ -30,7 +30,7 @@ class DefaultPolicy implements PolicyInterface
private $preferLowest; private $preferLowest;
/** @var array<string, string>|null */ /** @var array<string, string>|null */
private $preferredVersions; private $preferredVersions;
/** @var array<int, array<string, array<int, int>>> */ /** @var array<int, array<string, non-empty-list<int>>> */
private $preferredPackageResultCachePerPool; private $preferredPackageResultCachePerPool;
/** @var array<int, array<string, int>> */ /** @var array<int, array<string, int>> */
private $sortingCachePerPool; private $sortingCachePerPool;
@ -68,9 +68,8 @@ class DefaultPolicy implements PolicyInterface
} }
/** /**
* @param int[] $literals * @param non-empty-list<int> $literals
* @param string $requiredPackage * @return non-empty-list<int>
* @return int[]
*/ */
public function selectPreferredPackages(Pool $pool, array $literals, ?string $requiredPackage = null): array public function selectPreferredPackages(Pool $pool, array $literals, ?string $requiredPackage = null): array
{ {
@ -118,8 +117,8 @@ class DefaultPolicy implements PolicyInterface
} }
/** /**
* @param int[] $literals * @param non-empty-list<int> $literals
* @return array<string, int[]> * @return non-empty-array<string, non-empty-list<int>>
*/ */
protected function groupLiteralsByName(Pool $pool, array $literals): 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 // for replacers not replacing each other, put a higher prio on replacing
// packages with the same vendor as the required package // 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); $requiredVendor = substr($requiredPackage, 0, $pos);
$aIsSameVendor = strpos($a->getName(), $requiredVendor) === 0; $aIsSameVendor = strpos($a->getName(), $requiredVendor) === 0;
@ -205,8 +204,8 @@ class DefaultPolicy implements PolicyInterface
} }
/** /**
* @param int[] $literals * @param list<int> $literals
* @return int[] * @return list<int>
*/ */
protected function pruneToBestVersion(Pool $pool, array $literals): array 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 * If no package is a local alias, nothing happens
* *
* @param int[] $literals * @param list<int> $literals
* @return int[] * @return list<int>
*/ */
protected function pruneRemoteAliases(Pool $pool, array $literals): array protected function pruneRemoteAliases(Pool $pool, array $literals): array
{ {

View File

@ -47,6 +47,9 @@ class GenericRule extends Rule
public function getHash() public function getHash()
{ {
$data = unpack('ihash', (string) hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', implode(',', $this->literals), true)); $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']; return $data['hash'];
} }

View File

@ -19,11 +19,11 @@ namespace Composer\DependencyResolver;
*/ */
class MultiConflictRule extends Rule class MultiConflictRule extends Rule
{ {
/** @var list<int> */ /** @var non-empty-list<int> */
protected $literals; protected $literals;
/** /**
* @param list<int> $literals * @param non-empty-list<int> $literals
*/ */
public function __construct(array $literals, $reason, $reasonData) public function __construct(array $literals, $reason, $reasonData)
{ {
@ -40,7 +40,7 @@ class MultiConflictRule extends Rule
} }
/** /**
* @return list<int> * @return non-empty-list<int>
*/ */
public function getLiterals(): array public function getLiterals(): array
{ {
@ -53,6 +53,9 @@ class MultiConflictRule extends Rule
public function getHash() public function getHash()
{ {
$data = unpack('ihash', (string) hash(\PHP_VERSION_ID > 80100 ? 'xxh3' : 'sha1', 'c:'.implode(',', $this->literals), true)); $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']; return $data['hash'];
} }

View File

@ -26,8 +26,8 @@ interface PolicyInterface
public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator): bool; public function versionCompare(PackageInterface $a, PackageInterface $b, string $operator): bool;
/** /**
* @param int[] $literals * @param non-empty-list<int> $literals
* @return int[] * @return non-empty-list<int>
*/ */
public function selectPreferredPackages(Pool $pool, array $literals, ?string $requiredPackage = null): array; public function selectPreferredPackages(Pool $pool, array $literals, ?string $requiredPackage = null): array;
} }

View File

@ -95,7 +95,7 @@ class PoolBuilder
*/ */
private $loadedPerRepo = []; private $loadedPerRepo = [];
/** /**
* @var BasePackage[] * @var array<int, BasePackage>
*/ */
private $packages = []; private $packages = [];
/** /**
@ -201,10 +201,14 @@ class PoolBuilder
{ {
$this->restrictedPackagesList = $request->getRestrictedPackages() !== null ? array_flip($request->getRestrictedPackages()) : null; $this->restrictedPackagesList = $request->getRestrictedPackages() !== null ? array_flip($request->getRestrictedPackages()) : null;
if ($request->getUpdateAllowList()) { if (\count($request->getUpdateAllowList()) > 0) {
$this->updateAllowList = $request->getUpdateAllowList(); $this->updateAllowList = $request->getUpdateAllowList();
$this->warnAboutNonMatchingUpdateAllowList($request); $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) { foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) {
if (!$this->isUpdateAllowed($lockedPackage)) { if (!$this->isUpdateAllowed($lockedPackage)) {
// remember which packages we skipped loading remote content for in this partial update // 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); $this->loadPackagesMarkedForLoading($request, $repositories);
} }
@ -303,7 +307,7 @@ class PoolBuilder
} }
} }
if ($this->eventDispatcher) { if ($this->eventDispatcher !== null) {
$prePoolCreateEvent = new PrePoolCreateEvent( $prePoolCreateEvent = new PrePoolCreateEvent(
PluginEvents::PRE_POOL_CREATE, PluginEvents::PRE_POOL_CREATE,
$repositories, $repositories,
@ -413,7 +417,7 @@ class PoolBuilder
$this->packagesToLoad = []; $this->packagesToLoad = [];
foreach ($repositories as $repoIndex => $repository) { foreach ($repositories as $repoIndex => $repository) {
if (empty($packageBatch)) { if (0 === \count($packageBatch)) {
break; break;
} }
@ -499,7 +503,7 @@ class PoolBuilder
if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) { if ($propagateUpdate && $request->getUpdateAllowTransitiveDependencies()) {
$skippedRootRequires = $this->getSkippedRootRequires($request, $require); $skippedRootRequires = $this->getSkippedRootRequires($request, $require);
if ($request->getUpdateAllowTransitiveRootDependencies() || !$skippedRootRequires) { if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) {
$this->unlockPackage($request, $repositories, $require); $this->unlockPackage($request, $repositories, $require);
$this->markPackageNameForLoading($request, $require, $linkConstraint); $this->markPackageNameForLoading($request, $require, $linkConstraint);
} else { } else {
@ -528,7 +532,7 @@ class PoolBuilder
if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) { if (isset($this->loadedPackages[$replace], $this->skippedLoad[$replace])) {
$skippedRootRequires = $this->getSkippedRootRequires($request, $replace); $skippedRootRequires = $this->getSkippedRootRequires($request, $replace);
if ($request->getUpdateAllowTransitiveRootDependencies() || !$skippedRootRequires) { if ($request->getUpdateAllowTransitiveRootDependencies() || 0 === \count($skippedRootRequires)) {
$this->unlockPackage($request, $repositories, $replace); $this->unlockPackage($request, $repositories, $replace);
// the replaced package only needs to be loaded if something else requires it // the replaced package only needs to be loaded if something else requires it
$this->markPackageNameForLoadingIfRequired($request, $replace); $this->markPackageNameForLoadingIfRequired($request, $replace);
@ -615,6 +619,10 @@ class PoolBuilder
private function warnAboutNonMatchingUpdateAllowList(Request $request): void 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) { foreach ($this->updateAllowList as $pattern) {
$matchedPlatformPackage = false; $matchedPlatformPackage = false;

View File

@ -207,7 +207,7 @@ class PoolOptimizer
$groupHashParts[] = 'require:' . (string) $requireConstraint; $groupHashParts[] = 'require:' . (string) $requireConstraint;
} }
if ($package->getReplaces()) { if (\count($package->getReplaces()) > 0) {
foreach ($package->getReplaces() as $link) { foreach ($package->getReplaces() as $link) {
if (CompilingMatcher::match($link->getConstraint(), Constraint::OP_EQ, $package->getVersion())) { 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 // 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; continue;
} }
@ -371,7 +371,7 @@ class PoolOptimizer
*/ */
private function optimizeImpossiblePackagesAway(Request $request, Pool $pool): void private function optimizeImpossiblePackagesAway(Request $request, Pool $pool): void
{ {
if (count($request->getLockedPackages()) === 0) { if (\count($request->getLockedPackages()) === 0) {
return; return;
} }

View File

@ -80,7 +80,7 @@ class Problem
// TODO doesn't this entirely defeat the purpose of the problem sections? what's the point of sections? // 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)); $reasons = array_merge(...array_reverse($this->reasons));
if (count($reasons) === 1) { if (\count($reasons) === 1) {
reset($reasons); reset($reasons);
$rule = current($reasons); $rule = current($reasons);
@ -93,7 +93,7 @@ class Problem
$constraint = $reasonData['constraint']; $constraint = $reasonData['constraint'];
$packages = $pool->whatProvides($packageName, $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)); return "\n ".implode(self::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $packageName, $constraint));
} }
} }
@ -188,7 +188,7 @@ class Problem
if (!$isVerbose) { if (!$isVerbose) {
$versions = self::condenseVersionList($versions, 1); $versions = self::condenseVersionList($versions, 1);
} }
if (count($versions) > 1) { if (\count($versions) > 1) {
// remove the s from requires/conflicts to correct grammar // remove the s from requires/conflicts to correct grammar
$message = Preg::replace('{^(%s%s (?:require|conflict))s}', '$1', $message); $message = Preg::replace('{^(%s%s (?:require|conflict))s}', '$1', $message);
$result[] = sprintf($message, $package, '['.implode(', ', $versions).']'); $result[] = sprintf($message, $package, '['.implode(', ', $versions).']');
@ -276,7 +276,7 @@ class Problem
$ext = substr($packageName, 4); $ext = substr($packageName, 4);
$msg = "- Root composer.json requires PHP extension ".$packageName.self::constraintToText($constraint).' but '; $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) { if (null === $version) {
$providersStr = self::getProvidersList($repositorySet, $packageName, 5); $providersStr = self::getProvidersList($repositorySet, $packageName, 5);
if ($providersStr !== null) { if ($providersStr !== null) {
@ -337,7 +337,8 @@ class Problem
// first check if the actual requested package is found in normal conditions // 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 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(); $rootReqs = $repositorySet->getRootRequires();
if (isset($rootReqs[$packageName])) { if (isset($rootReqs[$packageName])) {
$filtered = array_filter($packages, static function ($p) use ($rootReqs, $packageName): bool { $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()); $fixedConstraint = new Constraint('==', $lockedPackage->getVersion());
$filtered = array_filter($packages, static function ($p) use ($fixedConstraint): bool { $filtered = array_filter($packages, static function ($p) use ($fixedConstraint): bool {
return $fixedConstraint->matches(new Constraint('==', $p->getVersion())); return $fixedConstraint->matches(new Constraint('==', $p->getVersion()));
@ -372,7 +373,7 @@ class Problem
return !$p->getRepository() instanceof LockArrayRepository; 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.']; 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 // 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 // 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); 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 // 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 // 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); return self::computeCheckForLowerPrioRepo($pool, $isVerbose, $packageName, $packages, $allReposPackages, 'constraint', $constraint);
} }
@ -441,12 +446,12 @@ class Problem
foreach ($packages as $package) { foreach ($packages as $package) {
$prepared[$package->getName()]['name'] = $package->getPrettyName(); $prepared[$package->getName()]['name'] = $package->getPrettyName();
$prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion().($package instanceof AliasPackage ? ' (alias of '.$package->getAliasOf()->getPrettyVersion().')' : ''); $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) { foreach ($pool->getRemovedVersions($package->getName(), $constraint) as $version => $prettyVersion) {
$prepared[$package->getName()]['versions'][$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) { foreach ($pool->getRemovedVersionsByPackage(spl_object_hash($package)) as $version => $prettyVersion) {
$prepared[$package->getName()]['versions'][$version] = $prettyVersion; $prepared[$package->getName()]['versions'][$version] = $prettyVersion;
} }
@ -482,7 +487,7 @@ class Problem
{ {
$available = $pool->whatProvides($packageName); $available = $pool->whatProvides($packageName);
if (count($available)) { if (\count($available) > 0) {
$selected = null; $selected = null;
foreach ($available as $pkg) { foreach ($available as $pkg) {
if ($pkg->getRepository() instanceof PlatformRepository) { if ($pkg->getRepository() instanceof PlatformRepository) {
@ -507,7 +512,7 @@ class Problem
$version = $selected->getPrettyVersion(); $version = $selected->getPrettyVersion();
$extra = $selected->getExtra(); $extra = $selected->getExtra();
if ($selected instanceof CompletePackageInterface && isset($extra['config.platform']) && $extra['config.platform'] === true) { 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 { } else {
return null; return null;
@ -568,8 +573,8 @@ class Problem
} }
/** /**
* @param PackageInterface[] $higherRepoPackages * @param non-empty-array<PackageInterface> $higherRepoPackages
* @param PackageInterface[] $allReposPackages * @param non-empty-array<PackageInterface> $allReposPackages
* @return array{0: string, 1: string} * @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 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); $topPackage = reset($higherRepoPackages);
if ($topPackage instanceof RootPackageInterface) { if ($topPackage instanceof RootPackageInterface) {
return [ 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->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 private static function getProvidersList(RepositorySet $repositorySet, string $packageName, int $maxProviders): ?string
@ -642,7 +649,7 @@ class Problem
$providers = $repositorySet->getProviders($packageName); $providers = $repositorySet->getProviders($packageName);
if (\count($providers) > 0) { if (\count($providers) > 0) {
$providersStr = implode(array_map(static function ($p): string { $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"; return ' - '.$p['name'].$description."\n";
}, count($providers) > $maxProviders + 1 ? array_slice($providers, 0, $maxProviders) : $providers)); }, count($providers) > $maxProviders + 1 ? array_slice($providers, 0, $maxProviders) : $providers));

View File

@ -190,7 +190,7 @@ class Request
} }
/** /**
* @return array<int|string, BasePackage> * @return ($packageIds is true ? array<int, BasePackage> : array<string, BasePackage>)
* *
* @TODO look into removing the packageIds option, the only place true is used * @TODO look into removing the packageIds option, the only place true is used
* is for the installed map in the solver problems. * is for the installed map in the solver problems.
@ -201,7 +201,7 @@ class Request
{ {
$presentMap = []; $presentMap = [];
if ($this->lockedRepository) { if ($this->lockedRepository !== null) {
foreach ($this->lockedRepository->getPackages() as $package) { foreach ($this->lockedRepository->getPackages() as $package) {
$presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package; $presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
} }
@ -215,7 +215,7 @@ class Request
} }
/** /**
* @return BasePackage[] * @return array<int, BasePackage>
*/ */
public function getFixedPackagesMap(): array public function getFixedPackagesMap(): array
{ {

View File

@ -153,7 +153,7 @@ abstract class Rule
if (PlatformRepository::isPlatformPackage($this->getReasonData()->getTarget())) { if (PlatformRepository::isPlatformPackage($this->getReasonData()->getTarget())) {
return false; return false;
} }
if ($request->getLockedRepository()) { if ($request->getLockedRepository() !== null) {
foreach ($request->getLockedRepository()->getPackages() as $package) { foreach ($request->getLockedRepository()->getPackages() as $package) {
if ($package->getName() === $this->getReasonData()->getTarget()) { if ($package->getName() === $this->getReasonData()->getTarget()) {
if ($pool->isUnacceptableFixedOrLockedPackage($package)) { if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
@ -176,7 +176,7 @@ abstract class Rule
if (PlatformRepository::isPlatformPackage($this->getReasonData()['packageName'])) { if (PlatformRepository::isPlatformPackage($this->getReasonData()['packageName'])) {
return false; return false;
} }
if ($request->getLockedRepository()) { if ($request->getLockedRepository() !== null) {
foreach ($request->getLockedRepository()->getPackages() as $package) { foreach ($request->getLockedRepository()->getPackages() as $package) {
if ($package->getName() === $this->getReasonData()['packageName']) { if ($package->getName() === $this->getReasonData()['packageName']) {
if ($pool->isUnacceptableFixedOrLockedPackage($package)) { if ($pool->isUnacceptableFixedOrLockedPackage($package)) {
@ -215,7 +215,7 @@ abstract class Rule
return $package2; return $package2;
case self::RULE_PACKAGE_REQUIRES: case self::RULE_PACKAGE_REQUIRES:
$sourceLiteral = array_shift($literals); $sourceLiteral = $literals[0];
$sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral)); $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
return $sourcePackage; return $sourcePackage;
@ -240,14 +240,14 @@ abstract class Rule
$constraint = $reasonData['constraint']; $constraint = $reasonData['constraint'];
$packages = $pool->whatProvides($packageName, $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(); return 'No package found to satisfy root composer.json require '.$packageName.' '.$constraint->getPrettyString();
} }
$packagesNonAlias = array_values(array_filter($packages, static function ($p): bool { $packagesNonAlias = array_values(array_filter($packages, static function ($p): bool {
return !($p instanceof AliasPackage); return !($p instanceof AliasPackage);
})); }));
if (count($packagesNonAlias) === 1) { if (\count($packagesNonAlias) === 1) {
$package = $packagesNonAlias[0]; $package = $packagesNonAlias[0];
if ($request->isLockedPackage($package)) { if ($request->isLockedPackage($package)) {
return $package->getPrettyName().' is locked to version '.$package->getPrettyVersion()." and an update of this package was not requested."; 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.'.'; return $package2->getPrettyString().' conflicts with '.$conflictTarget.'.';
case self::RULE_PACKAGE_REQUIRES: case self::RULE_PACKAGE_REQUIRES:
assert(\count($literals) > 0);
$sourceLiteral = array_shift($literals); $sourceLiteral = array_shift($literals);
$sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral)); $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
$reasonData = $this->getReasonData(); $reasonData = $this->getReasonData();
@ -315,7 +316,7 @@ abstract class Rule
} }
$text = $reasonData->getPrettyString($sourcePackage); $text = $reasonData->getPrettyString($sourcePackage);
if ($requires) { if (\count($requires) > 0) {
$text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose, $reasonData->getConstraint()) . '.'; $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose, $reasonData->getConstraint()) . '.';
} else { } else {
$targetName = $reasonData->getTarget(); $targetName = $reasonData->getTarget();
@ -333,19 +334,18 @@ abstract class Rule
$package = $pool->literalToPackage($literal); $package = $pool->literalToPackage($literal);
$packageNames[$package->getName()] = true; $packageNames[$package->getName()] = true;
} }
unset($literal);
$replacedName = $this->getReasonData(); $replacedName = $this->getReasonData();
if (count($packageNames) > 1) { if (\count($packageNames) > 1) {
$reason = null;
if (!isset($packageNames[$replacedName])) { 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 { } else {
$replacerNames = $packageNames; $replacerNames = $packageNames;
unset($replacerNames[$replacedName]); unset($replacerNames[$replacedName]);
$replacerNames = array_keys($replacerNames); $replacerNames = array_keys($replacerNames);
if (count($replacerNames) === 1) { if (\count($replacerNames) === 1) {
$reason = $replacerNames[0] . ' replaces '; $reason = $replacerNames[0] . ' replaces ';
} else { } else {
$reason = '['.implode(', ', $replacerNames).'] replace '; $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; 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)'; $learnedString = ' (conflict analysis result)';
if (count($literals) === 1) { if (\count($literals) === 1) {
$ruleText = $pool->literalToPrettyString($literals[0], $installedMap); $ruleText = $pool->literalToPrettyString($literals[0], $installedMap);
} else { } else {
$groups = []; $groups = [];
@ -397,7 +397,7 @@ abstract class Rule
} }
$ruleTexts = []; $ruleTexts = [];
foreach ($groups as $group => $packages) { 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); $ruleText = implode(' | ', $ruleTexts);
@ -439,14 +439,13 @@ abstract class Rule
} }
/** /**
* @param array<int|BasePackage> $packages An array containing packages or literals * @param array<int|BasePackage> $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) { $packages = [];
if (!\is_object($package)) { foreach ($literalsOrPackages as $package) {
$packages[$index] = $pool->literalToPackage($package); $packages[] = \is_object($package) ? $package : $pool->literalToPackage($package);
}
} }
return Problem::getPackageList($packages, $isVerbose, $pool, $constraint, $useRemovedVersionGroup); return Problem::getPackageList($packages, $isVerbose, $pool, $constraint, $useRemovedVersionGroup);

View File

@ -43,7 +43,7 @@ class Rule2Literals extends Rule
} }
/** /**
* @return list<int> * @return non-empty-list<int>
*/ */
public function getLiterals(): array public function getLiterals(): array
{ {

View File

@ -179,7 +179,7 @@ class RuleSet implements \IteratorAggregate, \Countable
foreach ($this->rules as $type => $rules) { foreach ($this->rules as $type => $rules) {
$string .= str_pad(self::TYPES[$type], 8, ' ') . ": "; $string .= str_pad(self::TYPES[$type], 8, ' ') . ": ";
foreach ($rules as $rule) { 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"; $string .= "\n\n";
} }

View File

@ -56,7 +56,7 @@ class RuleSetGenerator
* *
* @phpstan-param ReasonData $reasonData * @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]; $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 * 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. * set of packages is empty an impossible rule is generated.
* *
* @param BasePackage[] $packages The set of packages to choose from * @param non-empty-array<BasePackage> $packages The set of packages to choose from
* @param Rule::RULE_* $reason A RULE_* constant describing the reason for * @param Rule::RULE_* $reason A RULE_* constant describing the reason for
* generating this rule * generating this rule
* @param mixed $reasonData Additional data like the root require or fix request info * @param mixed $reasonData Additional data like the root require or fix request info
@ -109,7 +109,7 @@ class RuleSetGenerator
* *
* @phpstan-param ReasonData $reasonData * @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 // ignore self conflict
if ($issuer === $provider) { if ($issuer === $provider) {
@ -120,7 +120,7 @@ class RuleSetGenerator
} }
/** /**
* @param BasePackage[] $packages * @param non-empty-array<BasePackage> $packages
* @param Rule::RULE_* $reason A RULE_* constant * @param Rule::RULE_* $reason A RULE_* constant
* @param mixed $reasonData * @param mixed $reasonData
* *
@ -151,7 +151,7 @@ class RuleSetGenerator
*/ */
private function addRule($type, ?Rule $newRule = null): void private function addRule($type, ?Rule $newRule = null): void
{ {
if (!$newRule) { if (null === $newRule) {
return; return;
} }
@ -276,7 +276,7 @@ class RuleSetGenerator
} }
$packages = $this->pool->whatProvides($packageName, $constraint); $packages = $this->pool->whatProvides($packageName, $constraint);
if ($packages) { if (\count($packages) > 0) {
foreach ($packages as $package) { foreach ($packages as $package) {
$this->addRulesForPackage($package, $platformRequirementFilter); $this->addRulesForPackage($package, $platformRequirementFilter);
} }
@ -307,7 +307,7 @@ class RuleSetGenerator
public function getRulesFor(Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): RuleSet public function getRulesFor(Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): RuleSet
{ {
$platformRequirementFilter = $platformRequirementFilter ?: PlatformRequirementFilterFactory::ignoreNothing(); $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing();
$this->addRulesForRequest($request, $platformRequirementFilter); $this->addRulesForRequest($request, $platformRequirementFilter);

View File

@ -14,7 +14,7 @@ namespace Composer\DependencyResolver;
/** /**
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
* @implements \Iterator<RuleSet::TYPE_*, Rule> * @implements \Iterator<RuleSet::TYPE_*|-1, Rule>
*/ */
class RuleSetIterator implements \Iterator class RuleSetIterator implements \Iterator
{ {

View File

@ -43,7 +43,7 @@ class Solver
/** @var int */ /** @var int */
protected $propagateIndex; protected $propagateIndex;
/** @var mixed[] */ /** @var array<int, array{array<int, int>, int}> */
protected $branches = []; protected $branches = [];
/** @var Problem[] */ /** @var Problem[] */
protected $problems = []; protected $problems = [];
@ -109,7 +109,7 @@ class Solver
$conflict = $this->decisions->decisionRule($literal); $conflict = $this->decisions->decisionRule($literal);
if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) { if (RuleSet::TYPE_PACKAGE === $conflict->getType()) {
$problem = new Problem(); $problem = new Problem();
$problem->addRule($rule); $problem->addRule($rule);
@ -164,7 +164,7 @@ class Solver
$constraint = $platformRequirementFilter->filterConstraint($packageName, $constraint); $constraint = $platformRequirementFilter->filterConstraint($packageName, $constraint);
} }
if (!$this->pool->whatProvides($packageName, $constraint)) { if (0 === \count($this->pool->whatProvides($packageName, $constraint))) {
$problem = new Problem(); $problem = new Problem();
$problem->addRule(new GenericRule([], Rule::RULE_ROOT_REQUIRE, ['packageName' => $packageName, 'constraint' => $constraint])); $problem->addRule(new GenericRule([], Rule::RULE_ROOT_REQUIRE, ['packageName' => $packageName, 'constraint' => $constraint]));
$this->problems[] = $problem; $this->problems[] = $problem;
@ -174,7 +174,7 @@ class Solver
public function solve(Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): LockTransaction public function solve(Request $request, ?PlatformRequirementFilterInterface $platformRequirementFilter = null): LockTransaction
{ {
$platformRequirementFilter = $platformRequirementFilter ?: PlatformRequirementFilterFactory::ignoreNothing(); $platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing();
$this->setupFixedMap($request); $this->setupFixedMap($request);
@ -199,7 +199,7 @@ class Solver
$this->io->writeError('', true, IOInterface::DEBUG); $this->io->writeError('', true, IOInterface::DEBUG);
$this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE); $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); throw new SolverProblemsException($this->problems, $this->learnedPool);
} }
@ -227,7 +227,7 @@ class Solver
$this->propagateIndex++; $this->propagateIndex++;
if ($conflict) { if ($conflict !== null) {
return $conflict; return $conflict;
} }
} }
@ -257,7 +257,7 @@ class Solver
$this->propagateIndex = \count($this->decisions); $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); array_pop($this->branches);
} }
} }
@ -274,10 +274,8 @@ class Solver
* rule (always unit) and re-propagate. * rule (always unit) and re-propagate.
* *
* returns the new solver level or 0 if unsolvable * 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++; $level++;
@ -291,7 +289,9 @@ class Solver
} }
if ($level === 1) { if ($level === 1) {
return $this->analyzeUnsolvable($rule); $this->analyzeUnsolvable($rule);
return 0;
} }
// conflict // conflict
@ -322,7 +322,7 @@ class Solver
} }
/** /**
* @param int[] $decisionQueue * @param non-empty-list<int> $decisionQueue
*/ */
private function selectAndInstall(int $level, array $decisionQueue, Rule $rule): int private function selectAndInstall(int $level, array $decisionQueue, Rule $rule): int
{ {
@ -332,7 +332,7 @@ class Solver
$selectedLiteral = array_shift($literals); $selectedLiteral = array_shift($literals);
// if there are multiple candidates, then branch // if there are multiple candidates, then branch
if (\count($literals)) { if (\count($literals) > 0) {
$this->branches[] = [$literals, $level]; $this->branches[] = [$literals, $level];
} }
@ -349,7 +349,8 @@ class Solver
$num = 0; $num = 0;
$l1num = 0; $l1num = 0;
$seen = []; $seen = [];
$learnedLiterals = [null]; $learnedLiteral = null;
$otherLearnedLiterals = [];
$decisionId = \count($this->decisions); $decisionId = \count($this->decisions);
@ -382,7 +383,7 @@ class Solver
$num++; $num++;
} else { } else {
// not level1 or conflict level, add to new rule // not level1 or conflict level, add to new rule
$learnedLiterals[] = $literal; $otherLearnedLiterals[] = $literal;
if ($l > $ruleLevel) { if ($l > $ruleLevel) {
$ruleLevel = $l; $ruleLevel = $l;
@ -423,16 +424,14 @@ class Solver
if ($literal < 0) { if ($literal < 0) {
$this->testFlagLearnedPositiveLiteral = true; $this->testFlagLearnedPositiveLiteral = true;
} }
$learnedLiterals[0] = -$literal; $learnedLiteral = -$literal;
if (!$l1num) { if (0 === $l1num) {
break 2; break 2;
} }
foreach ($learnedLiterals as $i => $learnedLiteral) { foreach ($otherLearnedLiterals as $otherLiteral) {
if ($i !== 0) { unset($seen[abs($otherLiteral)]);
unset($seen[abs($learnedLiteral)]);
}
} }
// only level 1 marks left // only level 1 marks left
$l1num++; $l1num++;
@ -442,24 +441,24 @@ class Solver
$rule = $decision[Decisions::DECISION_REASON]; $rule = $decision[Decisions::DECISION_REASON];
if ($rule instanceof MultiConflictRule) { if ($rule instanceof MultiConflictRule) {
// there is only ever exactly one positive decision in a multiconflict rule // there is only ever exactly one positive decision in a MultiConflictRule
foreach ($rule->getLiterals() as $literal) { foreach ($rule->getLiterals() as $ruleLiteral) {
if (!isset($seen[abs($literal)]) && $this->decisions->satisfy(-$literal)) { if (!isset($seen[abs($ruleLiteral)]) && $this->decisions->satisfy(-$ruleLiteral)) {
$this->learnedPool[\count($this->learnedPool) - 1][] = $rule; $this->learnedPool[\count($this->learnedPool) - 1][] = $rule;
$l = $this->decisions->decisionLevel($literal); $l = $this->decisions->decisionLevel($ruleLiteral);
if (1 === $l) { if (1 === $l) {
$l1num++; $l1num++;
} elseif ($level === $l) { } elseif ($level === $l) {
$num++; $num++;
} else { } else {
// not level1 or conflict level, add to new rule // not level1 or conflict level, add to new rule
$learnedLiterals[] = $literal; $otherLearnedLiterals[] = $ruleLiteral;
if ($l > $ruleLevel) { if ($l > $ruleLevel) {
$ruleLevel = $l; $ruleLevel = $l;
} }
} }
$seen[abs($literal)] = true; $seen[abs($ruleLiteral)] = true;
break; break;
} }
} }
@ -475,15 +474,16 @@ class Solver
$why = \count($this->learnedPool) - 1; $why = \count($this->learnedPool) - 1;
if (null === $learnedLiterals[0]) { if (null === $learnedLiteral) {
throw new SolverBugException( throw new SolverBugException(
"Did not find a learnable literal in analyzed rule $analyzedRule." "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); $problem->addRule($conflictRule);
} }
private function analyzeUnsolvable(Rule $conflictRule): int private function analyzeUnsolvable(Rule $conflictRule): void
{ {
$problem = new Problem(); $problem = new Problem();
$problem->addRule($conflictRule); $problem->addRule($conflictRule);
@ -539,10 +539,10 @@ class Solver
} }
foreach ($this->decisions as $decision) { foreach ($this->decisions as $decision) {
$literal = $decision[Decisions::DECISION_LITERAL]; $decisionLiteral = $decision[Decisions::DECISION_LITERAL];
// skip literals that are not in this rule // skip literals that are not in this rule
if (!isset($seen[abs($literal)])) { if (!isset($seen[abs($decisionLiteral)])) {
continue; continue;
} }
@ -552,7 +552,6 @@ class Solver
$this->analyzeUnsolvableRule($problem, $why, $ruleSeen); $this->analyzeUnsolvableRule($problem, $why, $ruleSeen);
$literals = $why->getLiterals(); $literals = $why->getLiterals();
foreach ($literals as $literal) { foreach ($literals as $literal) {
// skip the one true literal // skip the one true literal
if ($this->decisions->satisfy($literal)) { if ($this->decisions->satisfy($literal)) {
@ -561,8 +560,6 @@ class Solver
$seen[abs($literal)] = true; $seen[abs($literal)] = true;
} }
} }
return 0;
} }
private function runSat(): void private function runSat(): void
@ -586,9 +583,7 @@ class Solver
if (1 === $level) { if (1 === $level) {
$conflictRule = $this->propagate($level); $conflictRule = $this->propagate($level);
if (null !== $conflictRule) { if (null !== $conflictRule) {
if ($this->analyzeUnsolvable($conflictRule)) { $this->analyzeUnsolvable($conflictRule);
continue;
}
return; 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 // if any of the options in the decision queue are fixed, only use those
$prunedQueue = []; $prunedQueue = [];
foreach ($decisionQueue as $literal) { foreach ($decisionQueue as $literal) {
@ -620,12 +615,12 @@ class Solver
$prunedQueue[] = $literal; $prunedQueue[] = $literal;
} }
} }
if (!empty($prunedQueue)) { if (\count($prunedQueue) > 0) {
$decisionQueue = $prunedQueue; $decisionQueue = $prunedQueue;
} }
} }
if ($noneSatisfied && \count($decisionQueue)) { if ($noneSatisfied && \count($decisionQueue) > 0) {
$oLevel = $level; $oLevel = $level;
$level = $this->selectAndInstall($level, $decisionQueue, $rule); $level = $this->selectAndInstall($level, $decisionQueue, $rule);
@ -719,7 +714,7 @@ class Solver
} }
// minimization step // minimization step
if (\count($this->branches)) { if (\count($this->branches) > 0) {
$lastLiteral = null; $lastLiteral = null;
$lastLevel = null; $lastLevel = null;
$lastBranchIndex = 0; $lastBranchIndex = 0;
@ -729,7 +724,7 @@ class Solver
[$literals, $l] = $this->branches[$i]; [$literals, $l] = $this->branches[$i];
foreach ($literals as $offset => $literal) { 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; $lastLiteral = $literal;
$lastBranchIndex = $i; $lastBranchIndex = $i;
$lastBranchOffset = $offset; $lastBranchOffset = $offset;
@ -738,7 +733,8 @@ class Solver
} }
} }
if ($lastLiteral) { if ($lastLiteral !== null) {
assert($lastLevel !== null);
unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]); unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
$level = $lastLevel; $level = $lastLevel;

View File

@ -38,7 +38,7 @@ class SolverProblemsException extends \RuntimeException
$this->problems = $problems; $this->problems = $problems;
$this->learnedPool = $learnedPool; $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 public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, bool $isVerbose, bool $isDevExtraction = false): string
@ -63,11 +63,11 @@ class SolverProblemsException extends \RuntimeException
} }
$hints = []; $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 <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems."; $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 <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
} }
if (!empty($missingExtensions)) { if (\count($missingExtensions) > 0) {
$hints[] = $this->createExtensionHint($missingExtensions); $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."; $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[] = "<warning>ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4.</warning>\nIf you can not upgrade PHP you can require <info>composer/package-versions-deprecated</info> to resolve this with PHP 7.0+."; $hints[] = "<warning>ocramius/package-versions only provides support for Composer 2 in 1.8+, which requires PHP 7.4.</warning>\nIf you can not upgrade PHP you can require <info>composer/package-versions-deprecated</info> to resolve this with PHP 7.0+.";
} }
if (!class_exists('PHPUnit\Framework\TestCase', false)) { 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."; $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); $text .= "\n" . implode("\n\n", $hints);
} }

View File

@ -123,7 +123,7 @@ class Transaction
$visited = []; $visited = [];
$processed = []; $processed = [];
while (!empty($stack)) { while (\count($stack) > 0) {
$package = array_pop($stack); $package = array_pop($stack);
if (isset($processed[spl_object_hash($package)])) { if (isset($processed[spl_object_hash($package)])) {
@ -283,17 +283,18 @@ class Transaction
continue; 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? // 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 // get the package's requires, but filter out any platform requirements
$requires = array_filter(array_keys($package->getRequires()), static function ($req): bool { $requires = array_filter(array_keys($package->getRequires()), static function ($req): bool {
return !PlatformRepository::isPlatformPackage($req); return !PlatformRepository::isPlatformPackage($req);
}); });
// is this a plugin with no meaningful dependencies? // 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 // plugins with no dependencies go to the very front
array_unshift($dlModifyingPluginsNoDeps, $op); array_unshift($dlModifyingPluginsNoDeps, $op);
} else { } else {
@ -311,14 +312,14 @@ class Transaction
$isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer'; $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
// is this a plugin or a dependency of a plugin? // 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 // get the package's requires, but filter out any platform requirements
$requires = array_filter(array_keys($package->getRequires()), static function ($req): bool { $requires = array_filter(array_keys($package->getRequires()), static function ($req): bool {
return !PlatformRepository::isPlatformPackage($req); return !PlatformRepository::isPlatformPackage($req);
}); });
// is this a plugin with no meaningful dependencies? // 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 // plugins with no dependencies go to the very front
array_unshift($pluginsNoDeps, $op); array_unshift($pluginsNoDeps, $op);
} else { } else {

View File

@ -226,6 +226,7 @@ class DefaultPolicyTest extends TestCase
$pool = $this->repositorySet->createPoolForPackage('A', $this->repoLocked); $pool = $this->repositorySet->createPoolForPackage('A', $this->repoLocked);
$packages = $pool->whatProvides('a', new Constraint('=', '2.1.9999999.9999999-dev')); $packages = $pool->whatProvides('a', new Constraint('=', '2.1.9999999.9999999-dev'));
self::assertNotEmpty($packages);
$literals = []; $literals = [];
foreach ($packages as $package) { foreach ($packages as $package) {
$literals[] = $package->getId(); $literals[] = $package->getId();