1
0
Fork 0
mirror of https://github.com/composer/composer synced 2025-05-10 17:12:51 +00:00

Add more type annotations

This commit is contained in:
Jordi Boggiano 2021-09-05 16:02:10 +02:00
parent dd49db6f08
commit 4bcd860b65
No known key found for this signature in database
GPG key ID: 7BBD42C429EC80BC
29 changed files with 217 additions and 119 deletions

View file

@ -16,17 +16,21 @@ namespace Composer\DependencyResolver;
* Stores decisions on installing, removing or keeping packages * Stores decisions on installing, removing or keeping packages
* *
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
* @implements \Iterator<array{0: int, 1: mixed}>
*/ */
class Decisions implements \Iterator, \Countable class Decisions implements \Iterator, \Countable
{ {
const DECISION_LITERAL = 0; const DECISION_LITERAL = 0;
const DECISION_REASON = 1; const DECISION_REASON = 1;
/** @var Pool */
protected $pool; protected $pool;
/** @var array<int, int> */
protected $decisionMap; protected $decisionMap;
/** @var array<array{0: int, 1: mixed}> */
protected $decisionQueue = array(); protected $decisionQueue = array();
public function __construct($pool) public function __construct(Pool $pool)
{ {
$this->pool = $pool; $this->pool = $pool;
$this->decisionMap = array(); $this->decisionMap = array();

View file

@ -23,7 +23,9 @@ use Composer\Semver\Constraint\Constraint;
*/ */
class DefaultPolicy implements PolicyInterface class DefaultPolicy implements PolicyInterface
{ {
/** @var bool */
private $preferStable; private $preferStable;
/** @var bool */
private $preferLowest; private $preferLowest;
public function __construct($preferStable = false, $preferLowest = false) public function __construct($preferStable = false, $preferLowest = false)

View file

@ -21,14 +21,11 @@ use Composer\Semver\Constraint\ConstraintInterface;
*/ */
class GenericRule extends Rule class GenericRule extends Rule
{ {
/** @var int[] */
protected $literals; protected $literals;
/** /**
* @param array $literals * @param int[] $literals
* @param int|null $reason A RULE_* constant describing the reason for generating this rule
* @param Link|BasePackage|int|null|array $reasonData
*
* @phpstan-param Link|BasePackage|int|null|array{packageName: string, constraint: ConstraintInterface} $reasonData
*/ */
public function __construct(array $literals, $reason, $reasonData) public function __construct(array $literals, $reason, $reasonData)
{ {

View file

@ -22,12 +22,11 @@ use Composer\Package\Link;
*/ */
class MultiConflictRule extends Rule class MultiConflictRule extends Rule
{ {
/** @var int[] */
protected $literals; protected $literals;
/** /**
* @param array $literals * @param int[] $literals
* @param int $reason A RULE_* constant describing the reason for generating this rule
* @param Link|BasePackage $reasonData
*/ */
public function __construct(array $literals, $reason, $reasonData) public function __construct(array $literals, $reason, $reasonData)
{ {

View file

@ -30,7 +30,9 @@ class Pool implements \Countable
protected $packages = array(); protected $packages = array();
/** @var array<string, BasePackage[]> */ /** @var array<string, BasePackage[]> */
protected $packageByName = array(); protected $packageByName = array();
/** @var VersionParser */
protected $versionParser; protected $versionParser;
/** @var array<string, array<string, BasePackage[]>> */
protected $providerCache = array(); protected $providerCache = array();
/** @var BasePackage[] */ /** @var BasePackage[] */
protected $unacceptableFixedOrLockedPackages; protected $unacceptableFixedOrLockedPackages;

View file

@ -94,7 +94,9 @@ class PoolBuilder
* @phpstan-var list<PackageInterface> * @phpstan-var list<PackageInterface>
*/ */
private $unacceptableFixedOrLockedPackages = array(); private $unacceptableFixedOrLockedPackages = array();
/** @var string[] */
private $updateAllowList = array(); private $updateAllowList = array();
/** @var array<string, string> */
private $skippedLoad = array(); private $skippedLoad = array();
/** /**
@ -104,6 +106,8 @@ class PoolBuilder
* *
* Packages get cleared from this list if they get unlocked as in that case * Packages get cleared from this list if they get unlocked as in that case
* we need to actually load them * we need to actually load them
*
* @var array<string, true>
*/ */
private $maxExtendedReqs = array(); private $maxExtendedReqs = array();
/** /**
@ -112,6 +116,7 @@ class PoolBuilder
*/ */
private $updateAllowWarned = array(); private $updateAllowWarned = array();
/** @var int */
private $indexCounter = 0; private $indexCounter = 0;
/** /**

View file

@ -30,16 +30,17 @@ class Problem
{ {
/** /**
* A map containing the id of each rule part of this problem as a key * A map containing the id of each rule part of this problem as a key
* @var array * @var array<string, true>
*/ */
protected $reasonSeen; protected $reasonSeen;
/** /**
* A set of reasons for the problem, each is a rule or a root require and a rule * A set of reasons for the problem, each is a rule or a root require and a rule
* @var array * @var array<int, array<int, Rule>>
*/ */
protected $reasons = array(); protected $reasons = array();
/** @var int */
protected $section = 0; protected $section = 0;
/** /**

View file

@ -40,12 +40,19 @@ class Request
*/ */
const UPDATE_LISTED_WITH_TRANSITIVE_DEPS = 2; const UPDATE_LISTED_WITH_TRANSITIVE_DEPS = 2;
/** @var ?LockArrayRepository */
protected $lockedRepository; protected $lockedRepository;
/** @var array<string, ConstraintInterface> */
protected $requires = array(); protected $requires = array();
/** @var array<string, PackageInterface> */
protected $fixedPackages = array(); protected $fixedPackages = array();
/** @var array<string, PackageInterface> */
protected $lockedPackages = array(); protected $lockedPackages = array();
/** @var array<string, PackageInterface> */
protected $fixedLockedPackages = array(); protected $fixedLockedPackages = array();
/** @var string[] */
protected $updateAllowList = array(); protected $updateAllowList = array();
/** @var false|self::UPDATE_* */
protected $updateAllowTransitiveDependencies = false; protected $updateAllowTransitiveDependencies = false;
public function __construct(LockArrayRepository $lockedRepository = null) public function __construct(LockArrayRepository $lockedRepository = null)
@ -169,12 +176,12 @@ class Request
if ($this->lockedRepository) { if ($this->lockedRepository) {
foreach ($this->lockedRepository->getPackages() as $package) { foreach ($this->lockedRepository->getPackages() as $package) {
$presentMap[$packageIds ? $package->id : spl_object_hash($package)] = $package; $presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
} }
} }
foreach ($this->fixedPackages as $package) { foreach ($this->fixedPackages as $package) {
$presentMap[$packageIds ? $package->id : spl_object_hash($package)] = $package; $presentMap[$packageIds ? $package->getId() : spl_object_hash($package)] = $package;
} }
return $presentMap; return $presentMap;
@ -185,7 +192,7 @@ class Request
$fixedPackagesMap = array(); $fixedPackagesMap = array();
foreach ($this->fixedPackages as $package) { foreach ($this->fixedPackages as $package) {
$fixedPackagesMap[$package->id] = $package; $fixedPackagesMap[$package->getId()] = $package;
} }
return $fixedPackagesMap; return $fixedPackagesMap;

View file

@ -19,35 +19,45 @@ use Composer\Repository\RepositorySet;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionParser;
use Composer\Semver\Constraint\Constraint; use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
/** /**
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
* @author Ruben Gonzalez <rubenrua@gmail.com> * @author Ruben Gonzalez <rubenrua@gmail.com>
* @phpstan-type ReasonData Link|BasePackage|string|int|array{packageName: string, constraint: ConstraintInterface}|array{package: BasePackage}
*/ */
abstract class Rule abstract class Rule
{ {
// reason constants // reason constants and // their reason data contents
const RULE_ROOT_REQUIRE = 2; const RULE_ROOT_REQUIRE = 2; // array{packageName: string, constraint: ConstraintInterface}
const RULE_FIXED = 3; const RULE_FIXED = 3; // array{package: BasePackage}
const RULE_PACKAGE_CONFLICT = 6; const RULE_PACKAGE_CONFLICT = 6; // Link
const RULE_PACKAGE_REQUIRES = 7; const RULE_PACKAGE_REQUIRES = 7; // Link
const RULE_PACKAGE_SAME_NAME = 10; const RULE_PACKAGE_SAME_NAME = 10; // string (package name)
const RULE_LEARNED = 12; const RULE_LEARNED = 12; // int (rule id)
const RULE_PACKAGE_ALIAS = 13; const RULE_PACKAGE_ALIAS = 13; // BasePackage
const RULE_PACKAGE_INVERSE_ALIAS = 14; const RULE_PACKAGE_INVERSE_ALIAS = 14; // BasePackage
// bitfield defs // bitfield defs
const BITFIELD_TYPE = 0; const BITFIELD_TYPE = 0;
const BITFIELD_REASON = 8; const BITFIELD_REASON = 8;
const BITFIELD_DISABLED = 16; const BITFIELD_DISABLED = 16;
/** @var int */
protected $bitfield; protected $bitfield;
/** @var Request */
protected $request; protected $request;
/**
* @var Link|BasePackage|ConstraintInterface|string
* @phpstan-var ReasonData
*/
protected $reasonData; protected $reasonData;
/** /**
* @param int $reason A RULE_* constant describing the reason for generating this rule * @param self::RULE_* $reason A RULE_* constant describing the reason for generating this rule
* @param Link|BasePackage $reasonData * @param Link|BasePackage|ConstraintInterface|string $reasonData
*
* @phpstan-param ReasonData $reasonData
*/ */
public function __construct($reason, $reasonData) public function __construct($reason, $reasonData)
{ {
@ -253,17 +263,19 @@ abstract class Rule
case self::RULE_PACKAGE_REQUIRES: case self::RULE_PACKAGE_REQUIRES:
$sourceLiteral = array_shift($literals); $sourceLiteral = array_shift($literals);
$sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral)); $sourcePackage = $this->deduplicateDefaultBranchAlias($pool->literalToPackage($sourceLiteral));
/** @var Link */
$reasonData = $this->reasonData;
$requires = array(); $requires = array();
foreach ($literals as $literal) { foreach ($literals as $literal) {
$requires[] = $pool->literalToPackage($literal); $requires[] = $pool->literalToPackage($literal);
} }
$text = $this->reasonData->getPrettyString($sourcePackage); $text = $reasonData->getPrettyString($sourcePackage);
if ($requires) { if ($requires) {
$text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose) . '.'; $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires, $isVerbose) . '.';
} else { } else {
$targetName = $this->reasonData->getTarget(); $targetName = $reasonData->getTarget();
$reason = Problem::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $targetName, $this->reasonData->getConstraint()); $reason = Problem::getMissingPackageReason($repositorySet, $request, $pool, $isVerbose, $targetName, $this->reasonData->getConstraint());

View file

@ -20,14 +20,14 @@ use Composer\Package\Link;
*/ */
class Rule2Literals extends Rule class Rule2Literals extends Rule
{ {
/** @var int */
protected $literal1; protected $literal1;
/** @var int */
protected $literal2; protected $literal2;
/** /**
* @param int $literal1 * @param int $literal1
* @param int $literal2 * @param int $literal2
* @param int $reason A RULE_* constant describing the reason for generating this rule
* @param Link|BasePackage $reasonData
*/ */
public function __construct($literal1, $literal2, $reason, $reasonData) public function __construct($literal1, $literal2, $reason, $reasonData)
{ {
@ -42,11 +42,13 @@ class Rule2Literals extends Rule
} }
} }
/** @return int[] */
public function getLiterals() public function getLiterals()
{ {
return array($this->literal1, $this->literal2); return array($this->literal1, $this->literal2);
} }
/** @return string */
public function getHash() public function getHash()
{ {
return $this->literal1.','.$this->literal2; return $this->literal1.','.$this->literal2;
@ -91,6 +93,7 @@ class Rule2Literals extends Rule
return true; return true;
} }
/** @return false */
public function isAssertion() public function isAssertion()
{ {
return false; return false;

View file

@ -16,6 +16,7 @@ use Composer\Repository\RepositorySet;
/** /**
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
* @implements \IteratorAggregate<Rule>
*/ */
class RuleSet implements \IteratorAggregate, \Countable class RuleSet implements \IteratorAggregate, \Countable
{ {
@ -27,10 +28,11 @@ class RuleSet implements \IteratorAggregate, \Countable
/** /**
* READ-ONLY: Lookup table for rule id to rule object * READ-ONLY: Lookup table for rule id to rule object
* *
* @var Rule[] * @var array<int, Rule>
*/ */
public $ruleById; public $ruleById = array();
/** @var array<255|0|1|4, string> */
protected static $types = array( protected static $types = array(
255 => 'UNKNOWN', 255 => 'UNKNOWN',
self::TYPE_PACKAGE => 'PACKAGE', self::TYPE_PACKAGE => 'PACKAGE',
@ -38,20 +40,20 @@ class RuleSet implements \IteratorAggregate, \Countable
self::TYPE_LEARNED => 'LEARNED', self::TYPE_LEARNED => 'LEARNED',
); );
/** @var array<self::TYPE_*, Rule[]> */
protected $rules; protected $rules;
protected $nextRuleId;
protected $rulesByHash; /** @var int */
protected $nextRuleId = 0;
/** @var array<string, Rule|Rule[]> */
protected $rulesByHash = array();
public function __construct() public function __construct()
{ {
$this->nextRuleId = 0;
foreach ($this->getTypes() as $type) { foreach ($this->getTypes() as $type) {
$this->rules[$type] = array(); $this->rules[$type] = array();
} }
$this->rulesByHash = array();
} }
public function add(Rule $rule, $type) public function add(Rule $rule, $type)
@ -109,6 +111,7 @@ class RuleSet implements \IteratorAggregate, \Countable
return $this->ruleById[$id]; return $this->ruleById[$id];
} }
/** @return array<self::TYPE_*, Rule[]> */
public function getRules() public function getRules()
{ {
return $this->rules; return $this->rules;
@ -123,6 +126,10 @@ class RuleSet implements \IteratorAggregate, \Countable
return new RuleSetIterator($this->getRules()); return new RuleSetIterator($this->getRules());
} }
/**
* @param self::TYPE_*|array<self::TYPE_*> $types
* @return RuleSetIterator
*/
public function getIteratorFor($types) public function getIteratorFor($types)
{ {
if (!\is_array($types)) { if (!\is_array($types)) {
@ -130,6 +137,8 @@ class RuleSet implements \IteratorAggregate, \Countable
} }
$allRules = $this->getRules(); $allRules = $this->getRules();
/** @var array<self::TYPE_*, Rule[]> $rules */
$rules = array(); $rules = array();
foreach ($types as $type) { foreach ($types as $type) {
@ -154,6 +163,7 @@ class RuleSet implements \IteratorAggregate, \Countable
return new RuleSetIterator($rules); return new RuleSetIterator($rules);
} }
/** @return array{0: 0, 1: 1, 2: 4} */
public function getTypes() public function getTypes()
{ {
$types = self::$types; $types = self::$types;

View file

@ -14,25 +14,31 @@ namespace Composer\DependencyResolver;
use Composer\Package\BasePackage; use Composer\Package\BasePackage;
use Composer\Package\AliasPackage; use Composer\Package\AliasPackage;
use Composer\Package\PackageInterface;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
/** /**
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
* @phpstan-import-type ReasonData from Rule
*/ */
class RuleSetGenerator class RuleSetGenerator
{ {
/** @var PolicyInterface */
protected $policy; protected $policy;
/** @var Pool */
protected $pool; protected $pool;
/** @var RuleSet */
protected $rules; protected $rules;
protected $addedMap; /** @var array<int, PackageInterface> */
protected $conflictAddedMap; protected $addedMap = array();
protected $addedPackagesByNames; /** @var array<string, PackageInterface[]> */
protected $conflictsForName; protected $addedPackagesByNames = array();
public function __construct(PolicyInterface $policy, Pool $pool) public function __construct(PolicyInterface $policy, Pool $pool)
{ {
$this->policy = $policy; $this->policy = $policy;
$this->pool = $pool; $this->pool = $pool;
$this->rules = new RuleSet;
} }
/** /**
@ -43,11 +49,13 @@ class RuleSetGenerator
* *
* @param BasePackage $package The package with a requirement * @param BasePackage $package The package with a requirement
* @param array $providers The providers of the requirement * @param array $providers The providers of the requirement
* @param int $reason A RULE_* constant describing the * @param Rule::RULE_* $reason A RULE_* constant describing the
* reason for generating this rule * reason for generating this rule
* @param mixed $reasonData Any data, e.g. the requirement name, * @param mixed $reasonData Any data, e.g. the requirement name,
* that goes with the reason * that goes with the reason
* @return Rule|null The generated rule or null if tautological * @return Rule|null The generated rule or null if tautological
*
* @phpstan-param ReasonData $reasonData
*/ */
protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData = null) protected function createRequireRule(BasePackage $package, array $providers, $reason, $reasonData = null)
{ {
@ -71,10 +79,12 @@ class RuleSetGenerator
* 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 BasePackage[] $packages The set of packages to choose from
* @param int $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 array $reasonData Additional data like the root require or fix request info * @param array $reasonData Additional data like the root require or fix request info
* @return Rule The generated rule * @return Rule The generated rule
*
* @phpstan-param ReasonData $reasonData
*/ */
protected function createInstallOneOfRule(array $packages, $reason, $reasonData) protected function createInstallOneOfRule(array $packages, $reason, $reasonData)
{ {
@ -94,11 +104,13 @@ class RuleSetGenerator
* *
* @param BasePackage $issuer The package declaring the conflict * @param BasePackage $issuer The package declaring the conflict
* @param BasePackage $provider The package causing the conflict * @param BasePackage $provider The package causing the conflict
* @param int $reason A RULE_* constant describing the * @param Rule::RULE_* $reason A RULE_* constant describing the
* reason for generating this rule * reason for generating this rule
* @param mixed $reasonData Any data, e.g. the package name, that * @param mixed $reasonData Any data, e.g. the package name, that
* goes with the reason * goes with the reason
* @return Rule|null The generated rule * @return Rule|null The generated rule
*
* @phpstan-param ReasonData $reasonData
*/ */
protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData = null) protected function createRule2Literals(BasePackage $issuer, BasePackage $provider, $reason, $reasonData = null)
{ {
@ -144,11 +156,11 @@ class RuleSetGenerator
protected function addRulesForPackage(BasePackage $package, $ignorePlatformReqs) protected function addRulesForPackage(BasePackage $package, $ignorePlatformReqs)
{ {
/** @var \SplQueue<BasePackage> */
$workQueue = new \SplQueue; $workQueue = new \SplQueue;
$workQueue->enqueue($package); $workQueue->enqueue($package);
while (!$workQueue->isEmpty()) { while (!$workQueue->isEmpty()) {
/** @var BasePackage $package */
$package = $workQueue->dequeue(); $package = $workQueue->dequeue();
if (isset($this->addedMap[$package->id])) { if (isset($this->addedMap[$package->id])) {
continue; continue;
@ -286,13 +298,6 @@ class RuleSetGenerator
*/ */
public function getRulesFor(Request $request, $ignorePlatformReqs = false) public function getRulesFor(Request $request, $ignorePlatformReqs = false)
{ {
$this->rules = new RuleSet;
$this->addedMap = array();
$this->conflictAddedMap = array();
$this->addedPackagesByNames = array();
$this->conflictsForName = array();
$this->addRulesForRequest($request, $ignorePlatformReqs); $this->addRulesForRequest($request, $ignorePlatformReqs);
$this->addRulesForRootAliases($ignorePlatformReqs); $this->addRulesForRootAliases($ignorePlatformReqs);
@ -300,8 +305,12 @@ class RuleSetGenerator
$this->addConflictRules($ignorePlatformReqs); $this->addConflictRules($ignorePlatformReqs);
// Remove references to packages // Remove references to packages
$this->addedMap = $this->addedPackagesByNames = null; $this->addedMap = $this->addedPackagesByNames = array();
return $this->rules; $rules = $this->rules;
$this->rules = new RuleSet;
return $rules;
} }
} }

View file

@ -14,16 +14,25 @@ namespace Composer\DependencyResolver;
/** /**
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
* @implements \Iterator<RuleSet::TYPE_*, Rule>
*/ */
class RuleSetIterator implements \Iterator class RuleSetIterator implements \Iterator
{ {
/** @var array<RuleSet::TYPE_*, Rule[]> */
protected $rules; protected $rules;
/** @var array<RuleSet::TYPE_*> */
protected $types; protected $types;
/** @var int */
protected $currentOffset; protected $currentOffset;
/** @var RuleSet::TYPE_*|-1 */
protected $currentType; protected $currentType;
/** @var int */
protected $currentTypeOffset; protected $currentTypeOffset;
/**
* @param array<RuleSet::TYPE_*, Rule[]> $rules
*/
public function __construct(array $rules) public function __construct(array $rules)
{ {
$this->rules = $rules; $this->rules = $rules;

View file

@ -19,11 +19,10 @@ namespace Composer\DependencyResolver;
* method to set the internal iterator to a particular offset. * method to set the internal iterator to a particular offset.
* *
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
* @extends \SplDoublyLinkedList<RuleWatchNode>
*/ */
class RuleWatchChain extends \SplDoublyLinkedList class RuleWatchChain extends \SplDoublyLinkedList
{ {
protected $offset = 0;
/** /**
* Moves the internal iterator to the specified offset * Moves the internal iterator to the specified offset
* *

View file

@ -24,6 +24,7 @@ namespace Composer\DependencyResolver;
*/ */
class RuleWatchGraph class RuleWatchGraph
{ {
/** @var array<int, RuleWatchChain> */
protected $watchChains = array(); protected $watchChains = array();
/** /**
@ -153,7 +154,7 @@ class RuleWatchGraph
* @param int $toLiteral A literal the node should watch now * @param int $toLiteral A literal the node should watch now
* @param RuleWatchNode $node The rule node to be moved * @param RuleWatchNode $node The rule node to be moved
*/ */
protected function moveWatch($fromLiteral, $toLiteral, $node) protected function moveWatch($fromLiteral, $toLiteral, RuleWatchNode $node)
{ {
if (!isset($this->watchChains[$toLiteral])) { if (!isset($this->watchChains[$toLiteral])) {
$this->watchChains[$toLiteral] = new RuleWatchChain; $this->watchChains[$toLiteral] = new RuleWatchChain;

View file

@ -21,9 +21,12 @@ namespace Composer\DependencyResolver;
*/ */
class RuleWatchNode class RuleWatchNode
{ {
/** @var int */
public $watch1; public $watch1;
/** @var int */
public $watch2; public $watch2;
/** @var Rule */
protected $rule; protected $rule;
/** /**
@ -31,7 +34,7 @@ class RuleWatchNode
* *
* @param Rule $rule The rule to wrap * @param Rule $rule The rule to wrap
*/ */
public function __construct($rule) public function __construct(Rule $rule)
{ {
$this->rule = $rule; $this->rule = $rule;

View file

@ -45,9 +45,9 @@ class Solver
protected $branches = array(); protected $branches = array();
/** @var Problem[] */ /** @var Problem[] */
protected $problems = array(); protected $problems = array();
/** @var array */ /** @var array<Rule[]> */
protected $learnedPool = array(); protected $learnedPool = array();
/** @var array */ /** @var array<string, int> */
protected $learnedWhy = array(); protected $learnedWhy = array();
/** @var bool */ /** @var bool */

View file

@ -14,15 +14,22 @@ namespace Composer\DependencyResolver;
use Composer\Util\IniHelper; use Composer\Util\IniHelper;
use Composer\Repository\RepositorySet; use Composer\Repository\RepositorySet;
use Composer\Package\PackageInterface;
/** /**
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
*/ */
class SolverProblemsException extends \RuntimeException class SolverProblemsException extends \RuntimeException
{ {
/** @var Problem[] */
protected $problems; protected $problems;
/** @var array<Rule[]> */
protected $learnedPool; protected $learnedPool;
/**
* @param Problem[] $problems
* @param array<Rule[]> $learnedPool
*/
public function __construct(array $problems, array $learnedPool) public function __construct(array $problems, array $learnedPool)
{ {
$this->problems = $problems; $this->problems = $problems;

View file

@ -16,6 +16,7 @@ use Composer\Package\AliasPackage;
use Composer\Package\Link; use Composer\Package\Link;
use Composer\Package\PackageInterface; use Composer\Package\PackageInterface;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
use Composer\DependencyResolver\Operation\OperationInterface;
/** /**
* @author Nils Adermann <naderman@naderman.de> * @author Nils Adermann <naderman@naderman.de>
@ -24,24 +25,24 @@ use Composer\Repository\PlatformRepository;
class Transaction class Transaction
{ {
/** /**
* @var array * @var OperationInterface[]
*/ */
protected $operations; protected $operations;
/** /**
* Packages present at the beginning of the transaction * Packages present at the beginning of the transaction
* @var array * @var PackageInterface[]
*/ */
protected $presentPackages; protected $presentPackages;
/** /**
* Package set resulting from this transaction * Package set resulting from this transaction
* @var array * @var array<string, PackageInterface>
*/ */
protected $resultPackageMap; protected $resultPackageMap;
/** /**
* @var array * @var array<string, PackageInterface[]>
*/ */
protected $resultPackagesByName = array(); protected $resultPackagesByName = array();
@ -52,6 +53,7 @@ class Transaction
$this->operations = $this->calculateOperations(); $this->operations = $this->calculateOperations();
} }
/** @return OperationInterface[] */
public function getOperations() public function getOperations()
{ {
return $this->operations; return $this->operations;
@ -201,7 +203,7 @@ class Transaction
* These serve as a starting point to enumerate packages in a topological order despite potential cycles. * These serve as a starting point to enumerate packages in a topological order despite potential cycles.
* If there are packages with a cycle on the top level the package with the lowest name gets picked * If there are packages with a cycle on the top level the package with the lowest name gets picked
* *
* @return array * @return array<string, PackageInterface>
*/ */
protected function getRootPackages() protected function getRootPackages()
{ {
@ -245,8 +247,8 @@ class Transaction
* it at least fixes the symptoms and makes usage of composer possible (again) * it at least fixes the symptoms and makes usage of composer possible (again)
* in such scenarios. * in such scenarios.
* *
* @param Operation\OperationInterface[] $operations * @param OperationInterface[] $operations
* @return Operation\OperationInterface[] reordered operation list * @return OperationInterface[] reordered operation list
*/ */
private function movePluginsToFront(array $operations) private function movePluginsToFront(array $operations)
{ {
@ -322,8 +324,8 @@ class Transaction
* Removals of packages should be executed before installations in * Removals of packages should be executed before installations in
* case two packages resolve to the same path (due to custom installers) * case two packages resolve to the same path (due to custom installers)
* *
* @param Operation\OperationInterface[] $operations * @param OperationInterface[] $operations
* @return Operation\OperationInterface[] reordered operation list * @return OperationInterface[] reordered operation list
*/ */
private function moveUninstallsToFront(array $operations) private function moveUninstallsToFront(array $operations)
{ {

View file

@ -17,9 +17,13 @@ namespace Composer\Downloader;
*/ */
class TransportException extends \RuntimeException class TransportException extends \RuntimeException
{ {
/** @var ?array<string, string> */
protected $headers; protected $headers;
/** @var ?string */
protected $response; protected $response;
/** @var ?int */
protected $statusCode; protected $statusCode;
/** @var ?array<mixed> */
protected $responseInfo = array(); protected $responseInfo = array();
public function setHeaders($headers) public function setHeaders($headers)

View file

@ -38,7 +38,7 @@ abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterfa
protected $process; protected $process;
/** @var Filesystem */ /** @var Filesystem */
protected $filesystem; protected $filesystem;
/** @var array */ /** @var array<string, true> */
protected $hasCleanedChanges = array(); protected $hasCleanedChanges = array();
public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null) public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)

View file

@ -25,8 +25,11 @@ use ZipArchive;
*/ */
class ZipDownloader extends ArchiveDownloader class ZipDownloader extends ArchiveDownloader
{ {
/** @var array<int, array{0: string, 1: string}> */
private static $unzipCommands; private static $unzipCommands;
/** @var bool */
private static $hasZipArchive; private static $hasZipArchive;
/** @var bool */
private static $isWindows; private static $isWindows;
/** @var ZipArchive|null */ /** @var ZipArchive|null */

View file

@ -28,9 +28,13 @@ use Composer\Util\Silencer;
*/ */
class BinaryInstaller class BinaryInstaller
{ {
/** @var string */
protected $binDir; protected $binDir;
/** @var string */
protected $binCompat; protected $binCompat;
/** @var IOInterface */
protected $io; protected $io;
/** @var Filesystem */
protected $filesystem; protected $filesystem;
/** /**

View file

@ -20,6 +20,7 @@ use Composer\Util\Filesystem;
use Composer\Util\Silencer; use Composer\Util\Silencer;
use Composer\Util\Platform; use Composer\Util\Platform;
use React\Promise\PromiseInterface; use React\Promise\PromiseInterface;
use Composer\Downloader\DownloadManager;
/** /**
* Package installation manager. * Package installation manager.
@ -29,14 +30,19 @@ use React\Promise\PromiseInterface;
*/ */
class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
{ {
/** @var Composer */
protected $composer; protected $composer;
/** @var string */
protected $vendorDir; protected $vendorDir;
protected $binDir; /** @var DownloadManager */
protected $downloadManager; protected $downloadManager;
/** @var IOInterface */
protected $io; protected $io;
/** @var string */
protected $type; protected $type;
/** @var Filesystem */
protected $filesystem; protected $filesystem;
protected $binCompat; /** @var BinaryInstaller */
protected $binaryInstaller; protected $binaryInstaller;
/** /**

View file

@ -99,7 +99,7 @@ class PluginInstaller extends LibraryInstaller
return $promise->then(function () use ($self, $pluginManager, $initial, $target, $repo) { return $promise->then(function () use ($self, $pluginManager, $initial, $target, $repo) {
try { try {
Platform::workaroundFilesystemIssues(); Platform::workaroundFilesystemIssues();
$pluginManager->deactivatePackage($initial, true); $pluginManager->deactivatePackage($initial);
$pluginManager->registerPackage($target, true); $pluginManager->registerPackage($target, true);
} catch (\Exception $e) { } catch (\Exception $e) {
$self->rollbackInstall($e, $repo, $target); $self->rollbackInstall($e, $repo, $target);
@ -109,7 +109,7 @@ class PluginInstaller extends LibraryInstaller
public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package) public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
{ {
$this->composer->getPluginManager()->uninstallPackage($package, true); $this->composer->getPluginManager()->uninstallPackage($package);
return parent::uninstall($repo, $package); return parent::uninstall($repo, $package);
} }

View file

@ -17,6 +17,7 @@ use Composer\DependencyResolver\Rule;
use Composer\DependencyResolver\RuleSet; use Composer\DependencyResolver\RuleSet;
use Composer\DependencyResolver\RuleSetIterator; use Composer\DependencyResolver\RuleSetIterator;
use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Pool;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Test\TestCase; use Composer\Test\TestCase;
class RuleSetIteratorTest extends TestCase class RuleSetIteratorTest extends TestCase
@ -30,11 +31,11 @@ class RuleSetIteratorTest extends TestCase
$this->rules = array( $this->rules = array(
RuleSet::TYPE_REQUEST => array( RuleSet::TYPE_REQUEST => array(
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null), new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null), new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
), ),
RuleSet::TYPE_LEARNED => array( RuleSet::TYPE_LEARNED => array(
new GenericRule(array(), Rule::RULE_LEARNED, null), new GenericRule(array(), Rule::RULE_LEARNED, 1),
), ),
RuleSet::TYPE_PACKAGE => array(), RuleSet::TYPE_PACKAGE => array(),
); );

View file

@ -16,6 +16,7 @@ use Composer\DependencyResolver\GenericRule;
use Composer\DependencyResolver\Rule; use Composer\DependencyResolver\Rule;
use Composer\DependencyResolver\RuleSet; use Composer\DependencyResolver\RuleSet;
use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\Pool;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Semver\Constraint\MatchNoneConstraint; use Composer\Semver\Constraint\MatchNoneConstraint;
use Composer\Test\TestCase; use Composer\Test\TestCase;
@ -26,11 +27,11 @@ class RuleSetTest extends TestCase
$rules = array( $rules = array(
RuleSet::TYPE_PACKAGE => array(), RuleSet::TYPE_PACKAGE => array(),
RuleSet::TYPE_REQUEST => array( RuleSet::TYPE_REQUEST => array(
new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null), new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null), new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
), ),
RuleSet::TYPE_LEARNED => array( RuleSet::TYPE_LEARNED => array(
new GenericRule(array(), Rule::RULE_LEARNED, null), new GenericRule(array(), Rule::RULE_LEARNED, 1),
), ),
); );
@ -47,9 +48,9 @@ class RuleSetTest extends TestCase
{ {
$rules = array( $rules = array(
RuleSet::TYPE_REQUEST => array( RuleSet::TYPE_REQUEST => array(
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null), new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null), new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null), new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)),
), ),
); );
@ -67,15 +68,15 @@ class RuleSetTest extends TestCase
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$this->setExpectedException('OutOfBoundsException'); $this->setExpectedException('OutOfBoundsException');
$ruleSet->add(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null), 7); $ruleSet->add(new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)), 7);
} }
public function testCount() public function testCount()
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$ruleSet->add(new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null), RuleSet::TYPE_REQUEST); $ruleSet->add(new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)), RuleSet::TYPE_REQUEST);
$ruleSet->add(new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null), RuleSet::TYPE_REQUEST); $ruleSet->add(new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint)), RuleSet::TYPE_REQUEST);
$this->assertEquals(2, $ruleSet->count()); $this->assertEquals(2, $ruleSet->count());
} }
@ -84,7 +85,7 @@ class RuleSetTest extends TestCase
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$ruleSet->add($rule, RuleSet::TYPE_REQUEST); $ruleSet->add($rule, RuleSet::TYPE_REQUEST);
$this->assertSame($rule, $ruleSet->ruleById[0]); $this->assertSame($rule, $ruleSet->ruleById[0]);
@ -94,8 +95,8 @@ class RuleSetTest extends TestCase
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null); $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null); $rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$ruleSet->add($rule1, RuleSet::TYPE_REQUEST); $ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
$ruleSet->add($rule2, RuleSet::TYPE_LEARNED); $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
@ -109,8 +110,8 @@ class RuleSetTest extends TestCase
public function testGetIteratorFor() public function testGetIteratorFor()
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null); $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null); $rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$ruleSet->add($rule1, RuleSet::TYPE_REQUEST); $ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
$ruleSet->add($rule2, RuleSet::TYPE_LEARNED); $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
@ -123,8 +124,8 @@ class RuleSetTest extends TestCase
public function testGetIteratorWithout() public function testGetIteratorWithout()
{ {
$ruleSet = new RuleSet; $ruleSet = new RuleSet;
$rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null); $rule1 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, null); $rule2 = new GenericRule(array(2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$ruleSet->add($rule1, RuleSet::TYPE_REQUEST); $ruleSet->add($rule1, RuleSet::TYPE_REQUEST);
$ruleSet->add($rule2, RuleSet::TYPE_LEARNED); $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);

View file

@ -24,7 +24,7 @@ class RuleTest extends TestCase
{ {
public function testGetHash() public function testGetHash()
{ {
$rule = new GenericRule(array(123), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(123), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$hash = unpack('ihash', md5('123', true)); $hash = unpack('ihash', md5('123', true));
$this->assertEquals($hash['hash'], $rule->getHash()); $this->assertEquals($hash['hash'], $rule->getHash());
@ -32,31 +32,31 @@ class RuleTest extends TestCase
public function testEqualsForRulesWithDifferentHashes() public function testEqualsForRulesWithDifferentHashes()
{ {
$rule = new GenericRule(array(1, 2), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(1, 2), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule2 = new GenericRule(array(1, 3), Rule::RULE_ROOT_REQUIRE, null); $rule2 = new GenericRule(array(1, 3), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$this->assertFalse($rule->equals($rule2)); $this->assertFalse($rule->equals($rule2));
} }
public function testEqualsForRulesWithDifferLiteralsQuantity() public function testEqualsForRulesWithDifferLiteralsQuantity()
{ {
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null); $rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$this->assertFalse($rule->equals($rule2)); $this->assertFalse($rule->equals($rule2));
} }
public function testEqualsForRulesWithSameLiterals() public function testEqualsForRulesWithSameLiterals()
{ {
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule2 = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null); $rule2 = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$this->assertTrue($rule->equals($rule2)); $this->assertTrue($rule->equals($rule2));
} }
public function testSetAndGetType() public function testSetAndGetType()
{ {
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule->setType(RuleSet::TYPE_REQUEST); $rule->setType(RuleSet::TYPE_REQUEST);
$this->assertEquals(RuleSet::TYPE_REQUEST, $rule->getType()); $this->assertEquals(RuleSet::TYPE_REQUEST, $rule->getType());
@ -64,7 +64,7 @@ class RuleTest extends TestCase
public function testEnable() public function testEnable()
{ {
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule->disable(); $rule->disable();
$rule->enable(); $rule->enable();
@ -74,7 +74,7 @@ class RuleTest extends TestCase
public function testDisable() public function testDisable()
{ {
$rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule->enable(); $rule->enable();
$rule->disable(); $rule->disable();
@ -84,8 +84,8 @@ class RuleTest extends TestCase
public function testIsAssertions() public function testIsAssertions()
{ {
$rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, null); $rule = new GenericRule(array(1, 12), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, null); $rule2 = new GenericRule(array(1), Rule::RULE_ROOT_REQUIRE, array('packageName' => '', 'constraint' => new MatchAllConstraint));
$this->assertFalse($rule->isAssertion()); $this->assertFalse($rule->isAssertion());
$this->assertTrue($rule2->isAssertion()); $this->assertTrue($rule2->isAssertion());

View file

@ -12,6 +12,11 @@
namespace Composer\Test\DependencyResolver; namespace Composer\Test\DependencyResolver;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Transaction; use Composer\DependencyResolver\Transaction;
use Composer\Package\Link; use Composer\Package\Link;
use Composer\Test\TestCase; use Composer\Test\TestCase;
@ -97,17 +102,19 @@ class TransactionTest extends TestCase
{ {
$result = array(); $result = array();
foreach ($transaction->getOperations() as $operation) { foreach ($transaction->getOperations() as $operation) {
if ('update' === $operation->getOperationType()) { if ($operation instanceof UpdateOperation) {
$result[] = array( $result[] = array(
'job' => 'update', 'job' => 'update',
'from' => $operation->getInitialPackage(), 'from' => $operation->getInitialPackage(),
'to' => $operation->getTargetPackage(), 'to' => $operation->getTargetPackage(),
); );
} else { } elseif ($operation instanceof InstallOperation || $operation instanceof UninstallOperation || $operation instanceof MarkAliasInstalledOperation || $operation instanceof MarkAliasUninstalledOperation) {
$result[] = array( $result[] = array(
'job' => $operation->getOperationType(), 'job' => $operation->getOperationType(),
'package' => $operation->getPackage(), 'package' => $operation->getPackage(),
); );
} else {
throw new \UnexpectedValueException('Unknown operation type: '.get_class($operation));
} }
} }