1
0
Fork 0

PHPStan Level 5 (#10070)

* Bump PHPStan to level 5

* Update seld/phar-utils to latest

* Add phpstan-setup / phpstan scripts
pull/10076/head
Jordi Boggiano 2021-08-21 17:41:52 +02:00 committed by GitHub
parent 4b8585d767
commit d3c176ec69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 395 additions and 547 deletions

View File

@ -78,11 +78,20 @@
],
"scripts": {
"compile": "@php -dphar.readonly=0 bin/compile",
"test": "simple-phpunit"
"test": "simple-phpunit",
"phpstan-setup": [
"@composer config platform --unset",
"@php composer.phar update",
"@composer require --dev phpstan/phpstan:^0.12.93 phpstan/phpstan-phpunit:^0.12.17 phpunit/phpunit:^7.5.20 --with-all-dependencies",
"git checkout composer.json composer.lock"
],
"phpstan": "@php vendor/bin/phpstan analyse --configuration=phpstan/config.neon"
},
"scripts-descriptions": {
"compile": "Compile composer.phar",
"test": "Run all tests"
"test": "Run all tests",
"phpstan-setup": "Prepare environment to run PHPStan locally (must be run with PHP7.4)",
"phpstan": "Runs PHPStan (after phpstan-setup was executed, must be run with PHP7.4)"
},
"support": {
"issues": "https://github.com/composer/composer/issues",

12
composer.lock generated
View File

@ -608,16 +608,16 @@
},
{
"name": "seld/phar-utils",
"version": "1.1.1",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/phar-utils.git",
"reference": "8674b1d84ffb47cc59a101f5d5a3b61e87d23796"
"reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/8674b1d84ffb47cc59a101f5d5a3b61e87d23796",
"reference": "8674b1d84ffb47cc59a101f5d5a3b61e87d23796",
"url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/749042a2315705d2dfbbc59234dd9ceb22bf3ff0",
"reference": "749042a2315705d2dfbbc59234dd9ceb22bf3ff0",
"shasum": ""
},
"require": {
@ -650,9 +650,9 @@
],
"support": {
"issues": "https://github.com/Seldaek/phar-utils/issues",
"source": "https://github.com/Seldaek/phar-utils/tree/master"
"source": "https://github.com/Seldaek/phar-utils/tree/1.1.2"
},
"time": "2020-07-07T18:42:57+00:00"
"time": "2021-08-19T21:01:38+00:00"
},
{
"name": "symfony/console",

View File

@ -1,277 +1,11 @@
parameters:
ignoreErrors:
-
message: "#^Else branch is unreachable because ternary operator condition is always true\\.$#"
message: "#^Parameter \\#1 \\$autoload_function of function spl_autoload_register expects callable\\(string\\)\\: void, array\\(\\$this\\(Composer\\\\Autoload\\\\ClassLoader\\), 'loadClass'\\) given\\.$#"
count: 1
path: ../src/Composer/Autoload/AutoloadGenerator.php
path: ../src/Composer/Autoload/ClassLoader.php
-
message: "#^Left side of && is always true\\.$#"
count: 1
path: ../src/Composer/Autoload/AutoloadGenerator.php
-
message: "#^If condition is always true\\.$#"
count: 1
path: ../src/Composer/Autoload/ClassMapGenerator.php
-
message: "#^Else branch is unreachable because previous condition is always true\\.$#"
count: 1
path: ../src/Composer/Command/BaseCommand.php
-
message: "#^Elseif branch is unreachable because previous condition is always true\\.$#"
count: 1
path: ../src/Composer/Command/BaseCommand.php
-
message: "#^Result of && is always false\\.$#"
count: 1
path: ../src/Composer/Command/DiagnoseCommand.php
-
message: "#^Strict comparison using \\!\\=\\= between '@package_version@' and '@package_version@' will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/Command/DiagnoseCommand.php
-
message: "#^Ternary operator condition is always true\\.$#"
count: 1
path: ../src/Composer/Command/DiagnoseCommand.php
-
message: "#^Negated boolean expression is always false\\.$#"
count: 1
path: ../src/Composer/Command/InitCommand.php
-
message: "#^Negated boolean expression is always false\\.$#"
count: 1
path: ../src/Composer/Command/InstallCommand.php
-
message: "#^Call to function is_array\\(\\) with string will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/Command/ShowCommand.php
-
message: "#^Elseif branch is unreachable because previous condition is always true\\.$#"
count: 1
path: ../src/Composer/Command/ShowCommand.php
-
message: "#^Negated boolean expression is always false\\.$#"
count: 1
path: ../src/Composer/Command/ShowCommand.php
-
message: "#^Unreachable statement \\- code above always terminates\\.$#"
count: 1
path: ../src/Composer/Composer.php
-
message: "#^If condition is always true\\.$#"
count: 1
path: ../src/Composer/Console/Application.php
-
message: "#^Left side of && is always true\\.$#"
message: "#^Parameter \\#2 \\$capabilityClassName of method Composer\\\\Plugin\\\\PluginManager\\:\\:getPluginCapability\\(\\) expects class\\-string\\<Composer\\\\Plugin\\\\Capability\\\\Capability\\>, string given\\.$#"
count: 2
path: ../src/Composer/Console/Application.php
-
message: "#^Strict comparison using \\!\\=\\= between '@package_branch…' and '@package_branch…' will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/Console/Application.php
-
message: "#^Strict comparison using \\=\\=\\= between null and Composer\\\\Composer will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/Console/Application.php
-
message: "#^Instanceof between mixed and Composer\\\\Package\\\\RootAliasPackage will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/DependencyResolver/LockTransaction.php
-
message: "#^If condition is always true\\.$#"
count: 1
path: ../src/Composer/DependencyResolver/PoolBuilder.php
-
message: "#^Ternary operator condition is always true\\.$#"
count: 1
path: ../src/Composer/DependencyResolver/Problem.php
-
message: "#^If condition is always true\\.$#"
count: 2
path: ../src/Composer/Downloader/FileDownloader.php
-
message: "#^Left side of && is always true\\.$#"
count: 3
path: ../src/Composer/Downloader/FileDownloader.php
-
message: "#^Comparison operation \"\\>\" between 0 and 6 is always false\\.$#"
count: 1
path: ../src/Composer/Downloader/PathDownloader.php
-
message: "#^Comparison operation \"\\>\\=\" between 0 and 1 is always false\\.$#"
count: 1
path: ../src/Composer/Downloader/PathDownloader.php
-
message: "#^Result of && is always false\\.$#"
count: 2
path: ../src/Composer/Downloader/PathDownloader.php
-
message: "#^Result of \\|\\| is always false\\.$#"
count: 1
path: ../src/Composer/Downloader/PathDownloader.php
-
message: "#^Strict comparison using \\=\\=\\= between 0 and 6 will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/Downloader/PathDownloader.php
-
message: "#^If condition is always true\\.$#"
count: 1
path: ../src/Composer/Factory.php
-
message: "#^Left side of && is always true\\.$#"
count: 3
path: ../src/Composer/Factory.php
-
message: "#^Strict comparison using \\=\\=\\= between 16 and 0 will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/IO/ConsoleIO.php
-
message: "#^Result of && is always false\\.$#"
count: 1
path: ../src/Composer/InstalledVersions.php
-
message: "#^If condition is always true\\.$#"
count: 2
path: ../src/Composer/Installer.php
-
message: "#^Negated boolean expression is always false\\.$#"
count: 1
path: ../src/Composer/Installer.php
-
message: "#^Empty array passed to foreach\\.$#"
count: 1
path: ../src/Composer/Installer/InstallationManager.php
-
message: "#^Right side of && is always true\\.$#"
count: 2
path: ../src/Composer/Installer/InstallationManager.php
-
message: "#^Strict comparison using \\=\\=\\= between null and string will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/Json/JsonFile.php
-
message: "#^If condition is always true\\.$#"
count: 1
path: ../src/Composer/Package/Dumper/ArrayDumper.php
-
message: "#^Ternary operator condition is always true\\.$#"
count: 1
path: ../src/Composer/Package/Link.php
-
message: "#^Unreachable statement \\- code above always terminates\\.$#"
count: 1
path: ../src/Composer/Package/Loader/ArrayLoader.php
-
message: "#^Else branch is unreachable because previous condition is always true\\.$#"
count: 1
path: ../src/Composer/Package/Locker.php
-
message: "#^If condition is always true\\.$#"
count: 3
path: ../src/Composer/Plugin/PluginManager.php
-
message: "#^Left side of && is always true\\.$#"
count: 1
path: ../src/Composer/Plugin/PluginManager.php
-
message: "#^Ternary operator condition is always true\\.$#"
count: 2
path: ../src/Composer/Plugin/PluginManager.php
-
message: "#^Instanceof between string and Composer\\\\Package\\\\PackageInterface will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/Plugin/PostFileDownloadEvent.php
-
message: "#^Result of && is always false\\.$#"
count: 1
path: ../src/Composer/Plugin/PostFileDownloadEvent.php
-
message: "#^Negated boolean expression is always false\\.$#"
count: 1
path: ../src/Composer/Repository/ArrayRepository.php
-
message: "#^Strict comparison using \\=\\=\\= between null and Composer\\\\Repository\\\\RepositoryInterface will always evaluate to false\\.$#"
count: 1
path: ../src/Composer/Repository/ArrayRepository.php
-
message: "#^If condition is always false\\.$#"
count: 1
path: ../src/Composer/Repository/ComposerRepository.php
-
message: "#^Negated boolean expression is always false\\.$#"
count: 1
path: ../src/Composer/Repository/ComposerRepository.php
-
message: "#^Negated boolean expression is always true\\.$#"
count: 1
path: ../src/Composer/Repository/InstalledRepository.php
-
message: "#^Negated boolean expression is always true\\.$#"
count: 1
path: ../src/Composer/Repository/Vcs/GitBitbucketDriver.php
-
message: "#^Unreachable statement \\- code above always terminates\\.$#"
count: 1
path: ../src/Composer/Repository/Vcs/GitBitbucketDriver.php
-
message: "#^Negated boolean expression is always false\\.$#"
count: 1
path: ../src/Composer/Repository/Vcs/GitLabDriver.php
-
message: "#^Right side of && is always true\\.$#"
count: 1
path: ../src/Composer/Repository/Vcs/GitLabDriver.php
path: ../tests/Composer/Test/Plugin/PluginInstallerTest.php

View File

@ -3,7 +3,7 @@ includes:
- ./baseline.neon
parameters:
level: 4
level: 5
excludes_analyse:
- '../tests/Composer/Test/Fixtures/*'
- '../tests/Composer/Test/Autoload/Fixtures/*'
@ -42,5 +42,11 @@ parameters:
- ../src
- ../tests
dynamicConstantNames:
- Composer\Composer::BRANCH_ALIAS_VERSION
- Composer\Composer::VERSION
- Composer\Composer::RELEASE_DATE
- Composer\Composer::SOURCE_VERSION
rules:
- Composer\PHPStanRules\AnonymousFunctionWithThisRule

View File

@ -41,7 +41,7 @@ class AutoloadGenerator
private $eventDispatcher;
/**
* @var IOInterface
* @var ?IOInterface
*/
private $io;
@ -667,7 +667,7 @@ EOF;
$baseDir = "'phar://' . " . $baseDir;
}
return $baseDir . (($path !== false) ? var_export($path, true) : "");
return $baseDir . var_export($path, true);
}
protected function getPlatformCheck(array $packageMap, array $ignorePlatformReqs, $checkPlatform, array $devPackageNames)

