From 50d738eeeea05b81b78e4e99f5eed58988a5dd22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?imme=C3=ABmosol?= Date: Mon, 18 Oct 2021 22:33:37 +0200 Subject: [PATCH] Reaching phpstan level 6 in Composer/DependencyResolver (refs #10159) (#10178) --- src/Composer/DependencyResolver/Decisions.php | 38 +++++++--- .../DependencyResolver/DefaultPolicy.php | 11 ++- .../DependencyResolver/GenericRule.php | 9 ++- .../LocalRepoTransaction.php | 3 +- .../DependencyResolver/LockTransaction.php | 11 +++ .../DependencyResolver/MultiConflictRule.php | 12 ++-- .../Operation/InstallOperation.php | 1 + .../Operation/UninstallOperation.php | 1 + .../Operation/UpdateOperation.php | 1 + src/Composer/DependencyResolver/Pool.php | 21 ++++-- .../DependencyResolver/PoolBuilder.php | 19 +++-- src/Composer/DependencyResolver/Problem.php | 34 +++++++-- src/Composer/DependencyResolver/Request.php | 30 ++++++-- src/Composer/DependencyResolver/Rule.php | 69 ++++++++++++++++--- .../DependencyResolver/Rule2Literals.php | 16 +++-- src/Composer/DependencyResolver/RuleSet.php | 7 ++ .../DependencyResolver/RuleSetGenerator.php | 44 ++++++------ .../DependencyResolver/RuleWatchChain.php | 3 + .../DependencyResolver/RuleWatchGraph.php | 4 +- .../DependencyResolver/RuleWatchNode.php | 2 + src/Composer/DependencyResolver/Solver.php | 26 ++----- .../DependencyResolver/SolverBugException.php | 3 + .../SolverProblemsException.php | 6 +- .../DependencyResolver/Transaction.php | 18 ++++- src/Composer/Plugin/PrePoolCreateEvent.php | 15 ++-- .../Test/DependencyResolver/RuleSetTest.php | 1 + 26 files changed, 292 insertions(+), 113 deletions(-) diff --git a/src/Composer/DependencyResolver/Decisions.php b/src/Composer/DependencyResolver/Decisions.php index 2a7e654b7..8dfd8d86d 100644 --- a/src/Composer/DependencyResolver/Decisions.php +++ b/src/Composer/DependencyResolver/Decisions.php @@ -16,7 +16,7 @@ namespace Composer\DependencyResolver; * Stores decisions on installing, removing or keeping packages * * @author Nils Adermann - * @implements \Iterator + * @implements \Iterator */ class Decisions implements \Iterator, \Countable { @@ -27,7 +27,9 @@ class Decisions implements \Iterator, \Countable protected $pool; /** @var array */ protected $decisionMap; - /** @var array */ + /** + * @var array + */ protected $decisionQueue = array(); public function __construct(Pool $pool) @@ -36,7 +38,12 @@ class Decisions implements \Iterator, \Countable $this->decisionMap = array(); } - public function decide($literal, $level, $why) + /** + * @param int $literal + * @param int $level + * @return void + */ + public function decide($literal, $level, Rule $why) { $this->addDecision($literal, $level); $this->decisionQueue[] = array( @@ -46,6 +53,7 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $literal * @return bool */ public function satisfy($literal) @@ -59,6 +67,7 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $literal * @return bool */ public function conflict($literal) @@ -72,6 +81,7 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $literalOrPackageId * @return bool */ public function decided($literalOrPackageId) @@ -80,6 +90,7 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $literalOrPackageId * @return bool */ public function undecided($literalOrPackageId) @@ -88,6 +99,7 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $literalOrPackageId * @return bool */ public function decidedInstall($literalOrPackageId) @@ -98,6 +110,7 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $literalOrPackageId * @return int */ public function decisionLevel($literalOrPackageId) @@ -111,13 +124,14 @@ class Decisions implements \Iterator, \Countable } /** - * @return mixed|null + * @param int $literalOrPackageId + * @return Rule|null */ public function decisionRule($literalOrPackageId) { $packageId = abs($literalOrPackageId); - foreach ($this->decisionQueue as $i => $decision) { + foreach ($this->decisionQueue as $decision) { if ($packageId === abs($decision[self::DECISION_LITERAL])) { return $decision[self::DECISION_REASON]; } @@ -127,7 +141,8 @@ class Decisions implements \Iterator, \Countable } /** - * @return array{0: int, 1: mixed} a literal and decision reason + * @param int $queueOffset + * @return array{0: int, 1: Rule} a literal and decision reason */ public function atOffset($queueOffset) { @@ -135,6 +150,7 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $queueOffset * @return bool */ public function validOffset($queueOffset) @@ -143,7 +159,7 @@ class Decisions implements \Iterator, \Countable } /** - * @return mixed + * @return Rule */ public function lastReason() { @@ -169,6 +185,7 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $offset * @return void */ public function resetToOffset($offset) @@ -207,7 +224,7 @@ class Decisions implements \Iterator, \Countable } /** - * @return array{0: int, 1: mixed}|false + * @return array{0: int, 1: Rule}|false */ #[\ReturnTypeWillChange] public function current() @@ -251,6 +268,8 @@ class Decisions implements \Iterator, \Countable } /** + * @param int $literal + * @param int $level * @return void */ protected function addDecision($literal, $level) @@ -289,9 +308,6 @@ class Decisions implements \Iterator, \Countable return $str; } - /** - * @return string - */ public function __toString() { return $this->toString(); diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index cc23731e3..4d7aa55b4 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -28,6 +28,10 @@ class DefaultPolicy implements PolicyInterface /** @var bool */ private $preferLowest; + /** + * @param bool $preferStable + * @param bool $preferLowest + */ public function __construct($preferStable = false, $preferLowest = false) { $this->preferStable = $preferStable; @@ -35,7 +39,10 @@ class DefaultPolicy implements PolicyInterface } /** + * @param string $operator One of Constraint::STR_OP_* * @return bool + * + * @phpstan-param Constraint::STR_OP_* $operator */ public function versionCompare(PackageInterface $a, PackageInterface $b, $operator) { @@ -101,6 +108,8 @@ class DefaultPolicy implements PolicyInterface /** * @protected + * @param ?string $requiredPackage + * @param bool $ignoreReplace * @return int */ public function compareByPriority(Pool $pool, BasePackage $a, BasePackage $b, $requiredPackage = null, $ignoreReplace = false) @@ -154,8 +163,6 @@ class DefaultPolicy implements PolicyInterface * Replace constraints are ignored. This method should only be used for * prioritisation, not for actual constraint verification. * - * @param BasePackage $source - * @param BasePackage $target * @return bool */ protected function replaces(BasePackage $source, BasePackage $target) diff --git a/src/Composer/DependencyResolver/GenericRule.php b/src/Composer/DependencyResolver/GenericRule.php index 7064c0914..00abfafd3 100644 --- a/src/Composer/DependencyResolver/GenericRule.php +++ b/src/Composer/DependencyResolver/GenericRule.php @@ -12,10 +12,6 @@ namespace Composer\DependencyResolver; -use Composer\Package\BasePackage; -use Composer\Package\Link; -use Composer\Semver\Constraint\ConstraintInterface; - /** * @author Nils Adermann */ @@ -25,7 +21,7 @@ class GenericRule extends Rule protected $literals; /** - * @param int[] $literals + * @param int[] $literals */ public function __construct(array $literals, $reason, $reasonData) { @@ -45,6 +41,9 @@ class GenericRule extends Rule return $this->literals; } + /** + * @inheritDoc + */ public function getHash() { $data = unpack('ihash', md5(implode(',', $this->literals), true)); diff --git a/src/Composer/DependencyResolver/LocalRepoTransaction.php b/src/Composer/DependencyResolver/LocalRepoTransaction.php index daefc12b9..4a03816d7 100644 --- a/src/Composer/DependencyResolver/LocalRepoTransaction.php +++ b/src/Composer/DependencyResolver/LocalRepoTransaction.php @@ -12,6 +12,7 @@ namespace Composer\DependencyResolver; +use Composer\Repository\InstalledRepositoryInterface; use Composer\Repository\RepositoryInterface; /** @@ -20,7 +21,7 @@ use Composer\Repository\RepositoryInterface; */ class LocalRepoTransaction extends Transaction { - public function __construct(RepositoryInterface $lockedRepository, $localRepository) + public function __construct(RepositoryInterface $lockedRepository, InstalledRepositoryInterface $localRepository) { parent::__construct( $localRepository->getPackages(), diff --git a/src/Composer/DependencyResolver/LockTransaction.php b/src/Composer/DependencyResolver/LockTransaction.php index 97eb58bb2..e246f2b3d 100644 --- a/src/Composer/DependencyResolver/LockTransaction.php +++ b/src/Composer/DependencyResolver/LockTransaction.php @@ -58,7 +58,11 @@ class LockTransaction extends Transaction parent::__construct($this->presentMap, $this->resultPackages['all']); } + // TODO make this a bit prettier instead of the two text indexes? + /** + * @return void + */ public function setResultPackages(Pool $pool, Decisions $decisions) { $this->resultPackages = array('all' => array(), 'non-dev' => array(), 'dev' => array()); @@ -76,6 +80,9 @@ class LockTransaction extends Transaction } } + /** + * @return void + */ public function setNonDevPackages(LockTransaction $extractionResult) { $packages = $extractionResult->getNewLockPackages(false); @@ -96,6 +103,8 @@ class LockTransaction extends Transaction // TODO additionalFixedRepository needs to be looked at here as well? /** + * @param bool $devMode + * @param bool $updateMirrors * @return BasePackage[] */ public function getNewLockPackages($devMode, $updateMirrors = false) @@ -126,6 +135,8 @@ class LockTransaction extends Transaction /** * Checks which of the given aliases from composer.json are actually in use for the lock file + * @param array $aliases + * @return array */ public function getAliases($aliases) { diff --git a/src/Composer/DependencyResolver/MultiConflictRule.php b/src/Composer/DependencyResolver/MultiConflictRule.php index 47c6a67db..deda73010 100644 --- a/src/Composer/DependencyResolver/MultiConflictRule.php +++ b/src/Composer/DependencyResolver/MultiConflictRule.php @@ -12,9 +12,6 @@ namespace Composer\DependencyResolver; -use Composer\Package\BasePackage; -use Composer\Package\Link; - /** * @author Nils Adermann * @@ -26,7 +23,7 @@ class MultiConflictRule extends Rule protected $literals; /** - * @param int[] $literals + * @param int[] $literals */ public function __construct(array $literals, $reason, $reasonData) { @@ -50,6 +47,9 @@ class MultiConflictRule extends Rule return $this->literals; } + /** + * @inheritDoc + */ public function getHash() { $data = unpack('ihash', md5('c:'.implode(',', $this->literals), true)); @@ -82,6 +82,10 @@ class MultiConflictRule extends Rule return false; } + /** + * @return never + * @throws \RuntimeException + */ public function disable() { throw new \RuntimeException("Disabling multi conflict rules is not possible. Please contact composer at https://github.com/composer/composer to let us debug what lead to this situation."); diff --git a/src/Composer/DependencyResolver/Operation/InstallOperation.php b/src/Composer/DependencyResolver/Operation/InstallOperation.php index 2ef9d3608..92b332d15 100644 --- a/src/Composer/DependencyResolver/Operation/InstallOperation.php +++ b/src/Composer/DependencyResolver/Operation/InstallOperation.php @@ -52,6 +52,7 @@ class InstallOperation extends SolverOperation implements OperationInterface } /** + * @param bool $lock * @return string */ public static function format(PackageInterface $package, $lock = false) diff --git a/src/Composer/DependencyResolver/Operation/UninstallOperation.php b/src/Composer/DependencyResolver/Operation/UninstallOperation.php index 97ff32312..5a3c2dd2e 100644 --- a/src/Composer/DependencyResolver/Operation/UninstallOperation.php +++ b/src/Composer/DependencyResolver/Operation/UninstallOperation.php @@ -52,6 +52,7 @@ class UninstallOperation extends SolverOperation implements OperationInterface } /** + * @param bool $lock * @return string */ public static function format(PackageInterface $package, $lock = false) diff --git a/src/Composer/DependencyResolver/Operation/UpdateOperation.php b/src/Composer/DependencyResolver/Operation/UpdateOperation.php index e32d50935..6e1bb3ec9 100644 --- a/src/Composer/DependencyResolver/Operation/UpdateOperation.php +++ b/src/Composer/DependencyResolver/Operation/UpdateOperation.php @@ -73,6 +73,7 @@ class UpdateOperation extends SolverOperation implements OperationInterface } /** + * @param bool $lock * @return string */ public static function format(PackageInterface $initialPackage, PackageInterface $targetPackage, $lock = false) diff --git a/src/Composer/DependencyResolver/Pool.php b/src/Composer/DependencyResolver/Pool.php index 68673453b..36f8046fa 100644 --- a/src/Composer/DependencyResolver/Pool.php +++ b/src/Composer/DependencyResolver/Pool.php @@ -12,11 +12,11 @@ namespace Composer\DependencyResolver; +use Composer\Package\BasePackage; use Composer\Package\Version\VersionParser; use Composer\Semver\CompilingMatcher; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\Constraint; -use Composer\Package\BasePackage; /** * A package pool contains all packages for dependency resolution @@ -37,6 +37,10 @@ class Pool implements \Countable /** @var BasePackage[] */ protected $unacceptableFixedOrLockedPackages; + /** + * @param BasePackage[] $packages + * @param BasePackage[] $unacceptableFixedOrLockedPackages + */ public function __construct(array $packages = array(), array $unacceptableFixedOrLockedPackages = array()) { $this->versionParser = new VersionParser; @@ -44,6 +48,10 @@ class Pool implements \Countable $this->unacceptableFixedOrLockedPackages = $unacceptableFixedOrLockedPackages; } + /** + * @param BasePackage[] $packages + * @return void + */ private function setPackages(array $packages) { $id = 1; @@ -91,10 +99,10 @@ class Pool implements \Countable /** * Searches all packages providing the given package name and match the constraint * - * @param string $name The package name to be searched for - * @param ConstraintInterface $constraint A constraint that all returned + * @param string $name The package name to be searched for + * @param ?ConstraintInterface $constraint A constraint that all returned * packages must match or null to return all - * @return BasePackage[] A set of packages + * @return BasePackage[] A set of packages */ public function whatProvides($name, ConstraintInterface $constraint = null) { @@ -130,6 +138,7 @@ class Pool implements \Countable } /** + * @param int $literal * @return BasePackage */ public function literalToPackage($literal) @@ -140,6 +149,8 @@ class Pool implements \Countable } /** + * @param int $literal + * @param array $installedMap * @return string */ public function literalToPrettyString($literal, $installedMap) @@ -159,9 +170,7 @@ class Pool implements \Countable * Checks if the package matches the given constraint directly or through * provided or replaced packages * - * @param BasePackage $candidate * @param string $name Name of the package to be matched - * @param ConstraintInterface $constraint The constraint to verify * @return bool */ public function match(BasePackage $candidate, $name, ConstraintInterface $constraint = null) diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index e0a06dc27..ef78a44e4 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -18,12 +18,13 @@ use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\CompleteAliasPackage; use Composer\Package\CompletePackage; -use Composer\Package\CompletePackageInterface; use Composer\Package\PackageInterface; use Composer\Package\Version\StabilityFilter; use Composer\Plugin\PluginEvents; use Composer\Plugin\PrePoolCreateEvent; +use Composer\Repository\LockArrayRepository; use Composer\Repository\PlatformRepository; +use Composer\Repository\RepositoryInterface; use Composer\Repository\RootPackageRepository; use Composer\Semver\CompilingMatcher; use Composer\Semver\Constraint\Constraint; @@ -86,12 +87,11 @@ class PoolBuilder */ private $loadedPerRepo = array(); /** - * @var PackageInterface[] + * @var BasePackage[] */ private $packages = array(); /** - * @var PackageInterface[] - * @phpstan-var list + * @var BasePackage[] */ private $unacceptableFixedOrLockedPackages = array(); /** @var string[] */ @@ -140,6 +140,7 @@ class PoolBuilder } /** + * @param RepositoryInterface[] $repositories * @return Pool */ public function buildPool(array $repositories, Request $request) @@ -265,6 +266,7 @@ class PoolBuilder } /** + * @param string $name * @return void */ private function markPackageNameForLoading(Request $request, $name, ConstraintInterface $constraint) @@ -323,6 +325,7 @@ class PoolBuilder } /** + * @param RepositoryInterface[] $repositories * @return void */ private function loadPackagesMarkedForLoading(Request $request, $repositories) @@ -358,6 +361,7 @@ class PoolBuilder } /** + * @param bool $propagateUpdate * @return void */ private function loadPackage(Request $request, BasePackage $package, $propagateUpdate = true) @@ -446,6 +450,7 @@ class PoolBuilder /** * Checks if a particular name is required directly in the request * + * @param string $name packageName * @return bool */ private function isRootRequire(Request $request, $name) @@ -460,7 +465,7 @@ class PoolBuilder * * @return bool */ - private function isUpdateAllowed(PackageInterface $package) + private function isUpdateAllowed(BasePackage $package) { // Path repo packages are never loaded from lock, to force them to always remain in sync // unless symlinking is disabled in which case we probably should rather treat them like @@ -513,6 +518,7 @@ class PoolBuilder * Reverts the decision to use a locked package if a partial update with transitive dependencies * found that this package actually needs to be updated * + * @param string $name * @return void */ private function unlockPackage(Request $request, $name) @@ -553,9 +559,10 @@ class PoolBuilder } /** + * @param int $index * @return void */ - private function removeLoadedPackage(Request $request, PackageInterface $package, $index) + private function removeLoadedPackage(Request $request, BasePackage $package, $index) { unset($this->packages[$index]); if (isset($this->aliasMap[spl_object_hash($package)])) { diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index 076c3a2a4..a759ac8cc 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -14,6 +14,8 @@ namespace Composer\DependencyResolver; use Composer\Package\CompletePackageInterface; use Composer\Package\AliasPackage; +use Composer\Package\BasePackage; +use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; use Composer\Repository\RepositorySet; use Composer\Repository\LockArrayRepository; @@ -47,6 +49,7 @@ class Problem * Add a rule as a reason * * @param Rule $rule A rule which is a reason for this problem + * @return void */ public function addRule(Rule $rule) { @@ -56,7 +59,7 @@ class Problem /** * Retrieve all reasons for this problem * - * @return array The problem's reasons + * @return array> The problem's reasons */ public function getReasons() { @@ -66,7 +69,9 @@ class Problem /** * A human readable textual representation of the problem's reasons * - * @param array $installedMap A map of all present packages + * @param bool $isVerbose + * @param array $installedMap A map of all present packages + * @param array $learnedPool * @return string */ public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, array $installedMap = array(), array $learnedPool = array()) @@ -101,8 +106,13 @@ class Problem } /** - * @internal + * @param Rule[] $rules + * @param string $indent + * @param bool $isVerbose + * @param array $installedMap A map of all present packages + * @param array $learnedPool * @return string + * @internal */ public static function formatDeduplicatedRules($rules, $indent, RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, array $installedMap = array(), array $learnedPool = array()) { @@ -166,7 +176,6 @@ class Problem * * @param string $id A canonical identifier for the reason * @param Rule $reason The reason descriptor - * * @return void */ protected function addReason($id, Rule $reason) @@ -190,9 +199,11 @@ class Problem /** * @internal + * @param bool $isVerbose + * @param string $packageName * @return array{0: string, 1: string} */ - public static function getMissingPackageReason(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, $packageName, $constraint = null) + public static function getMissingPackageReason(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, $packageName, ConstraintInterface $constraint = null) { // handle php/hhvm if ($packageName === 'php' || $packageName === 'php-64bit' || $packageName === 'hhvm') { @@ -343,6 +354,8 @@ class Problem /** * @internal + * @param PackageInterface[] $packages + * @param bool $isVerbose * @return string */ public static function getPackageList(array $packages, $isVerbose) @@ -395,7 +408,9 @@ class Problem } /** - * @param string[] $versions an array of pretty versions, with normalized versions as keys + * @param string[] $versions an array of pretty versions, with normalized versions as keys + * @param int $max + * @param int $maxDev * @return list a list of pretty versions and '...' where versions were removed */ private static function condenseVersionList(array $versions, $max, $maxDev = 16) @@ -429,6 +444,7 @@ class Problem } /** + * @param PackageInterface[] $packages * @return bool */ private static function hasMultipleNames(array $packages) @@ -446,6 +462,12 @@ class Problem } /** + * @param bool $isVerbose + * @param string $packageName + * @param ?ConstraintInterface $constraint + * @param PackageInterface[] $higherRepoPackages + * @param PackageInterface[] $allReposPackages + * @param string $reason * @return array{0: string, 1: string} */ private static function computeCheckForLowerPrioRepo($isVerbose, $packageName, $constraint, array $higherRepoPackages, array $allReposPackages, $reason) diff --git a/src/Composer/DependencyResolver/Request.php b/src/Composer/DependencyResolver/Request.php index 7378d9cfd..3b680ad0b 100644 --- a/src/Composer/DependencyResolver/Request.php +++ b/src/Composer/DependencyResolver/Request.php @@ -12,8 +12,8 @@ namespace Composer\DependencyResolver; -use Composer\Package\Package; use Composer\Package\BasePackage; +use Composer\Package\PackageInterface; use Composer\Repository\LockArrayRepository; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\MatchAllConstraint; @@ -60,6 +60,10 @@ class Request $this->lockedRepository = $lockedRepository; } + /** + * @param string $packageName + * @return void + */ public function requireName($packageName, ConstraintInterface $constraint = null) { $packageName = strtolower($packageName); @@ -78,6 +82,8 @@ class Request * * This is used for platform packages which cannot be modified by Composer. A rule enforcing their installation is * generated for dependency resolution. Partial updates with dependencies cannot in any way modify these packages. + * + * @return void */ public function fixPackage(BasePackage $package) { @@ -93,6 +99,8 @@ class Request * However unlike fixed packages there will not be a special rule enforcing their installation for the solver, so * if nothing requires these packages they will be removed. Additionally in a partial update these packages can be * unlocked, meaning other versions can be installed if explicitly requested as part of the update. + * + * @return void */ public function lockPackage(BasePackage $package) { @@ -105,6 +113,8 @@ class Request * This is necessary for the composer install step which verifies the lock file integrity and should not allow * removal of any packages. At the same time lock packages there cannot simply be marked fixed, as error reporting * would then report them as platform packages, so this still marks them as locked packages at the same time. + * + * @return void */ public function fixLockedPackage(BasePackage $package) { @@ -112,11 +122,19 @@ class Request $this->fixedLockedPackages[spl_object_hash($package)] = $package; } + /** + * @return void + */ public function unlockPackage(BasePackage $package) { unset($this->lockedPackages[spl_object_hash($package)]); } + /** + * @param string[] $updateAllowList + * @param false|self::UPDATE_* $updateAllowTransitiveDependencies + * @return void + */ public function setUpdateAllowList($updateAllowList, $updateAllowTransitiveDependencies) { $this->updateAllowList = $updateAllowList; @@ -182,7 +200,7 @@ class Request /** * @return bool */ - public function isLockedPackage(BasePackage $package) + public function isLockedPackage(PackageInterface $package) { return isset($this->lockedPackages[spl_object_hash($package)]) || isset($this->fixedLockedPackages[spl_object_hash($package)]); } @@ -195,10 +213,14 @@ class Request return array_merge($this->fixedPackages, $this->lockedPackages); } - // TODO look into removing the packageIds option, the only place true is used is for the installed map in the solver problems - // some locked packages may not be in the pool so they have a package->id of -1 /** + * @param bool $packageIds * @return array + * + * @TODO look into removing the packageIds option, the only place true is used + * is for the installed map in the solver problems. + * Some locked packages may not be in the pool, + * so they have a package->id of -1 */ public function getPresentMap($packageIds = false) { diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index edc486496..9dd6ccb48 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -12,11 +12,11 @@ namespace Composer\DependencyResolver; -use Composer\Package\Link; -use Composer\Package\BasePackage; use Composer\Package\AliasPackage; -use Composer\Repository\RepositorySet; +use Composer\Package\BasePackage; +use Composer\Package\Link; use Composer\Repository\PlatformRepository; +use Composer\Repository\RepositorySet; use Composer\Package\Version\VersionParser; use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\ConstraintInterface; @@ -54,8 +54,8 @@ abstract class Rule protected $reasonData; /** - * @param self::RULE_* $reason A RULE_* constant describing the reason for generating this rule - * @param Link|BasePackage|ConstraintInterface|string $reasonData + * @param self::RULE_* $reason A RULE_* constant describing the reason for generating this rule + * @param mixed $reasonData * * @phpstan-param ReasonData $reasonData */ @@ -68,26 +68,42 @@ abstract class Rule (255 << self::BITFIELD_TYPE); } + /** + * @return int[] + */ abstract public function getLiterals(); + /** + * @return int|string + */ abstract public function getHash(); abstract public function __toString(); + /** + * @param Rule $rule + * @return bool + */ abstract public function equals(Rule $rule); + /** + * @return int + */ public function getReason() { return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON; } + /** + * @phpstan-return ReasonData + */ public function getReasonData() { return $this->reasonData; } /** - * @return ?string + * @return string|null */ public function getRequiredPackage() { @@ -108,38 +124,63 @@ abstract class Rule return null; } + /** + * @param 255|RuleSet::TYPE_* $type + * @return void + */ public function setType($type) { $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE); } + /** + * @return int + */ public function getType() { return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE; } + /** + * @return void + */ public function disable() { $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED); } + /** + * @return void + */ public function enable() { $this->bitfield &= ~(255 << self::BITFIELD_DISABLED); } + /** + * @return bool + */ public function isDisabled() { return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED); } + /** + * @return bool + */ public function isEnabled() { return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED); } + /** + * @return bool + */ abstract public function isAssertion(); + /** + * @return bool + */ public function isCausedByLock(RepositorySet $repositorySet, Request $request, Pool $pool) { if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) { @@ -187,6 +228,12 @@ abstract class Rule return false; } + /** + * @param bool $isVerbose + * @param BasePackage[] $installedMap + * @param array $learnedPool + * @return string + */ public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, array $installedMap = array(), array $learnedPool = array()) { $literals = $this->getLiterals(); @@ -396,12 +443,11 @@ abstract class Rule } /** - * @param Pool $pool - * @param array $packages - * + * @param array $packages An array containing packages or literals + * @param bool $isVerbose * @return string */ - protected function formatPackagesUnique($pool, array $packages, $isVerbose) + protected function formatPackagesUnique(Pool $pool, array $packages, $isVerbose) { foreach ($packages as $index => $package) { if (!\is_object($package)) { @@ -412,6 +458,9 @@ abstract class Rule return Problem::getPackageList($packages, $isVerbose); } + /** + * @return BasePackage + */ private function deduplicateDefaultBranchAlias(BasePackage $package) { if ($package instanceof AliasPackage && $package->getPrettyVersion() === VersionParser::DEFAULT_BRANCH_ALIAS) { diff --git a/src/Composer/DependencyResolver/Rule2Literals.php b/src/Composer/DependencyResolver/Rule2Literals.php index 6a4c599ce..cf5e20792 100644 --- a/src/Composer/DependencyResolver/Rule2Literals.php +++ b/src/Composer/DependencyResolver/Rule2Literals.php @@ -12,11 +12,9 @@ namespace Composer\DependencyResolver; -use Composer\Package\BasePackage; -use Composer\Package\Link; - /** * @author Nils Adermann + * @phpstan-import-type ReasonData from Rule */ class Rule2Literals extends Rule { @@ -26,8 +24,12 @@ class Rule2Literals extends Rule protected $literal2; /** - * @param int $literal1 - * @param int $literal2 + * @param int $literal1 + * @param int $literal2 + * @param Rule::RULE_* $reason A RULE_* constant + * @param mixed $reasonData + * + * @phpstan-param ReasonData $reasonData */ public function __construct($literal1, $literal2, $reason, $reasonData) { @@ -48,7 +50,9 @@ class Rule2Literals extends Rule return array($this->literal1, $this->literal2); } - /** @return string */ + /** + * @inheritDoc + */ public function getHash() { return $this->literal1.','.$this->literal2; diff --git a/src/Composer/DependencyResolver/RuleSet.php b/src/Composer/DependencyResolver/RuleSet.php index 9d75dac70..a34c76bb6 100644 --- a/src/Composer/DependencyResolver/RuleSet.php +++ b/src/Composer/DependencyResolver/RuleSet.php @@ -56,6 +56,10 @@ class RuleSet implements \IteratorAggregate, \Countable } } + /** + * @param 255|self::TYPE_* $type + * @return void + */ public function add(Rule $rule, $type) { if (!isset(self::$types[$type])) { @@ -110,6 +114,7 @@ class RuleSet implements \IteratorAggregate, \Countable } /** + * @param int $id * @return Rule */ public function ruleById($id) @@ -155,6 +160,7 @@ class RuleSet implements \IteratorAggregate, \Countable } /** + * @param array|self::TYPE_* $types * @return RuleSetIterator */ public function getIteratorWithout($types) @@ -182,6 +188,7 @@ class RuleSet implements \IteratorAggregate, \Countable } /** + * @param bool $isVerbose * @return string */ public function getPrettyString(RepositorySet $repositorySet = null, Request $request = null, Pool $pool = null, $isVerbose = false) diff --git a/src/Composer/DependencyResolver/RuleSetGenerator.php b/src/Composer/DependencyResolver/RuleSetGenerator.php index 2c6a94803..d0e4554b5 100644 --- a/src/Composer/DependencyResolver/RuleSetGenerator.php +++ b/src/Composer/DependencyResolver/RuleSetGenerator.php @@ -14,7 +14,6 @@ namespace Composer\DependencyResolver; use Composer\Package\BasePackage; use Composer\Package\AliasPackage; -use Composer\Package\PackageInterface; use Composer\Repository\PlatformRepository; /** @@ -29,9 +28,9 @@ class RuleSetGenerator protected $pool; /** @var RuleSet */ protected $rules; - /** @var array */ + /** @var array */ protected $addedMap = array(); - /** @var array */ + /** @var array */ protected $addedPackagesByNames = array(); public function __construct(PolicyInterface $policy, Pool $pool) @@ -47,13 +46,11 @@ class RuleSetGenerator * This rule is of the form (-A|B|C), where B and C are the providers of * one requirement of the package A. * - * @param BasePackage $package The package with a requirement - * @param array $providers The providers of the requirement - * @param Rule::RULE_* $reason A RULE_* constant describing the - * reason for generating this rule - * @param mixed $reasonData Any data, e.g. the requirement name, - * that goes with the reason - * @return Rule|null The generated rule or null if tautological + * @param BasePackage $package The package with a requirement + * @param BasePackage[] $providers The providers of the requirement + * @param Rule::RULE_* $reason A RULE_* constant describing the reason for generating this rule + * @param mixed $reasonData Any data, e.g. the requirement name, that goes with the reason + * @return Rule|null The generated rule or null if tautological * * @phpstan-param ReasonData $reasonData */ @@ -102,13 +99,11 @@ class RuleSetGenerator * The rule for conflicting packages A and B is (-A|-B). A is called the issuer * and B the provider. * - * @param BasePackage $issuer The package declaring the conflict - * @param BasePackage $provider The package causing the conflict - * @param Rule::RULE_* $reason A RULE_* constant describing the - * reason for generating this rule - * @param mixed $reasonData Any data, e.g. the package name, that - * goes with the reason - * @return Rule|null The generated rule + * @param BasePackage $issuer The package declaring the conflict + * @param BasePackage $provider The package causing the conflict + * @param Rule::RULE_* $reason A RULE_* constant describing the reason for generating this rule + * @param mixed $reasonData Any data, e.g. the package name, that goes with the reason + * @return ?Rule The generated rule * * @phpstan-param ReasonData $reasonData */ @@ -123,9 +118,14 @@ class RuleSetGenerator } /** + * @param BasePackage[] $packages + * @param Rule::RULE_* $reason A RULE_* constant + * @param mixed $reasonData * @return Rule + * + * @phpstan-param ReasonData $reasonData */ - protected function createMultiConflictRule(array $packages, $reason, $reasonData = null) + protected function createMultiConflictRule(array $packages, $reason, $reasonData) { $literals = array(); foreach ($packages as $package) { @@ -145,7 +145,7 @@ class RuleSetGenerator * To be able to directly pass in the result of one of the rule creation * methods null is allowed which will not insert a rule. * - * @param int $type A TYPE_* constant defining the rule type + * @param 255|RuleSet::TYPE_* $type A TYPE_* constant defining the rule type * @param Rule $newRule The rule about to be added * * @return void @@ -160,6 +160,7 @@ class RuleSetGenerator } /** + * @param bool|string[] $ignorePlatformReqs * @return void */ protected function addRulesForPackage(BasePackage $package, $ignorePlatformReqs) @@ -211,6 +212,7 @@ class RuleSetGenerator } /** + * @param bool|string[] $ignorePlatformReqs * @return void */ protected function addConflictRules($ignorePlatformReqs = false) @@ -249,6 +251,7 @@ class RuleSetGenerator } /** + * @param bool|string[] $ignorePlatformReqs * @return void */ protected function addRulesForRequest(Request $request, $ignorePlatformReqs) @@ -293,6 +296,7 @@ class RuleSetGenerator } /** + * @param bool|string[] $ignorePlatformReqs * @return void */ protected function addRulesForRootAliases($ignorePlatformReqs) @@ -311,7 +315,7 @@ class RuleSetGenerator } /** - * @param bool|array $ignorePlatformReqs + * @param bool|string[] $ignorePlatformReqs * @return RuleSet */ public function getRulesFor(Request $request, $ignorePlatformReqs = false) diff --git a/src/Composer/DependencyResolver/RuleWatchChain.php b/src/Composer/DependencyResolver/RuleWatchChain.php index 52795ea89..a03aaf2f6 100644 --- a/src/Composer/DependencyResolver/RuleWatchChain.php +++ b/src/Composer/DependencyResolver/RuleWatchChain.php @@ -27,6 +27,7 @@ class RuleWatchChain extends \SplDoublyLinkedList * Moves the internal iterator to the specified offset * * @param int $offset The offset to seek to. + * @return void */ public function seek($offset) { @@ -41,6 +42,8 @@ class RuleWatchChain extends \SplDoublyLinkedList * incorrectly sets the internal iterator if you delete the current value * this method sets the internal iterator back to the following element * using the seek method. + * + * @return void */ public function remove() { diff --git a/src/Composer/DependencyResolver/RuleWatchGraph.php b/src/Composer/DependencyResolver/RuleWatchGraph.php index 76b6abb55..e9e3caa17 100644 --- a/src/Composer/DependencyResolver/RuleWatchGraph.php +++ b/src/Composer/DependencyResolver/RuleWatchGraph.php @@ -38,6 +38,7 @@ class RuleWatchGraph * watch changes in any literals. * * @param RuleWatchNode $node The rule node to be inserted into the graph + * @return void */ public function insert(RuleWatchNode $node) { @@ -87,7 +88,7 @@ class RuleWatchGraph * register decisions resulting from propagation * @return Rule|null If a conflict is found the conflicting rule is returned */ - public function propagateLiteral($decidedLiteral, $level, $decisions) + public function propagateLiteral($decidedLiteral, $level, Decisions $decisions) { // we invert the decided literal here, example: // A was decided => (-A|B) now requires B to be true, so we look for @@ -153,6 +154,7 @@ class RuleWatchGraph * @param int $fromLiteral A literal the node used to watch * @param int $toLiteral A literal the node should watch now * @param RuleWatchNode $node The rule node to be moved + * @return void */ protected function moveWatch($fromLiteral, $toLiteral, RuleWatchNode $node) { diff --git a/src/Composer/DependencyResolver/RuleWatchNode.php b/src/Composer/DependencyResolver/RuleWatchNode.php index 24fccd8d3..a0abf254d 100644 --- a/src/Composer/DependencyResolver/RuleWatchNode.php +++ b/src/Composer/DependencyResolver/RuleWatchNode.php @@ -52,6 +52,7 @@ class RuleWatchNode * likely to quickly lead to further decisions. * * @param Decisions $decisions The decisions made so far by the solver + * @return void */ public function watch2OnHighest(Decisions $decisions) { @@ -104,6 +105,7 @@ class RuleWatchNode * * @param int $from The previously watched literal * @param int $to The literal to be watched now + * @return void */ public function moveWatch($from, $to) { diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 830ee826c..c8979748b 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -56,11 +56,6 @@ class Solver /** @var IOInterface */ protected $io; - /** - * @param PolicyInterface $policy - * @param Pool $pool - * @param IOInterface $io - */ public function __construct(PolicyInterface $policy, Pool $pool, IOInterface $io) { $this->io = $io; @@ -171,9 +166,7 @@ class Solver } /** - * @param Request $request - * @param bool|array $ignorePlatformReqs - * + * @param bool|string[] $ignorePlatformReqs * @return void */ protected function checkForRootRequireProblems(Request $request, $ignorePlatformReqs) @@ -192,8 +185,7 @@ class Solver } /** - * @param Request $request - * @param bool|array $ignorePlatformReqs + * @param bool|string[] $ignorePlatformReqs * @return LockTransaction */ public function solve(Request $request, $ignorePlatformReqs = false) @@ -304,7 +296,6 @@ class Solver * * @param int $level * @param string|int $literal - * @param Rule $rule * @return int */ private function setPropagateLearn($level, $literal, Rule $rule) @@ -332,11 +323,6 @@ class Solver "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."." ); } - if (!$newRule) { - throw new SolverBugException( - "No rule was learned from analyzing $rule at level $level." - ); - } $level = $newLevel; @@ -358,8 +344,7 @@ class Solver /** * @param int $level - * @param array $decisionQueue - * @param Rule $rule + * @param int[] $decisionQueue * @return int */ private function selectAndInstall($level, array $decisionQueue, Rule $rule) @@ -379,8 +364,7 @@ class Solver /** * @param int $level - * @param Rule $rule - * @return array + * @return array{int, int, GenericRule, int} */ protected function analyze($level, Rule $rule) { @@ -527,6 +511,7 @@ class Solver } /** + * @param array $ruleSeen * @return void */ private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule, array &$ruleSeen) @@ -557,7 +542,6 @@ class Solver } /** - * @param Rule $conflictRule * @return int */ private function analyzeUnsolvable(Rule $conflictRule) diff --git a/src/Composer/DependencyResolver/SolverBugException.php b/src/Composer/DependencyResolver/SolverBugException.php index 6920411f5..31932a265 100644 --- a/src/Composer/DependencyResolver/SolverBugException.php +++ b/src/Composer/DependencyResolver/SolverBugException.php @@ -17,6 +17,9 @@ namespace Composer\DependencyResolver; */ class SolverBugException extends \RuntimeException { + /** + * @param string $message + */ public function __construct($message) { parent::__construct( diff --git a/src/Composer/DependencyResolver/SolverProblemsException.php b/src/Composer/DependencyResolver/SolverProblemsException.php index ec86c5fa3..d332fee58 100644 --- a/src/Composer/DependencyResolver/SolverProblemsException.php +++ b/src/Composer/DependencyResolver/SolverProblemsException.php @@ -14,7 +14,6 @@ namespace Composer\DependencyResolver; use Composer\Util\IniHelper; use Composer\Repository\RepositorySet; -use Composer\Package\PackageInterface; /** * @author Nils Adermann @@ -29,7 +28,7 @@ class SolverProblemsException extends \RuntimeException protected $learnedPool; /** - * @param Problem[] $problems + * @param Problem[] $problems * @param array $learnedPool */ public function __construct(array $problems, array $learnedPool) @@ -41,6 +40,8 @@ class SolverProblemsException extends \RuntimeException } /** + * @param bool $isVerbose + * @param bool $isDevExtraction * @return string */ public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, $isDevExtraction = false) @@ -123,6 +124,7 @@ class SolverProblemsException extends \RuntimeException } /** + * @param Rule[][] $reasonSets * @return bool */ private function hasExtensionProblems(array $reasonSets) diff --git a/src/Composer/DependencyResolver/Transaction.php b/src/Composer/DependencyResolver/Transaction.php index 1cda16927..ef9c74174 100644 --- a/src/Composer/DependencyResolver/Transaction.php +++ b/src/Composer/DependencyResolver/Transaction.php @@ -46,6 +46,10 @@ class Transaction */ protected $resultPackagesByName = array(); + /** + * @param PackageInterface[] $presentPackages + * @param PackageInterface[] $resultPackages + */ public function __construct($presentPackages, $resultPackages) { $this->presentPackages = $presentPackages; @@ -53,12 +57,18 @@ class Transaction $this->operations = $this->calculateOperations(); } - /** @return OperationInterface[] */ + /** + * @return OperationInterface[] + */ public function getOperations() { return $this->operations; } + /** + * @param PackageInterface[] $resultPackages + * @return void + */ private function setResultPackageMaps($resultPackages) { $packageSort = function (PackageInterface $a, PackageInterface $b) { @@ -88,6 +98,9 @@ class Transaction } } + /** + * @return OperationInterface[] + */ protected function calculateOperations() { $operations = array(); @@ -228,6 +241,9 @@ class Transaction return $roots; } + /** + * @return PackageInterface[] + */ protected function getProvidersInResult(Link $link) { if (!isset($this->resultPackagesByName[$link->getTarget()])) { diff --git a/src/Composer/Plugin/PrePoolCreateEvent.php b/src/Composer/Plugin/PrePoolCreateEvent.php index baa4bc985..109462fca 100644 --- a/src/Composer/Plugin/PrePoolCreateEvent.php +++ b/src/Composer/Plugin/PrePoolCreateEvent.php @@ -15,7 +15,6 @@ namespace Composer\Plugin; use Composer\EventDispatcher\Event; use Composer\Repository\RepositoryInterface; use Composer\DependencyResolver\Request; -use Composer\Package\PackageInterface; use Composer\Package\BasePackage; /** @@ -54,11 +53,11 @@ class PrePoolCreateEvent extends Event */ private $rootReferences; /** - * @var PackageInterface[] + * @var BasePackage[] */ private $packages; /** - * @var PackageInterface[] + * @var BasePackage[] */ private $unacceptableFixedPackages; @@ -69,6 +68,8 @@ class PrePoolCreateEvent extends Event * @param int[] $stabilityFlags array of package name => BasePackage::STABILITY_* value * @param array[] $rootAliases array of package => version => [alias, alias_normalized] * @param string[] $rootReferences + * @param BasePackage[] $packages + * @param BasePackage[] $unacceptableFixedPackages * * @phpstan-param array $acceptableStabilities * @phpstan-param array $stabilityFlags @@ -142,7 +143,7 @@ class PrePoolCreateEvent extends Event } /** - * @return PackageInterface[] + * @return BasePackage[] */ public function getPackages() { @@ -150,7 +151,7 @@ class PrePoolCreateEvent extends Event } /** - * @return PackageInterface[] + * @return BasePackage[] */ public function getUnacceptableFixedPackages() { @@ -158,7 +159,7 @@ class PrePoolCreateEvent extends Event } /** - * @param PackageInterface[] $packages + * @param BasePackage[] $packages */ public function setPackages(array $packages) { @@ -166,7 +167,7 @@ class PrePoolCreateEvent extends Event } /** - * @param PackageInterface[] $packages + * @param BasePackage[] $packages */ public function setUnacceptableFixedPackages(array $packages) { diff --git a/tests/Composer/Test/DependencyResolver/RuleSetTest.php b/tests/Composer/Test/DependencyResolver/RuleSetTest.php index 68ac43ad1..1cdd83a9b 100644 --- a/tests/Composer/Test/DependencyResolver/RuleSetTest.php +++ b/tests/Composer/Test/DependencyResolver/RuleSetTest.php @@ -68,6 +68,7 @@ class RuleSetTest extends TestCase $ruleSet = new RuleSet; $this->setExpectedException('OutOfBoundsException'); + // @phpstan-ignore-next-line $ruleSet->add(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)), 7); }