View File

@ -33,7 +33,7 @@ class ClassMapGenerator
/**
* Generate a class map file
*
* @param \Traversable $dirs Directories or a single path to search in
* @param \Traversable|array $dirs Directories or a single path to search in
* @param string $file The name of the class map file
*/
public static function dump($dirs, $file)
@ -50,11 +50,11 @@ class ClassMapGenerator
/**
* Iterate over all files in the given directory searching for classes
*
* @param \Iterator|string $path The path to search in or an iterator
* @param \Traversable|string $path The path to search in or an iterator
* @param string $excluded Regex that matches file paths to be excluded from the classmap
* @param IOInterface $io IO object
* @param string $namespace Optional namespace prefix to filter by
* @param string $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules
* @param ?IOInterface $io IO object
* @param ?string $namespace Optional namespace prefix to filter by
* @param ?string $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules
*
* @throws \RuntimeException When the path is neither an existing file nor directory
* @return array A class map array
@ -152,7 +152,7 @@ class ClassMapGenerator
* @param string $baseNamespace prefix of given autoload mapping
* @param string $namespaceType psr-0|psr-4
* @param string $basePath root directory of given autoload mapping
* @param IOInterface $io IO object
* @param ?IOInterface $io IO object
* @return array valid classes
*/
private static function filterByNamespace($classes, $filePath, $baseNamespace, $namespaceType, $basePath, $io)

View File

@ -49,7 +49,7 @@ class ArchiveCommand extends BaseCommand
new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
.' Note that the format will be appended.'),
new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
new InputOption('ignore-filters', null, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
))
->setHelp(
<<<EOT

View File

@ -61,6 +61,7 @@ abstract class BaseCommand extends Command
if ($application instanceof Application) {
/* @var $application Application */
$this->composer = $application->getComposer($required, $disablePlugins);
/** @phpstan-ignore-next-line */
} elseif ($required) {
throw new \RuntimeException(
'Could not create a Composer\Composer instance, you must inject '.
@ -109,8 +110,8 @@ abstract class BaseCommand extends Command
if (null === $this->io) {
$application = $this->getApplication();
if ($application instanceof Application) {
/* @var $application Application */
$this->io = $application->getIO();
/** @phpstan-ignore-next-line */
} else {
$this->io = new NullIO();
}

View File

@ -304,9 +304,11 @@ EOT
try {
$url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
return $this->httpDownloader->get($url, array(
$this->httpDownloader->get($url, array(
'retry-auth-failure' => false,
)) ? true : 'Unexpected error';
));
return true;
} catch (\Exception $e) {
if ($e instanceof TransportException && $e->getCode() === 401) {
return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';

View File

@ -43,7 +43,7 @@ use Symfony\Component\Console\Helper\FormatterHelper;
*/
class InitCommand extends BaseCommand
{
/** @var CompositeRepository */
/** @var ?CompositeRepository */
protected $repos;
/** @var array */
@ -705,10 +705,11 @@ EOT
$finder = new ExecutableFinder();
$gitBin = $finder->find('git');
// TODO in v3 always call with an array
// TODO in v2.3 always call with an array
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
$cmd = new Process(array($gitBin, 'config', '-l'));
} else {
// @phpstan-ignore-next-line
$cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
}
$cmd->run();

View File

@ -320,7 +320,7 @@ EOT
'require-dev' => $rootPackage->getDevRequires(),
);
$loader = new ArrayLoader();
$newLinks = $loader->parseLinks($rootPackage->getName(), $rootPackage->getPrettyVersion(), BasePackage::$supportedLinkTypes[$requireKey]['description'], $requirements);
$newLinks = $loader->parseLinks($rootPackage->getName(), $rootPackage->getPrettyVersion(), BasePackage::$supportedLinkTypes[$requireKey]['method'], $requirements);
$links[$requireKey] = array_merge($links[$requireKey], $newLinks);
foreach ($requirements as $package => $constraint) {
unset($links[$removeKey][$package]);

View File

@ -54,7 +54,7 @@ class ShowCommand extends BaseCommand
protected $versionParser;
protected $colors;
/** @var RepositorySet */
/** @var ?RepositorySet */
private $repositorySet;
protected function configure()
@ -311,12 +311,6 @@ EOT
return 0;
}
if ($repos instanceof CompositeRepository) {
$repos = $repos->getRepositories();
} elseif (!is_array($repos)) {
$repos = array($repos);
}
// list packages
$packages = array();
$packageFilterRegex = null;
@ -334,7 +328,7 @@ EOT
$input->setOption('path', false);
}
foreach ($repos as $repo) {
foreach ($repos->getRepositories() as $repo) {
if ($repo === $platformRepo) {
$type = 'platform';
} elseif ($lockedRepo !== null && $repo === $lockedRepo) {
@ -1245,6 +1239,9 @@ EOT
return $candidate;
}
/**
* @return RepositorySet
*/
private function getRepositorySet(Composer $composer)
{
if (!$this->repositorySet) {

View File

@ -315,6 +315,7 @@ EOT
$link->getSource(),
$link->getTarget(),
$newConstraint,
/** @phpstan-ignore-next-line */
$link->getDescription(),
$link->getPrettyConstraint() . ', ' . $constraint
);

View File

@ -43,13 +43,25 @@ class Compiler
unlink($pharFile);
}
// TODO in v2.3 always call with an array
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
$process = new Process(array('git', 'log', '--pretty="%H"', '-n1', 'HEAD'), __DIR__);
} else {
// @phpstan-ignore-next-line
$process = new Process('git log --pretty="%H" -n1 HEAD', __DIR__);
}
if ($process->run() != 0) {
throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.');
}
$this->version = trim($process->getOutput());
// TODO in v2.3 always call with an array
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
$process = new Process(array('git', 'log', '-n1', '--pretty=%ci', 'HEAD'), __DIR__);
} else {
// @phpstan-ignore-next-line
$process = new Process('git log -n1 --pretty=%ci HEAD', __DIR__);
}
if ($process->run() != 0) {
throw new \RuntimeException('Can\'t run git log. You must ensure to run compile from composer git repository clone and that git binary is available.');
}
@ -57,7 +69,13 @@ class Compiler
$this->versionDate = new \DateTime(trim($process->getOutput()));
$this->versionDate->setTimezone(new \DateTimeZone('UTC'));
// TODO in v2.3 always call with an array
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
$process = new Process(array('git', 'describe', '--tags', '--exact-match', 'HEAD'), __DIR__);
} else {
// @phpstan-ignore-next-line
$process = new Process('git describe --tags --exact-match HEAD');
}
if ($process->run() == 0) {
$this->version = trim($process->getOutput());
} else {

View File

@ -88,9 +88,9 @@ class Composer
private $package;
/**
* @var Locker
* @var ?Locker
*/
private $locker;
private $locker = null;
/**
* @var Loop
@ -179,7 +179,7 @@ class Composer
}
/**
* @return Locker
* @return ?Locker
*/
public function getLocker()
{

View File

@ -77,8 +77,8 @@ class Application extends BaseApplication
static $shutdownRegistered = false;
if (function_exists('ini_set') && extension_loaded('xdebug')) {
ini_set('xdebug.show_exception_trace', false);
ini_set('xdebug.scream', false);
ini_set('xdebug.show_exception_trace', '0');
ini_set('xdebug.scream', '0');
}
if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
@ -408,7 +408,8 @@ class Application extends BaseApplication
* @param bool $required
* @param bool|null $disablePlugins
* @throws JsonValidationException
* @return \Composer\Composer
* @throws \InvalidArgumentException
* @return ?\Composer\Composer If $required is true then the return value is guaranteed
*/
public function getComposer($required = true, $disablePlugins = null)
{
@ -444,7 +445,7 @@ class Application extends BaseApplication
public function resetComposer()
{
$this->composer = null;
if ($this->getIO() && method_exists($this->getIO(), 'resetAuthentications')) {
if (method_exists($this->getIO(), 'resetAuthentications')) {
$this->getIO()->resetAuthentications();
}
}

View File

@ -14,6 +14,7 @@ namespace Composer\DependencyResolver;
use Composer\Package\BasePackage;
use Composer\Package\Link;
use Composer\Semver\Constraint\ConstraintInterface;
/**
* @author Nils Adermann <naderman@naderman.de>
@ -25,7 +26,9 @@ class GenericRule extends Rule
/**
* @param array $literals
* @param int|null $reason A RULE_* constant describing the reason for generating this rule
* @param Link|BasePackage|int|null $reasonData
* @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)
{

View File

@ -13,7 +13,8 @@
namespace Composer\DependencyResolver;
use Composer\Package\AliasPackage;
use Composer\Package\RootAliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\Package;
/**
* @author Nils Adermann <naderman@naderman.de>
@ -23,22 +24,32 @@ class LockTransaction extends Transaction
{
/**
* packages in current lock file, platform repo or otherwise present
* @var array
*
* Indexed by spl_object_hash
*
* @var array<string, BasePackage>
*/
protected $presentMap;
/**
* Packages which cannot be mapped, platform repo, root package, other fixed repos
* @var array
*
* Indexed by package id
*
* @var array<int, BasePackage>
*/
protected $unlockableMap;
/**
* @var array
* @var array{dev: BasePackage[], non-dev: BasePackage[], all: BasePackage[]}
*/
protected $resultPackages;
public function __construct(Pool $pool, $presentMap, $unlockableMap, $decisions)
/**
* @param array<string, BasePackage> $presentMap
* @param array<int, BasePackage> $unlockableMap
*/
public function __construct(Pool $pool, array $presentMap, array $unlockableMap, Decisions $decisions)
{
$this->presentMap = $presentMap;
$this->unlockableMap = $unlockableMap;
@ -88,7 +99,7 @@ class LockTransaction extends Transaction
{
$packages = array();
foreach ($this->resultPackages[$devMode ? 'dev' : 'non-dev'] as $package) {
if (!($package instanceof AliasPackage) && !($package instanceof RootAliasPackage)) {
if (!$package instanceof AliasPackage) {
// if we're just updating mirrors we need to reset references to the same as currently "present" packages' references to keep the lock file as-is
// we do not reset references if the currently present package didn't have any, or if the type of VCS has changed
if ($updateMirrors && !isset($this->presentMap[spl_object_hash($package)])) {
@ -97,7 +108,7 @@ class LockTransaction extends Transaction
if ($presentPackage->getSourceReference() && $presentPackage->getSourceType() === $package->getSourceType()) {
$package->setSourceDistReferences($presentPackage->getSourceReference());
}
if ($presentPackage->getReleaseDate()) {
if ($presentPackage->getReleaseDate() && $package instanceof Package) {
$package->setReleaseDate($presentPackage->getReleaseDate());
}
}

View File

@ -202,7 +202,7 @@ class Pool implements \Countable
$str = "Pool:\n";
foreach ($this->packages as $package) {
$str .= '- '.str_pad($package->id, 6, ' ', STR_PAD_LEFT).': '.$package->getName()."\n";
$str .= '- '.str_pad((string) $package->id, 6, ' ', STR_PAD_LEFT).': '.$package->getName()."\n";
}
return $str;

View File

@ -17,6 +17,7 @@ use Composer\IO\IOInterface;
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;
@ -38,10 +39,12 @@ class PoolBuilder
{
/**
* @var int[]
* @phpstan-var array<string, BasePackage::STABILITY_*>
*/
private $acceptableStabilities;
/**
* @var int[]
* @phpstan-var array<string, BasePackage::STABILITY_*>
*/
private $stabilityFlags;
/**
@ -55,7 +58,7 @@ class PoolBuilder
*/
private $rootReferences;
/**
* @var EventDispatcher
* @var ?EventDispatcher
*/
private $eventDispatcher;
/**
@ -340,7 +343,7 @@ class PoolBuilder
}
}
private function loadPackage(Request $request, PackageInterface $package, $propagateUpdate = true)
private function loadPackage(Request $request, BasePackage $package, $propagateUpdate = true)
{
$index = $this->indexCounter++;
$this->packages[$index] = $package;
@ -370,7 +373,7 @@ class PoolBuilder
} else {
$basePackage = $package;
}
if ($basePackage instanceof CompletePackageInterface) {
if ($basePackage instanceof CompletePackage) {
$aliasPackage = new CompleteAliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']);
} else {
$aliasPackage = new AliasPackage($basePackage, $alias['alias_normalized'], $alias['alias']);

View File

@ -18,6 +18,7 @@ use Composer\Package\RootPackageInterface;
use Composer\Repository\RepositorySet;
use Composer\Repository\LockArrayRepository;
use Composer\Semver\Constraint\Constraint;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Package\Version\VersionParser;
/**
@ -459,7 +460,7 @@ class Problem
/**
* Turns a constraint into text usable in a sentence describing a request
*
* @param \Composer\Semver\Constraint\ConstraintInterface $constraint
* @param ?ConstraintInterface $constraint
* @return string
*/
protected static function constraintToText($constraint)

View File

@ -401,7 +401,7 @@ class DownloadManager
}
/**
* @return string[]
* @return array<'dist'|'source'>&non-empty-array
*/
private function getAvailableSources(PackageInterface $package, PackageInterface $prevPackage = null)
{

View File

@ -51,9 +51,9 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
protected $httpDownloader;
/** @var Filesystem */
protected $filesystem;
/** @var Cache */
/** @var ?Cache */
protected $cache;
/** @var EventDispatcher */
/** @var ?EventDispatcher */
protected $eventDispatcher;
/** @var ProcessExecutor */
protected $process;

View File

@ -38,6 +38,7 @@ use Composer\Autoload\AutoloadGenerator;
use Composer\Package\Version\VersionParser;
use Composer\Downloader\TransportException;
use Composer\Json\JsonValidationException;
use Composer\Repository\InstalledRepositoryInterface;
use Seld\JsonLint\JsonParser;
/**
@ -434,10 +435,8 @@ class Factory
// once everything is initialized we can
// purge packages from local repos if they have been deleted on the filesystem
if ($rm->getLocalRepository()) {
$this->purgePackages($rm->getLocalRepository(), $im);
}
}
return $composer;
}
@ -585,10 +584,10 @@ class Factory
}
/**
* @param WritableRepositoryInterface $repo repository to purge packages from
* @param InstalledRepositoryInterface $repo repository to purge packages from
* @param Installer\InstallationManager $im manager to check whether packages are still installed
*/
protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
protected function purgePackages(InstalledRepositoryInterface $repo, Installer\InstallationManager $im)
{
foreach ($repo->getPackages() as $package) {
if (!$im->isPackageInstalled($repo, $package)) {
@ -632,7 +631,7 @@ class Factory
if (isset($_SERVER['argv']) && in_array('disable-tls', $_SERVER['argv']) && (in_array('conf', $_SERVER['argv']) || in_array('config', $_SERVER['argv']))) {
$warned = true;
$disableTls = !extension_loaded('openssl');
} elseif ($config && $config->get('disable-tls') === true) {
} elseif ($config->get('disable-tls') === true) {
if (!$warned) {
$io->writeError('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
}
@ -644,10 +643,10 @@ class Factory
}
$httpDownloaderOptions = array();
if ($disableTls === false) {
if ($config && $config->get('cafile')) {
if ($config->get('cafile')) {
$httpDownloaderOptions['ssl']['cafile'] = $config->get('cafile');
}
if ($config && $config->get('capath')) {
if ($config->get('capath')) {
$httpDownloaderOptions['ssl']['capath'] = $config->get('capath');
}
$httpDownloaderOptions = array_replace_recursive($httpDownloaderOptions, $options);

View File

@ -159,13 +159,6 @@ class ConsoleIO extends BaseIO
return;
}
// hack to keep our usage BC with symfony<2.8 versions
// this removes the quiet output but there is no way around it
// see https://github.com/composer/composer/pull/4913
if (OutputInterface::VERBOSITY_QUIET === 0) {
$sfVerbosity = OutputInterface::OUTPUT_NORMAL;
}
if ($raw) {
if ($sfVerbosity === OutputInterface::OUTPUT_NORMAL) {
$sfVerbosity = OutputInterface::OUTPUT_RAW;

View File

@ -228,7 +228,7 @@ class InstalledVersions
/**
* @return array
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}
*/
public static function getRootPackage()
{
@ -242,7 +242,7 @@ class InstalledVersions
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}
* @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}
*/
public static function getRawData()
{
@ -265,7 +265,7 @@ class InstalledVersions
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
public static function getAllRawData()
{
@ -288,7 +288,7 @@ class InstalledVersions
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>} $data
* @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data
*/
public static function reload($data)
{
@ -298,7 +298,7 @@ class InstalledVersions
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}>
*/
private static function getInstalled()
{

View File

@ -152,7 +152,7 @@ class Installer
protected $suggestedPackagesReporter;
/**
* @var RepositoryInterface
* @var ?RepositoryInterface
*/
protected $additionalFixedRepository;
@ -180,6 +180,7 @@ class Installer
$this->installationManager = $installationManager;
$this->eventDispatcher = $eventDispatcher;
$this->autoloadGenerator = $autoloadGenerator;
$this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
$this->writeLock = $config->get('lock');
}
@ -238,10 +239,6 @@ class Installer
$localRepo = $this->repositoryManager->getLocalRepository();
if (!$this->suggestedPackagesReporter) {
$this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
}
try {
if ($this->update) {
$res = $this->doUpdate($localRepo, $this->install);

View File

@ -47,7 +47,7 @@ class InstallationManager
private $loop;
/** @var IOInterface */
private $io;
/** @var EventDispatcher */
/** @var ?EventDispatcher */
private $eventDispatcher;
/** @var bool */
private $outputProgress;
@ -179,6 +179,7 @@ class InstallationManager
*/
public function execute(InstalledRepositoryInterface $repo, array $operations, $devMode = true, $runScripts = true)
{
/** @var PromiseInterface[] */
$cleanupPromises = array();
$loop = $this->loop;

View File

@ -291,7 +291,7 @@ class JsonFile
/**
* Parses json string and returns hash.
*
* @param string $json json string
* @param ?string $json json string
* @param string $file the json file
*
* @throws ParsingException
@ -300,7 +300,7 @@ class JsonFile
public static function parseJson($json, $file = null)
{
if (null === $json) {
return;
return null;
}
$data = json_decode($json, true);
if (null === $data && JSON_ERROR_NONE !== json_last_error()) {

View File

@ -113,6 +113,7 @@ class AliasPackage extends BasePackage
/**
* {@inheritDoc}
* @return array<string|int, Link>
*/
public function getConflicts()
{
@ -121,6 +122,7 @@ class AliasPackage extends BasePackage
/**
* {@inheritDoc}
* @return array<string|int, Link>
*/
public function getProvides()
{
@ -129,6 +131,7 @@ class AliasPackage extends BasePackage
/**
* {@inheritDoc}
* @return array<string|int, Link>
*/
public function getReplaces()
{
@ -168,7 +171,7 @@ class AliasPackage extends BasePackage
/**
* @param Link[] $links
* @param string $linkType
* @param Link::TYPE_* $linkType
*
* @return Link[]
*/

View File

@ -24,6 +24,7 @@ abstract class BasePackage implements PackageInterface
{
/**
* @phpstan-var array<string, array{description: string, method: Link::TYPE_*}>
* @internal
*/
public static $supportedLinkTypes = array(
'require' => array('description' => 'requires', 'method' => Link::TYPE_REQUIRE),

View File

@ -26,6 +26,12 @@ class Link
const TYPE_PROVIDE = 'provides';
const TYPE_CONFLICT = 'conflicts';
const TYPE_REPLACE = 'replaces';
/**
* Special type
* @internal
*/
const TYPE_DOES_NOT_REQUIRE = 'does not require';
/**
* TODO should be marked private once 5.3 is dropped
* @private
@ -37,6 +43,7 @@ class Link
*
* @internal
* @var string[]
* @phpstan-var array<self::TYPE_REQUIRE|self::TYPE_DEV_REQUIRE|self::TYPE_PROVIDE|self::TYPE_CONFLICT|self::TYPE_REPLACE>
*/
public static $TYPES = array(
self::TYPE_REQUIRE,
@ -63,12 +70,12 @@ class Link
/**
* @var string
* @phpstan-var self::TYPE_* $description
* @phpstan-var string $description
*/
protected $description;
/**
* @var string|null
* @var ?string
*/
protected $prettyConstraint;
@ -91,7 +98,7 @@ class Link
$this->source = strtolower($source);
$this->target = strtolower($target);
$this->constraint = $constraint;
$this->description = $description;
$this->description = self::TYPE_DEV_REQUIRE === $description ? 'requires (for development)' : $description;
$this->prettyConstraint = $prettyConstraint;
}
@ -154,6 +161,6 @@ class Link
*/
public function getPrettyString(PackageInterface $sourcePackage)
{
return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.($this->constraint ? ' '.$this->constraint->getPrettyString() : '');
return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString();
}
}

View File

@ -45,9 +45,12 @@ class ArrayLoader implements LoaderInterface
/**
* @template PackageClass of CompletePackageInterface
*
* @param array $config package data
* @param string $class FQCN to be instantiated
* @return CompletePackage|CompleteAliasPackage
*
* @return CompletePackage|CompleteAliasPackage|RootPackage|RootAliasPackage
*
* @phpstan-param class-string<PackageClass> $class
*/
public function load(array $config, $class = 'Composer\Package\CompletePackage')
@ -65,7 +68,7 @@ class ArrayLoader implements LoaderInterface
$this->parseLinks(
$package->getName(),
$package->getPrettyVersion(),
$opts['description'],
$opts['method'],
$config[$type]
)
);
@ -78,23 +81,16 @@ class ArrayLoader implements LoaderInterface
}
/**
* @template PackageClass of CompletePackageInterface
* @param array $versions
* @param string $class FQCN to be instantiated
* @return list<CompletePackage|CompleteAliasPackage>
* @phpstan-param class-string<PackageClass> $class
*/
public function loadPackages(array $versions, $class = 'Composer\Package\CompletePackage')
public function loadPackages(array $versions)
{
if ($class !== 'Composer\Package\CompletePackage') {
trigger_error('The $class arg is deprecated, please reach out to Composer maintainers ASAP if you still need this.', E_USER_DEPRECATED);
}
$packages = array();
$linkCache = array();
foreach ($versions as $version) {
$package = $this->createObject($version, $class);
$package = $this->createObject($version, 'Composer\Package\CompletePackage');
$this->configureCachedLinks($linkCache, $package, $version);
$package = $this->configureObject($package, $version);
@ -137,14 +133,14 @@ class ArrayLoader implements LoaderInterface
}
/**
* @param CompletePackageInterface $package
* @param CompletePackage $package
* @param array $config package data
* @return RootPackage|RootAliasPackage|CompletePackage|CompleteAliasPackage
*/
private function configureObject(PackageInterface $package, array $config)
{
if (!$package instanceof Package) {
throw new \LogicException('ArrayLoader expects instances of the Composer\Package\Package class to function correctly');
if (!$package instanceof CompletePackage) {
throw new \LogicException('ArrayLoader expects instances of the Composer\Package\CompletePackage class to function correctly');
}
$package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
@ -302,17 +298,13 @@ class ArrayLoader implements LoaderInterface
if ($aliasNormalized = $this->getBranchAlias($config)) {
$prettyAlias = preg_replace('{(\.9{7})+}', '.x', $aliasNormalized);
if ($package instanceof RootPackageInterface) {
if ($package instanceof RootPackage) {
return new RootAliasPackage($package, $aliasNormalized, $prettyAlias);
}
if ($package instanceof CompletePackageInterface) {
return new CompleteAliasPackage($package, $aliasNormalized, $prettyAlias);
}
return new AliasPackage($package, $aliasNormalized, $prettyAlias);
}
return $package;
}
@ -335,10 +327,10 @@ class ArrayLoader implements LoaderInterface
foreach ($config[$type] as $prettyTarget => $constraint) {
$target = strtolower($prettyTarget);
if ($constraint === 'self.version') {
$links[$target] = $this->createLink($name, $prettyVersion, $opts['description'], $target, $constraint);
$links[$target] = $this->createLink($name, $prettyVersion, $opts['method'], $target, $constraint);
} else {
if (!isset($linkCache[$name][$type][$target][$constraint])) {
$linkCache[$name][$type][$target][$constraint] = array($target, $this->createLink($name, $prettyVersion, $opts['description'], $target, $constraint));
$linkCache[$name][$type][$target][$constraint] = array($target, $this->createLink($name, $prettyVersion, $opts['method'], $target, $constraint));
}
list($target, $link) = $linkCache[$name][$type][$target][$constraint];

View File

@ -186,11 +186,7 @@ class Locker
if (isset($lockData['aliases'])) {
foreach ($lockData['aliases'] as $alias) {
if (isset($packageByName[$alias['package']])) {
if ($packageByName[$alias['package']] instanceof CompletePackageInterface) {
$aliasPkg = new CompleteAliasPackage($packageByName[$alias['package']], $alias['alias_normalized'], $alias['alias']);
} else {
$aliasPkg = new AliasPackage($packageByName[$alias['package']], $alias['alias_normalized'], $alias['alias']);
}
$aliasPkg->setRootPackageAlias(true);
$packages->addPackage($aliasPkg);
}

View File

@ -22,46 +22,68 @@ use Composer\Util\ComposerMirror;
*/
class Package extends BasePackage
{
/** @var string */
protected $type;
/** @var ?string */
protected $targetDir;
/** @var 'source'|'dist'|null */
protected $installationSource;
/** @var ?string */
protected $sourceType;
/** @var ?string */
protected $sourceUrl;
/** @var ?string */
protected $sourceReference;
/** @var ?array */
protected $sourceMirrors;
/** @var ?string */
protected $distType;
/** @var ?string */
protected $distUrl;
/** @var ?string */
protected $distReference;
/** @var ?string */
protected $distSha1Checksum;
/** @var ?array */
protected $distMirrors;
/** @var string */
protected $version;
/** @var string */
protected $prettyVersion;
/** @var ?\DateTime */
protected $releaseDate;
/** @var mixed[] */
protected $extra = array();
/** @var string[] */
protected $binaries = array();
/** @var bool */
protected $dev;
/** @var string */
protected $stability;
/** @var ?string */
protected $notificationUrl;
/** @var Link[] */
/** @var array<string, Link> */
protected $requires = array();
/** @var Link[] */
/** @var array<string, Link> */
protected $conflicts = array();
/** @var Link[] */
/** @var array<string, Link> */
protected $provides = array();
/** @var Link[] */
/** @var array<string, Link> */
protected $replaces = array();
/** @var Link[] */
/** @var array<string, Link> */
protected $devRequires = array();
/** @var array<string, string> */
protected $suggests = array();
/** @var array{psr-0?: array<string, string|string[]>, psr-4?: array<string, string|string[]>, classmap?: list<string>, files?: list<string>} */
protected $autoload = array();
/** @var array{psr-0?: array<string, string|string[]>, psr-4?: array<string, string|string[]>, classmap?: list<string>, files?: list<string>} */
protected $devAutoload = array();
/** @var string[] */
protected $includePaths = array();
/** @var bool */
protected $isDefaultBranch = false;
/** @var array */
/** @var mixed[] */
protected $transportOptions = array();
/**
@ -395,7 +417,7 @@ class Package extends BasePackage
/**
* Set the required packages
*
* @param Link[] $requires A set of package links
* @param array<string, Link> $requires A set of package links
*/
public function setRequires(array $requires)
{
@ -413,7 +435,7 @@ class Package extends BasePackage
/**
* Set the conflicting packages
*
* @param Link[] $conflicts A set of package links
* @param array<string, Link> $conflicts A set of package links
*/
public function setConflicts(array $conflicts)
{
@ -422,6 +444,7 @@ class Package extends BasePackage
/**
* {@inheritDoc}
* @return array<string, Link>
*/
public function getConflicts()
{
@ -431,7 +454,7 @@ class Package extends BasePackage
/**
* Set the provided virtual packages
*
* @param Link[] $provides A set of package links
* @param array<string, Link> $provides A set of package links
*/
public function setProvides(array $provides)
{
@ -440,6 +463,7 @@ class Package extends BasePackage
/**
* {@inheritDoc}
* @return array<string, Link>
*/
public function getProvides()
{
@ -449,7 +473,7 @@ class Package extends BasePackage
/**
* Set the packages this one replaces
*
* @param Link[] $replaces A set of package links
* @param array<string, Link> $replaces A set of package links
*/
public function setReplaces(array $replaces)
{
@ -458,6 +482,7 @@ class Package extends BasePackage
/**
* {@inheritDoc}
* @return array<string, Link>
*/
public function getReplaces()
{
@ -467,7 +492,7 @@ class Package extends BasePackage
/**
* Set the recommended packages
*
* @param Link[] $devRequires A set of package links
* @param array<string, Link> $devRequires A set of package links
*/
public function setDevRequires(array $devRequires)
{
@ -485,7 +510,7 @@ class Package extends BasePackage
/**
* Set the suggested packages
*
* @param array $suggests A set of package names/comments
* @param array<string, string> $suggests A set of package names/comments
*/
public function setSuggests(array $suggests)
{

View File

@ -82,14 +82,14 @@ interface PackageInterface
/**
* Returns the package targetDir property
*
* @return string|null The package targetDir
* @return ?string The package targetDir
*/
public function getTargetDir();
/**
* Returns the package extra data
*
* @return array The package extra data
* @return mixed[] The package extra data
*/
public function getExtra();
@ -97,27 +97,29 @@ interface PackageInterface
* Sets source from which this package was installed (source/dist).
*
* @param string $type source/dist
* @phpstan-param 'source'|'dist'|null $type
*/
public function setInstallationSource($type);
/**
* Returns source from which this package was installed (source/dist).
*
* @return string source/dist
* @return ?string source/dist
* @phpstan-return 'source'|'dist'|null
*/
public function getInstallationSource();
/**
* Returns the repository type of this package, e.g. git, svn
*
* @return string The repository type
* @return ?string The repository type
*/
public function getSourceType();
/**
* Returns the repository url of this package, e.g. git://github.com/naderman/composer.git
*
* @return string The repository url
* @return ?string The repository url
*/
public function getSourceUrl();
@ -138,12 +140,12 @@ interface PackageInterface
/**
* Returns the source mirrors of this package
*
* @return array|null
* @return ?array
*/
public function getSourceMirrors();
/**
* @param array|null $mirrors
* @param ?array $mirrors
* @return void
*/
public function setSourceMirrors($mirrors);
@ -151,14 +153,14 @@ interface PackageInterface
/**
* Returns the type of the distribution archive of this version, e.g. zip, tarball
*
* @return string The repository type
* @return ?string The repository type
*/
public function getDistType();
/**
* Returns the url of the distribution archive of this version
*
* @return string
* @return ?string
*/
public function getDistUrl();
@ -186,12 +188,12 @@ interface PackageInterface
/**
* Returns the dist mirrors of this package
*
* @return array|null
* @return ?array
*/
public function getDistMirrors();
/**
* @param array|null $mirrors
* @param ?array $mirrors
* @return void
*/
public function setDistMirrors($mirrors);
@ -226,7 +228,7 @@ interface PackageInterface
/**
* Returns the release date of the package
*
* @return \DateTime
* @return ?\DateTime
*/
public function getReleaseDate();
@ -241,7 +243,7 @@ interface PackageInterface
* Returns a set of links to packages which need to be installed before
* this package can be installed
*
* @return Link[] An array of package links defining required packages
* @return array<string, Link> An array of package links defining required packages
*/
public function getRequires();
@ -273,7 +275,7 @@ interface PackageInterface
* Returns a set of links to packages which are required to develop
* this package. These are installed if in dev mode.
*
* @return Link[] An array of package links defining packages required for development
* @return array<string, Link> An array of package links defining packages required for development
*/
public function getDevRequires();
@ -295,7 +297,7 @@ interface PackageInterface
* directories for autoloading using the type specified.
*
* @return array Mapping of autoloading rules
* @phpstan-return array{psr-0?: array<string, string>, psr-4?: array<string, string>, classmap?: list<string>, files?: list<string>}
* @phpstan-return array{psr-0?: array<string, string|string[]>, psr-4?: array<string, string|string[]>, classmap?: list<string>, files?: list<string>}
*/
public function getAutoload();
@ -308,7 +310,7 @@ interface PackageInterface
* directories for autoloading using the type specified.
*
* @return array Mapping of dev autoloading rules
* @phpstan-return array{psr-0?: array<string, string>, psr-4?: array<string, string>, classmap?: list<string>, files?: list<string>}
* @phpstan-return array{psr-0?: array<string, string|string[]>, psr-4?: array<string, string|string[]>, classmap?: list<string>, files?: list<string>}
*/
public function getDevAutoload();
@ -330,7 +332,7 @@ interface PackageInterface
/**
* Returns a reference to the repository that owns the package
*
* @return RepositoryInterface
* @return ?RepositoryInterface
*/
public function getRepository();
@ -351,7 +353,7 @@ interface PackageInterface
/**
* Returns the package notification url
*
* @return string
* @return ?string
*/
public function getNotificationUrl();
@ -377,7 +379,7 @@ interface PackageInterface
/**
* Returns a list of options to download package dist files
*
* @return array
* @return mixed[]
*/
public function getTransportOptions();

View File

@ -17,23 +17,23 @@ namespace Composer\Package;
*/
class RootAliasPackage extends CompleteAliasPackage implements RootPackageInterface
{
/** @var RootPackageInterface */
/** @var RootPackage */
protected $aliasOf;
/**
* All descendants' constructors should call this parent constructor
*
* @param RootPackageInterface $aliasOf The package this package is an alias of
* @param RootPackage $aliasOf The package this package is an alias of
* @param string $version The version the alias must report
* @param string $prettyVersion The alias's non-normalized version
*/
public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
public function __construct(RootPackage $aliasOf, $version, $prettyVersion)
{
parent::__construct($aliasOf, $version, $prettyVersion);
}
/**
* @return RootPackageInterface
* @return RootPackage
*/
public function getAliasOf()
{

View File

@ -39,7 +39,7 @@ class PluginManager
protected $composer;
/** @var IOInterface */
protected $io;
/** @var Composer */
/** @var ?Composer */
protected $globalComposer;
/** @var VersionParser */
protected $versionParser;
@ -82,9 +82,7 @@ class PluginManager
$repo = $this->composer->getRepositoryManager()->getLocalRepository();
$globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
if ($repo) {
$this->loadRepository($repo, false);
}
if ($globalRepo) {
$this->loadRepository($globalRepo, true);
}
@ -259,6 +257,7 @@ class PluginManager
}
if ($oldInstallerPlugin) {
/** @var \Composer\Installer\InstallerInterface $installer */
$installer = $this->registeredPlugins[$package->getName()];
unset($this->registeredPlugins[$package->getName()]);
$this->composer->getInstallationManager()->removeInstaller($installer);
@ -469,7 +468,7 @@ class PluginManager
array_key_exists($capability, $capabilities)
&& (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
) {
throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], true));
}
return null;

View File

@ -59,6 +59,7 @@ class PostFileDownloadEvent extends Event
*/
public function __construct($name, $fileName, $checksum, $url, $type, $context = null)
{
/** @phpstan-ignore-next-line */
if ($context === null && $type instanceof PackageInterface) {
$context = $type;
$type = 'package';

View File

@ -13,7 +13,9 @@
namespace Composer\Repository;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\CompletePackage;
use Composer\Package\PackageInterface;
use Composer\Package\CompletePackageInterface;
use Composer\Package\Version\VersionParser;
@ -28,11 +30,11 @@ use Composer\Semver\Constraint\Constraint;
*/
class ArrayRepository implements RepositoryInterface
{
/** @var ?PackageInterface[] */
/** @var ?array<PackageInterface&BasePackage> */
protected $packages = null;
/**
* @var ?PackageInterface[] indexed by package unique name and used to cache hasPackage calls
* @var ?array<PackageInterface&BasePackage> indexed by package unique name and used to cache hasPackage calls
*/
protected $packageMap = null;
@ -232,13 +234,17 @@ class ArrayRepository implements RepositoryInterface
return $result;
}
/**
* @phpstan-param PackageInterface&BasePackage $package
* @return AliasPackage|CompleteAliasPackage
*/
protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
{
while ($package instanceof AliasPackage) {
$package = $package->getAliasOf();
}
if ($package instanceof CompletePackageInterface) {
if ($package instanceof CompletePackage) {
return new CompleteAliasPackage($package, $alias, $prettyAlias);
}
@ -275,6 +281,10 @@ class ArrayRepository implements RepositoryInterface
$this->initialize();
}
if (null === $this->packages) {
throw new \LogicException('initialize failed to initialize the packages array');
}
return $this->packages;
}

View File

@ -49,6 +49,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
private $url;
private $baseUrl;
private $io;
/** @var HttpDownloader */
private $httpDownloader;
private $loop;
protected $cache;

View File

@ -114,7 +114,7 @@ class InstalledRepository extends CompositeRepository
foreach ($package->getReplaces() as $link) {
foreach ($needles as $needle) {
if ($link->getSource() === $needle) {
if ($constraint === null || ($link->getConstraint()->matches($constraint) === !$invert)) {
if ($constraint === null || ($link->getConstraint()->matches($constraint) === true)) {
// already displayed this node's dependencies, cutting short
if (in_array($link->getTarget(), $packagesInTree)) {
$results[] = array($package, $link, false);
@ -221,7 +221,7 @@ class InstalledRepository extends CompositeRepository
}
$results[] = array($package, $link, false);
$results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), new MatchAllConstraint, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
$results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), new MatchAllConstraint, Link::TYPE_DOES_NOT_REQUIRE, 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
} else {
// no root so let's just print whatever we found
$results[] = array($package, $link, false);

View File

@ -566,7 +566,7 @@ class PlatformRepository extends ArrayRepository
if ($name === 'uuid') {
$ext->setReplaces(array(
new Link('ext-uuid', 'lib-uuid', new Constraint('=', $version), Link::TYPE_REPLACE, $ext->getPrettyVersion()),
'lib-uuid' => new Link('ext-uuid', 'lib-uuid', new Constraint('=', $version), Link::TYPE_REPLACE, $ext->getPrettyVersion()),
));
}

View File

@ -44,6 +44,7 @@ interface RepositoryInterface extends \Countable
* @param string|ConstraintInterface $constraint package version or version constraint to match against
*
* @return PackageInterface|null
* @phpstan-return (BasePackage&PackageInterface)|null
*/
public function findPackage($name, $constraint);
@ -54,6 +55,7 @@ interface RepositoryInterface extends \Countable
* @param string|ConstraintInterface $constraint package version or version constraint to match against
*
* @return PackageInterface[]
* @phpstan-return array<BasePackage&PackageInterface>
*/
public function findPackages($name, $constraint = null);
@ -61,6 +63,7 @@ interface RepositoryInterface extends \Countable
* Returns list of registered packages.
*
* @return PackageInterface[]
* @phpstan-return array<BasePackage&PackageInterface>
*/
public function getPackages();
@ -75,7 +78,10 @@ interface RepositoryInterface extends \Countable
* @param array<string, BasePackage::STABILITY_*> $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @param array<string, array<string, PackageInterface>> $alreadyLoaded an array of package name => package version => package
*
* @return array{namesFound: string[], packages: PackageInterface[]}
* @return array
*
* @phpstan-param array<string, ConstraintInterface|null> $packageNameMap
* @phpstan-return array{namesFound: string[], packages: array<BasePackage&PackageInterface>}
*/
public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = array());

View File

@ -21,6 +21,7 @@ use Composer\IO\NullIO;
use Composer\Package\BasePackage;
use Composer\Package\AliasPackage;
use Composer\Package\CompleteAliasPackage;
use Composer\Package\CompletePackage;
use Composer\Package\CompletePackageInterface;
use Composer\Semver\Constraint\ConstraintInterface;
use Composer\Package\Version\StabilityFilter;
@ -56,13 +57,13 @@ class RepositorySet
/**
* @var int[] array of stability => BasePackage::STABILITY_* value
* @phpstan-var array<string, int>
* @phpstan-var array<string, BasePackage::STABILITY_*>
*/
private $acceptableStabilities;
/**
* @var int[] array of package name => BasePackage::STABILITY_* value
* @phpstan-var array<string, int>
* @phpstan-var array<string, BasePackage::STABILITY_*>
*/
private $stabilityFlags;
@ -80,7 +81,7 @@ class RepositorySet
*
* @param string $minimumStability
* @param int[] $stabilityFlags an array of package name => BasePackage::STABILITY_* value
* @phpstan-param array<string, int> $stabilityFlags
* @phpstan-param array<string, BasePackage::STABILITY_*> $stabilityFlags
* @param array[] $rootAliases
* @phpstan-param list<array{package: string, version: string, alias: string, alias_normalized: string}> $rootAliases
* @param string[] $rootReferences an array of package name => source reference
@ -254,7 +255,7 @@ class RepositorySet
while ($package instanceof AliasPackage) {
$package = $package->getAliasOf();
}
if ($package instanceof CompletePackageInterface) {
if ($package instanceof CompletePackage) {
$aliasPackage = new CompleteAliasPackage($package, $alias['alias_normalized'], $alias['alias']);
} else {
$aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);

View File

@ -77,6 +77,7 @@ abstract class BitbucketDriver extends VcsDriver
* sets some parameters which are used in other methods
*
* @return bool
* @phpstan-impure
*/
protected function getRepoData()
{
@ -363,6 +364,8 @@ abstract class BitbucketDriver extends VcsDriver
* @param bool $fetchingRepoData
*
* @return Response The result
*
* @phpstan-impure
*/
protected function fetchWithOAuthCredentials($url, $fetchingRepoData = false)
{
@ -396,6 +399,9 @@ abstract class BitbucketDriver extends VcsDriver
*/
abstract protected function generateSshUrl();
/**
* @phpstan-impure
*/
protected function attemptCloneFallback()
{
try {

View File

@ -31,12 +31,10 @@ class HgBitbucketDriver extends BitbucketDriver
if (null === $this->rootIdentifier) {
if (!$this->getRepoData()) {
// @phpstan-ignore-next-line
if (!$this->fallbackDriver) {
throw new \LogicException('A fallback driver should be setup if getRepoData returns false');
}
// @phpstan-ignore-next-line
return $this->fallbackDriver->getRootIdentifier();
}

View File

@ -157,6 +157,7 @@ abstract class VcsDriver implements VcsDriverInterface
* @param string $url The URL of content
*
* @return Response
* @throws TransportException
*/
protected function getContents($url)
{

View File

@ -142,6 +142,7 @@ class CurlDownloader
if ($copyTo) {
$errorMessage = '';
// @phpstan-ignore-next-line
set_error_handler(function ($code, $msg) use (&$errorMessage) {
if ($errorMessage) {
$errorMessage .= "\n";

View File

@ -481,6 +481,7 @@ class HttpDownloader
/**
* @internal
* @return bool
*/
public static function isCurlEnabled()
{

View File

@ -264,7 +264,7 @@ class NoProxyPattern
/**
* Returns the binary network mask mapped to IPv6
*
* @param string $prefix CIDR prefix-length
* @param int $prefix CIDR prefix-length
* @param int $size Byte size of in_addr
*
* @return string
@ -274,7 +274,7 @@ class NoProxyPattern
$mask = '';
if ($ones = floor($prefix / 8)) {
$mask = str_repeat(chr(255), $ones);
$mask = str_repeat(chr(255), (int) $ones);
}
if ($remainder = $prefix % 8) {
@ -291,7 +291,7 @@ class NoProxyPattern
*
* @param string $rangeIp IP in_addr
* @param int $size Byte size of in_addr
* @param string $prefix CIDR prefix-length
* @param int $prefix CIDR prefix-length
*
* @return string[] network in_addr, binary mask
*/

View File

@ -31,7 +31,7 @@ final class StreamContextFactory
* Creates a context supporting HTTP proxies
*
* @param string $url URL the context is to be used for
* @phpstan-param array{http?: array{follow_location?: int, max_redirects?: int, header?: string|array<string, string|int>}} $defaultOptions
* @phpstan-param array{http?: array{follow_location?: int, max_redirects?: int, header?: string|array<string>}} $defaultOptions
* @param array $defaultOptions Options to merge with the default
* @param array $defaultParams Parameters to specify on the context
* @throws \RuntimeException if https proxy required and OpenSSL uninstalled

View File

@ -39,7 +39,7 @@ class SyncHelper
self::await($loop, $downloader->prepare($type, $package, $path, $prevPackage));
if ($type === 'update') {
self::await($loop, $downloader->update($package, $path, $prevPackage));
self::await($loop, $downloader->update($package, $prevPackage, $path));
} else {
self::await($loop, $downloader->install($package, $path));
}

View File

@ -78,7 +78,13 @@ class AllFunctionalTest extends TestCase
}
}
// TODO in v2.3 always call with an array
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
$proc = new Process(array((defined('PHP_BINARY') ? PHP_BINARY : 'php'), '-dphar.readonly=0', './bin/compile'), $target);
} else {
// @phpstan-ignore-next-line
$proc = new Process((defined('PHP_BINARY') ? escapeshellcmd(PHP_BINARY) : 'php').' -dphar.readonly=0 '.escapeshellarg('./bin/compile'), $target);
}
$exitcode = $proc->run();
if ($exitcode !== 0 || trim($proc->getOutput())) {
@ -110,8 +116,15 @@ class AllFunctionalTest extends TestCase
'COMPOSER_CACHE_DIR' => $this->testDir.'cache',
);
$cmd = (defined('PHP_BINARY') ? escapeshellcmd(PHP_BINARY) : 'php') .' '.escapeshellarg(self::$pharPath).' --no-ansi '.$testData['RUN'];
// TODO in v2.3 always call with an array
if (method_exists('Symfony\Component\Process\Process', 'fromShellCommandline')) {
$cmd = array((defined('PHP_BINARY') ? PHP_BINARY : 'php'), self::$pharPath, '--no-ansi', $testData['RUN']);
$proc = new Process($cmd, $this->testDir, $env, null, 300);
} else {
$cmd = (defined('PHP_BINARY') ? escapeshellcmd(PHP_BINARY) : 'php') .' '.escapeshellarg(self::$pharPath).' --no-ansi '.$testData['RUN'];
// @phpstan-ignore-next-line
$proc = new Process($cmd, $this->testDir, $env, null, 300);
}
$output = '';
$exitcode = $proc->run(function ($type, $buffer) use (&$output) {

View File

@ -371,8 +371,8 @@ class AutoloadGeneratorTest extends TestCase
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
));
$packages = array();
@ -400,7 +400,7 @@ class AutoloadGeneratorTest extends TestCase
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
));
$packages = array();
@ -408,11 +408,11 @@ class AutoloadGeneratorTest extends TestCase
$packages[] = $b = new Package('b/b', '1.0', '1.0');
$a->setAutoload(array('psr-0' => array('A' => 'src/', 'A\\B' => 'lib/')));
$a->setRequires(array(
new Link('a/a', 'b/b', new MatchAllConstraint()),
'b/b' => new Link('a/a', 'b/b', new MatchAllConstraint()),
));
$b->setAutoload(array('psr-0' => array('B\\Sub\\Name' => 'src/')));
$b->setRequires(array(
new Link('b/b', 'a/a', new MatchAllConstraint()),
'a/a' => new Link('b/b', 'a/a', new MatchAllConstraint()),
));
$this->repository->expects($this->once())
@ -432,17 +432,17 @@ class AutoloadGeneratorTest extends TestCase
public function testNonDevAutoloadShouldIncludeReplacedPackages()
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(new Link('a', 'a/a', new MatchAllConstraint())));
$package->setRequires(array('a/a' => new Link('a', 'a/a', new MatchAllConstraint())));
$packages = array();
$packages[] = $a = new Package('a/a', '1.0', '1.0');
$packages[] = $b = new Package('b/b', '1.0', '1.0');
$a->setRequires(array(new Link('a/a', 'b/c', new MatchAllConstraint())));
$a->setRequires(array('b/c' => new Link('a/a', 'b/c', new MatchAllConstraint())));
$b->setAutoload(array('psr-4' => array('B\\' => 'src/')));
$b->setReplaces(
array(new Link('b/b', 'b/c', new Constraint('==', '1.0'), Link::TYPE_REPLACE))
array('b/c' => new Link('b/b', 'b/c', new Constraint('==', '1.0'), Link::TYPE_REPLACE))
);
$this->repository->expects($this->once())
@ -467,7 +467,7 @@ class AutoloadGeneratorTest extends TestCase
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
));
$packages = array();
@ -475,11 +475,11 @@ class AutoloadGeneratorTest extends TestCase
$packages[] = $b = new Package('b/b', '1.0', '1.0');
$a->setAutoload(array('psr-0' => array('A' => 'src/', 'A\\B' => 'lib/')));
$a->setRequires(array(
new Link('a/a', 'c/c', new MatchAllConstraint()),
'c/c' => new Link('a/a', 'c/c', new MatchAllConstraint()),
));
$b->setAutoload(array('psr-0' => array('B\\Sub\\Name' => 'src/')));
$b->setReplaces(array(
new Link('b/b', 'c/c', new MatchAllConstraint()),
'c/c' => new Link('b/b', 'c/c', new MatchAllConstraint()),
));
$this->repository->expects($this->once())
@ -500,7 +500,7 @@ class AutoloadGeneratorTest extends TestCase
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
));
$packages = array();
@ -511,18 +511,18 @@ class AutoloadGeneratorTest extends TestCase
$packages[] = $e = new Package('e/e', '1.0', '1.0');
$a->setAutoload(array('classmap' => array('src/A.php')));
$a->setRequires(array(
new Link('a/a', 'b/b', new MatchAllConstraint()),
'b/b' => new Link('a/a', 'b/b', new MatchAllConstraint()),
));
$b->setAutoload(array('classmap' => array('src/B.php')));
$b->setRequires(array(
new Link('b/b', 'e/e', new MatchAllConstraint()),
'e/e' => new Link('b/b', 'e/e', new MatchAllConstraint()),
));
$c->setAutoload(array('classmap' => array('src/C.php')));
$c->setReplaces(array(
new Link('c/c', 'b/b', new MatchAllConstraint()),
'b/b' => new Link('c/c', 'b/b', new MatchAllConstraint()),
));
$c->setRequires(array(
new Link('c/c', 'd/d', new MatchAllConstraint()),
'd/d' => new Link('c/c', 'd/d', new MatchAllConstraint()),
));
$d->setAutoload(array('classmap' => array('src/D.php')));
$e->setAutoload(array('classmap' => array('src/E.php')));
@ -552,7 +552,7 @@ class AutoloadGeneratorTest extends TestCase
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
));
$package->setAutoload(array(
@ -657,8 +657,8 @@ EOF;
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
));
$packages = array();
@ -697,8 +697,8 @@ EOF;
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
));
$packages = array();
@ -737,9 +737,9 @@ EOF;
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
new Link('a', 'c/c', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
'c/c' => new Link('a', 'c/c', new MatchAllConstraint()),
));
$packages = array();
@ -782,9 +782,9 @@ EOF;
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
new Link('a', 'c/c', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
'c/c' => new Link('a', 'c/c', new MatchAllConstraint()),
));
$packages = array();
@ -831,9 +831,9 @@ EOF;
{
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
new Link('a', 'c/c', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
'c/c' => new Link('a', 'c/c', new MatchAllConstraint()),
));
$packages = array();
@ -881,9 +881,9 @@ EOF;
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setAutoload(array('files' => array('root.php')));
$package->setRequires(array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
new Link('a', 'c/c', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
'c/c' => new Link('a', 'c/c', new MatchAllConstraint()),
));
$packages = array();
@ -932,9 +932,9 @@ EOF;
$notAutoloadPackage = new RootPackage('root/a', '1.0', '1.0');
$requires = array(
new Link('a', 'a/a', new MatchAllConstraint()),
new Link('a', 'b/b', new MatchAllConstraint()),
new Link('a', 'c/c', new MatchAllConstraint()),
'a/a' => new Link('a', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
'c/c' => new Link('a', 'c/c', new MatchAllConstraint()),
);
$autoloadPackage->setRequires($requires);
$notAutoloadPackage->setRequires($requires);
@ -1003,10 +1003,10 @@ EOF;
$package = new RootPackage('root/a', '1.0', '1.0');
$package->setAutoload(array('files' => array('root2.php')));
$package->setRequires(array(
new Link('a', 'z/foo', new MatchAllConstraint()),
new Link('a', 'b/bar', new MatchAllConstraint()),
new Link('a', 'd/d', new MatchAllConstraint()),
new Link('a', 'e/e', new MatchAllConstraint()),
'z/foo' => new Link('a', 'z/foo', new MatchAllConstraint()),
'b/bar' => new Link('a', 'b/bar', new MatchAllConstraint()),
'd/d' => new Link('a', 'd/d', new MatchAllConstraint()),
'e/e' => new Link('a', 'e/e', new MatchAllConstraint()),
));
$packages = array();
@ -1017,18 +1017,18 @@ EOF;
$packages[] = $e = new Package('e/e', '1.0', '1.0');
$z->setAutoload(array('files' => array('testA.php')));
$z->setRequires(array(new Link('z/foo', 'c/lorem', new MatchAllConstraint())));
$z->setRequires(array('c/lorem' => new Link('z/foo', 'c/lorem', new MatchAllConstraint())));
$b->setAutoload(array('files' => array('testB.php')));
$b->setRequires(array(new Link('b/bar', 'c/lorem', new MatchAllConstraint()), new Link('b/bar', 'd/d', new MatchAllConstraint())));
$b->setRequires(array('c/lorem' => new Link('b/bar', 'c/lorem', new MatchAllConstraint()), 'd/d' => new Link('b/bar', 'd/d', new MatchAllConstraint())));
$c->setAutoload(array('files' => array('testC.php')));
$d->setAutoload(array('files' => array('testD.php')));
$d->setRequires(array(new Link('d/d', 'c/lorem', new MatchAllConstraint())));
$d->setRequires(array('c/lorem' => new Link('d/d', 'c/lorem', new MatchAllConstraint())));
$e->setAutoload(array('files' => array('testE.php')));
$e->setRequires(array(new Link('e/e', 'c/lorem', new MatchAllConstraint())));
$e->setRequires(array('c/lorem' => new Link('e/e', 'c/lorem', new MatchAllConstraint())));
$this->repository->expects($this->once())
->method('getCanonicalPackages')
@ -1076,8 +1076,8 @@ EOF;
'classmap' => array($this->workingDir.'/src'),
));
$rootPackage->setRequires(array(
new Link('z', 'a/a', new MatchAllConstraint()),
new Link('z', 'b/b', new MatchAllConstraint()),
'a/a' => new Link('z', 'a/a', new MatchAllConstraint()),
'b/b' => new Link('z', 'b/b', new MatchAllConstraint()),
));
$packages = array();
@ -1339,7 +1339,7 @@ EOF;
'files' => array('test.php'),
));
$package->setRequires(array(
new Link('a', 'b/b', new MatchAllConstraint()),
'b/b' => new Link('a', 'b/b', new MatchAllConstraint()),
));
$vendorPackage = new Package('b/b', '1.0', '1.0');

View File

@ -110,7 +110,7 @@ class InitCommandTest extends TestCase
public function testNamespaceFromMissingPackageName()
{
$command = new InitCommand;
$namespace = $command->namespaceFromPackageName(null);
$namespace = $command->namespaceFromPackageName('');
$this->assertNull($namespace);
}
}

View File

@ -16,6 +16,7 @@ use Composer\DependencyResolver\GenericRule;
use Composer\DependencyResolver\Rule;
use Composer\DependencyResolver\RuleSet;
use Composer\DependencyResolver\Pool;
use Composer\Semver\Constraint\MatchNoneConstraint;
use Composer\Test\TestCase;
class RuleSetTest extends TestCase
@ -144,7 +145,7 @@ class RuleSetTest extends TestCase
$ruleSet = new RuleSet;
$literal = $p->getId();
$rule = new GenericRule(array($literal), Rule::RULE_ROOT_REQUIRE, array('packageName' => 'foo/bar', 'constraint' => null));
$rule = new GenericRule(array($literal), Rule::RULE_ROOT_REQUIRE, array('packageName' => 'foo/bar', 'constraint' => new MatchNoneConstraint));
$ruleSet->add($rule, RuleSet::TYPE_REQUEST);

View File

@ -36,8 +36,8 @@ class BufferIOTest extends TestCase
'',
));
$this->assertTrue($bufferIO->askConfirmation('Please say yes!', 'no'));
$this->assertFalse($bufferIO->askConfirmation('Now please say no!', 'yes'));
$this->assertTrue($bufferIO->askConfirmation('Please say yes!', false));
$this->assertFalse($bufferIO->askConfirmation('Now please say no!', true));
$this->assertSame('default', $bufferIO->ask('Empty string last', 'default'));
}
}

View File

@ -191,7 +191,7 @@ class ConsoleIOTest extends TestCase
;
$consoleIO = new ConsoleIO($inputMock, $outputMock, $setMock);
$consoleIO->askConfirmation('Why?', 'default');
$consoleIO->askConfirmation('Why?', false);
}
public function testAskAndValidate()
@ -250,7 +250,7 @@ class ConsoleIOTest extends TestCase
;
$consoleIO = new ConsoleIO($inputMock, $outputMock, $setMock);
$result = $consoleIO->select('Select item', array("item1", "item2"), null, false, "Error message", true);
$result = $consoleIO->select('Select item', array("item1", "item2"), 'item1', false, "Error message", true);
$this->assertEquals(array('1'), $result);
}

View File

@ -58,14 +58,14 @@ class NullIOTest extends TestCase
{
$io = new NullIO();
$this->assertEquals('foo', $io->askConfirmation('bar', 'foo'));
$this->assertEquals(false, $io->askConfirmation('bar', false));
}
public function testAskAndValidate()
{
$io = new NullIO();
$this->assertEquals('foo', $io->askAndValidate('question', 'validator', false, 'foo'));
$this->assertEquals('foo', $io->askAndValidate('question', function ($x) { return true; }, null, 'foo'));
}
public function testSelect()

View File

@ -288,7 +288,7 @@ class LibraryInstallerTest extends TestCase
protected function createPackageMock()
{
return $this->getMockBuilder('Composer\Package\Package')
->setConstructorArgs(array(md5(mt_rand()), '1.0.0.0', '1.0.0'))
->setConstructorArgs(array(md5((string) mt_rand()), '1.0.0.0', '1.0.0'))
->getMock();
}
}

View File

@ -101,7 +101,7 @@ class MetapackageInstallerTest extends TestCase
private function createPackageMock()
{
return $this->getMockBuilder('Composer\Package\Package')
->setConstructorArgs(array(md5(mt_rand()), '1.0.0.0', '1.0.0'))
->setConstructorArgs(array(md5((string) mt_rand()), '1.0.0.0', '1.0.0'))
->getMock();
}
}

View File

@ -279,7 +279,7 @@ class SuggestedPackagesReporterTest extends TestCase
private function createPackageMock()
{
return $this->getMockBuilder('Composer\Package\Package')
->setConstructorArgs(array(md5(mt_rand()), '1.0.0.0', '1.0.0'))
->setConstructorArgs(array(md5((string) mt_rand()), '1.0.0.0', '1.0.0'))
->getMock();
}
}

View File

@ -16,13 +16,14 @@ use Composer\Composer;
use Composer\Config;
use Composer\Factory;
use Composer\Repository\RepositoryManager;
use Composer\Repository\WritableRepositoryInterface;
use Composer\Package\Version\VersionGuesser;
use Composer\Package\Version\VersionParser;
use Composer\Package\RootPackageInterface;
use Composer\Installer;
use Composer\EventDispatcher\EventDispatcher;
use Composer\IO\IOInterface;
use Composer\Repository\InstalledArrayRepository;
use Composer\Repository\InstalledRepositoryInterface;
use Composer\Test\TestCase;
use Composer\Util\Loop;
use Composer\Util\ProcessExecutor;
@ -48,6 +49,7 @@ class FactoryMock extends Factory
protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir, RootPackageInterface $rootPackage, ProcessExecutor $process = null)
{
$rm->setLocalRepository(new InstalledArrayRepository);
}
public function createInstallationManager(Loop $loop, IOInterface $io, EventDispatcher $dispatcher = null)
@ -59,7 +61,7 @@ class FactoryMock extends Factory
{
}
protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
protected function purgePackages(InstalledRepositoryInterface $repo, Installer\InstallationManager $im)
{
}
}

View File

@ -30,7 +30,7 @@ class ProcessExecutorMock extends ProcessExecutor
private $log = array();
/**
* @param array<string|array{cmd: string, return: int, stdout?: string, stderr?: string, callback?: callable}> $expectations
* @param array<string|array{cmd: string, return?: int, stdout?: string, stderr?: string, callback?: callable}> $expectations
* @param bool $strict set to true if you want to provide *all* expected commands, and not just a subset you are interested in testing
* @param array{return: int, stdout?: string, stderr?: string} $defaultHandler default command handler for undefined commands if not in strict mode
*/

View File

@ -15,6 +15,7 @@ namespace Composer\Test\Package\Archiver;
use Composer\IO\NullIO;
use Composer\Factory;
use Composer\Package\Archiver\ArchiveManager;
use Composer\Package\CompletePackage;
use Composer\Package\PackageInterface;
use Composer\Util\Loop;
use Composer\Test\Mock\FactoryMock;
@ -95,7 +96,7 @@ class ArchiveManagerTest extends ArchiverTest
unlink($target);
}
protected function getTargetName(PackageInterface $package, $format, $fileName = null)
protected function getTargetName(CompletePackage $package, $format, $fileName = null)
{
if (null === $fileName) {
$packageName = $this->manager->getPackageFilename($package);

View File

@ -178,7 +178,7 @@ class ArrayDumperTest extends TestCase
),
array(
'require-dev',
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), 'requires (for development)', '1.0.0')),
array(new Link('foo', 'foo/bar', new Constraint('=', '1.0.0.0'), Link::TYPE_DEV_REQUIRE, '1.0.0')),
'devRequires',
array('foo/bar' => '1.0.0'),
),

View File

@ -14,6 +14,7 @@ namespace Composer\Test\Package\Loader;
use Composer\Package\Loader\ArrayLoader;
use Composer\Package\Dumper\ArrayDumper;
use Composer\Package\Link;
use Composer\Test\TestCase;
class ArrayLoaderTest extends TestCase
@ -287,7 +288,7 @@ class ArrayLoaderTest extends TestCase
*/
public function testPluginApiVersionAreKeptAsDeclared($apiVersion)
{
$links = $this->loader->parseLinks('Plugin', '9.9.9', '', array('composer-plugin-api' => $apiVersion));
$links = $this->loader->parseLinks('Plugin', '9.9.9', Link::TYPE_REQUIRE, array('composer-plugin-api' => $apiVersion));
$this->assertArrayHasKey('composer-plugin-api', $links);
$this->assertSame($apiVersion, $links['composer-plugin-api']->getConstraint()->getPrettyString());
@ -295,7 +296,7 @@ class ArrayLoaderTest extends TestCase
public function testPluginApiVersionDoesSupportSelfVersion()
{
$links = $this->loader->parseLinks('Plugin', '6.6.6', '', array('composer-plugin-api' => 'self.version'));
$links = $this->loader->parseLinks('Plugin', '6.6.6', Link::TYPE_REQUIRE, array('composer-plugin-api' => 'self.version'));
$this->assertArrayHasKey('composer-plugin-api', $links);
$this->assertSame('6.6.6', $links['composer-plugin-api']->getConstraint()->getPrettyString());

View File

@ -27,7 +27,7 @@ class RootAliasPackageTest extends TestCase
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
$this->assertEmpty($alias->getRequires());
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
$links = array(new Link('a', 'b', new MatchAllConstraint(), Link::TYPE_REQUIRE, 'self.version'));
$alias->setRequires($links);
$this->assertNotEmpty($alias->getRequires());
}
@ -39,7 +39,7 @@ class RootAliasPackageTest extends TestCase
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
$this->assertEmpty($alias->getDevRequires());
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
$links = array(new Link('a', 'b', new MatchAllConstraint(), Link::TYPE_DEV_REQUIRE, 'self.version'));
$alias->setDevRequires($links);
$this->assertNotEmpty($alias->getDevRequires());
}
@ -51,7 +51,7 @@ class RootAliasPackageTest extends TestCase
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
$this->assertEmpty($alias->getConflicts());
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
$links = array(new Link('a', 'b', new MatchAllConstraint(), Link::TYPE_CONFLICT, 'self.version'));
$alias->setConflicts($links);
$this->assertNotEmpty($alias->getConflicts());
}
@ -63,7 +63,7 @@ class RootAliasPackageTest extends TestCase
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
$this->assertEmpty($alias->getProvides());
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
$links = array(new Link('a', 'b', new MatchAllConstraint(), Link::TYPE_PROVIDE, 'self.version'));
$alias->setProvides($links);
$this->assertNotEmpty($alias->getProvides());
}
@ -75,7 +75,7 @@ class RootAliasPackageTest extends TestCase
$alias = new RootAliasPackage($root->reveal(), '1.0', '1.0.0.0');
$this->assertEmpty($alias->getReplaces());
$links = array(new Link('a', 'b', new MatchAllConstraint(), 'foo', 'self.version'));
$links = array(new Link('a', 'b', new MatchAllConstraint(), Link::TYPE_REPLACE, 'self.version'));
$alias->setReplaces($links);
$this->assertNotEmpty($alias->getReplaces());
}

View File

@ -54,12 +54,12 @@ class PluginInstallerTest extends TestCase
protected $directory;
/**
* @var \PHPUnit\Framework\MockObject\MockObject
* @var \PHPUnit\Framework\MockObject\MockObject&\Composer\Installer\InstallationManager
*/
protected $im;
/**
* @var \PHPUnit\Framework\MockObject\MockObject
* @var \PHPUnit\Framework\MockObject\MockObject&\Composer\Repository\InstalledRepositoryInterface
*/
protected $repository;

View File

@ -13,6 +13,7 @@
namespace Composer\Test\Repository;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Repository\PlatformRepository;
use Composer\Test\TestCase;
use PHPUnit\Framework\Assert;
@ -1189,7 +1190,7 @@ Linked Version => 1.2.11',
}
}
private function assertPackageLinks($context, array $expectedLinks, Package $sourcePackage, array $links)
private function assertPackageLinks($context, array $expectedLinks, PackageInterface $sourcePackage, array $links)
{
self::assertCount(count($expectedLinks), $links, sprintf('%s: expected package count to match', $context));

View File

@ -94,7 +94,7 @@ abstract class TestCase extends PolyfillTestCase
$arrayLoader->parseLinks(
$package->getName(),
$package->getPrettyVersion(),
$opts['description'],
$opts['method'],
$config[$type]
)
);

View File

@ -22,7 +22,7 @@ class MetadataMinifierTest extends TestCase
public function testMinifyExpand()
{
$package1 = new CompletePackage('foo/bar', '2.0.0.0', '2.0.0');
$package1->setScripts(array('foo' => 'bar'));
$package1->setScripts(array('foo' => array('bar')));
$package1->setLicense(array('MIT'));
$package2 = new CompletePackage('foo/bar', '1.2.0.0', '1.2.0');
$package2->setLicense(array('GPL'));
@ -32,7 +32,7 @@ class MetadataMinifierTest extends TestCase
$dumper = new ArrayDumper();
$minified = array(
array('name' => 'foo/bar', 'version' => '2.0.0', 'version_normalized' => '2.0.0.0', 'type' => 'library', 'scripts' => array('foo' => 'bar'), 'license' => array('MIT')),
array('name' => 'foo/bar', 'version' => '2.0.0', 'version_normalized' => '2.0.0.0', 'type' => 'library', 'scripts' => array('foo' => array('bar')), 'license' => array('MIT')),
array('version' => '1.2.0', 'version_normalized' => '1.2.0.0', 'license' => array('GPL'), 'homepage' => 'https://example.org', 'scripts' => '__unset'),
array('version' => '1.0.0', 'version_normalized' => '1.0.0.0', 'homepage' => '__unset'),
);

View File

@ -123,7 +123,7 @@ class PackageSorterTest extends TestCase
$links = array();
foreach ($requires as $requireName) {
$links[] = new Link($package->getName(), $requireName, new MatchAllConstraint);
$links[$requireName] = new Link($package->getName(), $requireName, new MatchAllConstraint);
}
$package->setRequires($links);