Fix type errors and tests
parent
55dc80862e
commit
b52053893c
|
@ -66,7 +66,7 @@ trait CompletionTrait
|
||||||
if ($locker->isLocked()) {
|
if ($locker->isLocked()) {
|
||||||
$platformRepo = new PlatformRepository(array(), $locker->getPlatformOverrides());
|
$platformRepo = new PlatformRepository(array(), $locker->getPlatformOverrides());
|
||||||
} else {
|
} else {
|
||||||
$platformRepo = new PlatformRepository(array(), $composer->getConfig()->get('platform') ?: array());
|
$platformRepo = new PlatformRepository(array(), $composer->getConfig()->get('platform'));
|
||||||
}
|
}
|
||||||
if ($input->getCompletionValue() === '') {
|
if ($input->getCompletionValue() === '') {
|
||||||
// to reduce noise, when no text is yet entered we list only two entries for ext- and lib- prefixes
|
// to reduce noise, when no text is yet entered we list only two entries for ext- and lib- prefixes
|
||||||
|
@ -115,36 +115,43 @@ trait CompletionTrait
|
||||||
$repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
|
$repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
|
||||||
|
|
||||||
$results = [];
|
$results = [];
|
||||||
|
$showVendors = false;
|
||||||
if (!str_contains($input->getCompletionValue(), '/')) {
|
if (!str_contains($input->getCompletionValue(), '/')) {
|
||||||
$results = $repos->search('^' . preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_VENDOR);
|
$results = $repos->search('^' . preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_VENDOR);
|
||||||
$vendors = true;
|
$showVendors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we get a single vendor, we expand it into its contents already
|
// if we get a single vendor, we expand it into its contents already
|
||||||
if (\count($results) <= 1) {
|
if (\count($results) <= 1) {
|
||||||
$results = $repos->search('^'.preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_NAME);
|
$results = $repos->search('^'.preg_quote($input->getCompletionValue()), RepositoryInterface::SEARCH_NAME);
|
||||||
$vendors = false;
|
$showVendors = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$results = array_column($results, 'name');
|
$results = array_column($results, 'name');
|
||||||
|
|
||||||
if ($vendors) {
|
if ($showVendors) {
|
||||||
$results = array_map(function (string $name): string {
|
$results = array_map(function (string $name): string {
|
||||||
return $name.'/';
|
return $name.'/';
|
||||||
}, $results);
|
}, $results);
|
||||||
|
|
||||||
// sort shorter results first to avoid auto-expanding the completion to a longer string than needed
|
// sort shorter results first to avoid auto-expanding the completion to a longer string than needed
|
||||||
usort($results, function (string $a, string $b) {
|
usort($results, function (string $a, string $b) {
|
||||||
return \strlen($a) - \strlen($b);
|
$lenA = \strlen($a);
|
||||||
|
$lenB = \strlen($b);
|
||||||
|
if ($lenA === $lenB) {
|
||||||
|
return $a <=> $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $lenA - $lenB;
|
||||||
});
|
});
|
||||||
|
|
||||||
$pinned = [];
|
$pinned = [];
|
||||||
|
|
||||||
// ensure if the input is an exact match that it is always in the result set
|
// ensure if the input is an exact match that it is always in the result set
|
||||||
$completionInput = $input->getCompletionValue().'/';
|
$completionInput = $input->getCompletionValue().'/';
|
||||||
if (in_array($completionInput, $results, true)) {
|
if (false !== ($exactIndex = array_search($completionInput, $results, true))) {
|
||||||
$pinned[] = $completionInput;
|
$pinned[] = $completionInput;
|
||||||
array_splice($results, array_search($completionInput, $results, true), 1);
|
array_splice($results, $exactIndex, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_merge($pinned, array_slice($results, 0, $max - \count($pinned)));
|
return array_merge($pinned, array_slice($results, 0, $max - \count($pinned)));
|
||||||
|
@ -177,7 +184,7 @@ trait CompletionTrait
|
||||||
private function suggestPlatformPackage(): \Closure
|
private function suggestPlatformPackage(): \Closure
|
||||||
{
|
{
|
||||||
return function (CompletionInput $input): array {
|
return function (CompletionInput $input): array {
|
||||||
$repos = new PlatformRepository([], $this->requireComposer()->getConfig()->get('platform') ?? []);
|
$repos = new PlatformRepository([], $this->requireComposer()->getConfig()->get('platform'));
|
||||||
|
|
||||||
$pattern = BasePackage::packageNameToRegexp($input->getCompletionValue().'*');
|
$pattern = BasePackage::packageNameToRegexp($input->getCompletionValue().'*');
|
||||||
return array_filter(array_map(function (PackageInterface $package) {
|
return array_filter(array_map(function (PackageInterface $package) {
|
||||||
|
|
|
@ -159,7 +159,7 @@ EOT
|
||||||
$preferSource,
|
$preferSource,
|
||||||
$preferDist,
|
$preferDist,
|
||||||
!$input->getOption('no-dev'),
|
!$input->getOption('no-dev'),
|
||||||
$input->getOption('repository') ?: $input->getOption('repository-url'),
|
\count($input->getOption('repository')) > 0 ? $input->getOption('repository') : $input->getOption('repository-url'),
|
||||||
$input->getOption('no-plugins'),
|
$input->getOption('no-plugins'),
|
||||||
$input->getOption('no-scripts'),
|
$input->getOption('no-scripts'),
|
||||||
$input->getOption('no-progress'),
|
$input->getOption('no-progress'),
|
||||||
|
@ -197,7 +197,7 @@ EOT
|
||||||
$repositories = (array) $repositories;
|
$repositories = (array) $repositories;
|
||||||
}
|
}
|
||||||
|
|
||||||
$platformRequirementFilter = $platformRequirementFilter ?: PlatformRequirementFilterFactory::ignoreNothing();
|
$platformRequirementFilter = $platformRequirementFilter ?? PlatformRequirementFilterFactory::ignoreNothing();
|
||||||
|
|
||||||
// we need to manually load the configuration to pass the auth credentials to the io interface!
|
// we need to manually load the configuration to pass the auth credentials to the io interface!
|
||||||
$io->loadConfiguration($config);
|
$io->loadConfiguration($config);
|
||||||
|
@ -424,7 +424,7 @@ EOT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$platformOverrides = $config->get('platform') ?: array();
|
$platformOverrides = $config->get('platform');
|
||||||
$platformRepo = new PlatformRepository(array(), $platformOverrides);
|
$platformRepo = new PlatformRepository(array(), $platformOverrides);
|
||||||
|
|
||||||
// find the latest version if there are multiple
|
// find the latest version if there are multiple
|
||||||
|
|
|
@ -119,6 +119,10 @@ EOT
|
||||||
|
|
||||||
private function prepareSubcommandInput(InputInterface $input, bool $quiet = false): StringInput
|
private function prepareSubcommandInput(InputInterface $input, bool $quiet = false): StringInput
|
||||||
{
|
{
|
||||||
|
if (!method_exists($input, '__toString')) {
|
||||||
|
throw new \LogicException('Expected an Input instance that is stringable, got '.get_class($input));
|
||||||
|
}
|
||||||
|
|
||||||
// The COMPOSER env var should not apply to the global execution scope
|
// The COMPOSER env var should not apply to the global execution scope
|
||||||
if (Platform::getEnv('COMPOSER')) {
|
if (Platform::getEnv('COMPOSER')) {
|
||||||
Platform::clearEnv('COMPOSER');
|
Platform::clearEnv('COMPOSER');
|
||||||
|
|
|
@ -99,7 +99,7 @@ trait PackageDiscoveryTrait
|
||||||
foreach ($requires as $requirement) {
|
foreach ($requires as $requirement) {
|
||||||
if (!isset($requirement['version'])) {
|
if (!isset($requirement['version'])) {
|
||||||
// determine the best version automatically
|
// determine the best version automatically
|
||||||
list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $platformRepo, $preferredStability, null, null, $fixed);
|
list($name, $version) = $this->findBestVersionAndNameForPackage($input, $requirement['name'], $platformRepo, $preferredStability, $fixed);
|
||||||
$requirement['version'] = $version;
|
$requirement['version'] = $version;
|
||||||
|
|
||||||
// replace package name from packagist.org
|
// replace package name from packagist.org
|
||||||
|
@ -268,7 +268,7 @@ trait PackageDiscoveryTrait
|
||||||
* @throws \InvalidArgumentException
|
* @throws \InvalidArgumentException
|
||||||
* @return array{string, string} name version
|
* @return array{string, string} name version
|
||||||
*/
|
*/
|
||||||
private function findBestVersionAndNameForPackage(InputInterface $input, string $name, ?PlatformRepository $platformRepo = null, string $preferredStability = 'stable', ?string $requiredVersion = null, ?string $minimumStability = null, bool $fixed = false): array
|
private function findBestVersionAndNameForPackage(InputInterface $input, string $name, ?PlatformRepository $platformRepo = null, string $preferredStability = 'stable', bool $fixed = false): array
|
||||||
{
|
{
|
||||||
// handle ignore-platform-reqs flag if present
|
// handle ignore-platform-reqs flag if present
|
||||||
if ($input->hasOption('ignore-platform-reqs') && $input->hasOption('ignore-platform-req')) {
|
if ($input->hasOption('ignore-platform-reqs') && $input->hasOption('ignore-platform-req')) {
|
||||||
|
@ -278,17 +278,17 @@ trait PackageDiscoveryTrait
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the latest version allowed in this repo set
|
// find the latest version allowed in this repo set
|
||||||
$repoSet = $this->getRepositorySet($input, $minimumStability);
|
$repoSet = $this->getRepositorySet($input);
|
||||||
$versionSelector = new VersionSelector($repoSet, $platformRepo);
|
$versionSelector = new VersionSelector($repoSet, $platformRepo);
|
||||||
$effectiveMinimumStability = $minimumStability ?? $this->getMinimumStability($input);
|
$effectiveMinimumStability = $this->getMinimumStability($input);
|
||||||
|
|
||||||
$package = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, $platformRequirementFilter);
|
$package = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter);
|
||||||
|
|
||||||
if (false === $package) {
|
if (false === $package) {
|
||||||
// platform packages can not be found in the pool in versions other than the local platform's has
|
// platform packages can not be found in the pool in versions other than the local platform's has
|
||||||
// so if platform reqs are ignored we just take the user's word for it
|
// so if platform reqs are ignored we just take the user's word for it
|
||||||
if ($platformRequirementFilter->isIgnored($name)) {
|
if ($platformRequirementFilter->isIgnored($name)) {
|
||||||
return array($name, $requiredVersion ?: '*');
|
return array($name, '*');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it is a virtual package provided by others
|
// Check if it is a virtual package provided by others
|
||||||
|
@ -308,17 +308,16 @@ trait PackageDiscoveryTrait
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the package requirements were the problem
|
// Check whether the package requirements were the problem
|
||||||
if (!($platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter) && false !== ($candidate = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, PlatformRequirementFilterFactory::ignoreAll()))) {
|
if (!($platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter) && false !== ($candidate = $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll()))) {
|
||||||
throw new \InvalidArgumentException(sprintf(
|
throw new \InvalidArgumentException(sprintf(
|
||||||
'Package %s%s has requirements incompatible with your PHP version, PHP extensions and Composer version' . $this->getPlatformExceptionDetails($candidate, $platformRepo),
|
'Package %s has requirements incompatible with your PHP version, PHP extensions and Composer version' . $this->getPlatformExceptionDetails($candidate, $platformRepo),
|
||||||
$name,
|
$name
|
||||||
is_string($requiredVersion) ? ' at version '.$requiredVersion : ''
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// Check whether the minimum stability was the problem but the package exists
|
// Check whether the minimum stability was the problem but the package exists
|
||||||
if (false !== ($package = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, $platformRequirementFilter, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES))) {
|
if (false !== ($package = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter, RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES))) {
|
||||||
// we must first verify if a valid package would be found in a lower priority repository
|
// we must first verify if a valid package would be found in a lower priority repository
|
||||||
if (false !== ($allReposPackage = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, $platformRequirementFilter, RepositorySet::ALLOW_SHADOWED_REPOSITORIES))) {
|
if (false !== ($allReposPackage = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter, RepositorySet::ALLOW_SHADOWED_REPOSITORIES))) {
|
||||||
throw new \InvalidArgumentException(
|
throw new \InvalidArgumentException(
|
||||||
'Package '.$name.' exists in '.$allReposPackage->getRepository()->getRepoName().' and '.$package->getRepository()->getRepoName().' which has a higher repository priority. The packages from the higher priority repository do not match your minimum-stability and are therefore not installable. That repository is canonical so the lower priority repo\'s packages are not installable. See https://getcomposer.org/repoprio for details and assistance.'
|
'Package '.$name.' exists in '.$allReposPackage->getRepository()->getRepoName().' and '.$package->getRepository()->getRepoName().' which has a higher repository priority. The packages from the higher priority repository do not match your minimum-stability and are therefore not installable. That repository is canonical so the lower priority repo\'s packages are not installable. See https://getcomposer.org/repoprio for details and assistance.'
|
||||||
);
|
);
|
||||||
|
@ -330,21 +329,6 @@ trait PackageDiscoveryTrait
|
||||||
$effectiveMinimumStability
|
$effectiveMinimumStability
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
// Check whether the required version was the problem
|
|
||||||
if (is_string($requiredVersion) && false !== ($package = $versionSelector->findBestCandidate($name, null, $preferredStability, $platformRequirementFilter))) {
|
|
||||||
// we must first verify if a valid package would be found in a lower priority repository
|
|
||||||
if (false !== ($allReposPackage = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, PlatformRequirementFilterFactory::ignoreNothing(), RepositorySet::ALLOW_SHADOWED_REPOSITORIES))) {
|
|
||||||
throw new \InvalidArgumentException(
|
|
||||||
'Package '.$name.' exists in '.$allReposPackage->getRepository()->getRepoName().' and '.$package->getRepository()->getRepoName().' which has a higher repository priority. The packages from the higher priority repository do not match your constraint and are therefore not installable. That repository is canonical so the lower priority repo\'s packages are not installable. See https://getcomposer.org/repoprio for details and assistance.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new \InvalidArgumentException(sprintf(
|
|
||||||
'Could not find package %s in a version matching "%s" and a stability matching "'.$effectiveMinimumStability.'".',
|
|
||||||
$name,
|
|
||||||
$requiredVersion
|
|
||||||
));
|
|
||||||
}
|
|
||||||
// Check whether the PHP version was the problem for all versions
|
// Check whether the PHP version was the problem for all versions
|
||||||
if (!$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter && false !== ($candidate = $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll(), RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES))) {
|
if (!$platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter && false !== ($candidate = $versionSelector->findBestCandidate($name, null, $preferredStability, PlatformRequirementFilterFactory::ignoreAll(), RepositorySet::ALLOW_UNACCEPTABLE_STABILITIES))) {
|
||||||
$additional = '';
|
$additional = '';
|
||||||
|
|
|
@ -187,7 +187,7 @@ EOT
|
||||||
// init repos
|
// init repos
|
||||||
$platformOverrides = array();
|
$platformOverrides = array();
|
||||||
if ($composer) {
|
if ($composer) {
|
||||||
$platformOverrides = $composer->getConfig()->get('platform') ?: array();
|
$platformOverrides = $composer->getConfig()->get('platform');
|
||||||
}
|
}
|
||||||
$platformRepo = new PlatformRepository(array(), $platformOverrides);
|
$platformRepo = new PlatformRepository(array(), $platformOverrides);
|
||||||
$lockedRepo = null;
|
$lockedRepo = null;
|
||||||
|
|
|
@ -65,7 +65,7 @@ EOT
|
||||||
$installedRepos[] = new PlatformRepository(array(), $locker->getPlatformOverrides());
|
$installedRepos[] = new PlatformRepository(array(), $locker->getPlatformOverrides());
|
||||||
$installedRepos[] = $locker->getLockedRepository(!$input->getOption('no-dev'));
|
$installedRepos[] = $locker->getLockedRepository(!$input->getOption('no-dev'));
|
||||||
} else {
|
} else {
|
||||||
$installedRepos[] = new PlatformRepository(array(), $composer->getConfig()->get('platform') ?: array());
|
$installedRepos[] = new PlatformRepository(array(), $composer->getConfig()->get('platform'));
|
||||||
$installedRepos[] = $composer->getRepositoryManager()->getLocalRepository();
|
$installedRepos[] = $composer->getRepositoryManager()->getLocalRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ class InputArgument extends BaseInputArgument
|
||||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||||
{
|
{
|
||||||
$values = $this->suggestedValues;
|
$values = $this->suggestedValues;
|
||||||
if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) {
|
if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) { // @phpstan-ignore-line
|
||||||
throw new LogicException(sprintf('Closure for option "%s" must return an array. Got "%s".', $this->getName(), get_debug_type($values)));
|
throw new LogicException(sprintf('Closure for option "%s" must return an array. Got "%s".', $this->getName(), get_debug_type($values)));
|
||||||
}
|
}
|
||||||
if ([] !== $values) {
|
if ([] !== $values) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ class InputOption extends BaseInputOption
|
||||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||||
{
|
{
|
||||||
$values = $this->suggestedValues;
|
$values = $this->suggestedValues;
|
||||||
if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) {
|
if ($values instanceof \Closure && !\is_array($values = $values($input, $suggestions))) { // @phpstan-ignore-line
|
||||||
throw new LogicException(sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->getName(), get_debug_type($values)));
|
throw new LogicException(sprintf('Closure for argument "%s" must return an array. Got "%s".', $this->getName(), get_debug_type($values)));
|
||||||
}
|
}
|
||||||
if ([] !== $values) {
|
if ([] !== $values) {
|
||||||
|
|
|
@ -27,34 +27,34 @@ class CompletionFunctionalTest extends TestCase
|
||||||
*/
|
*/
|
||||||
public function getCommandSuggestions(): iterable
|
public function getCommandSuggestions(): iterable
|
||||||
{
|
{
|
||||||
$randomProject = '104corp/cache';
|
$randomVendor = 'a/';
|
||||||
$installedPackages = ['composer/semver', 'psr/log'];
|
$installedPackages = ['composer/semver', 'psr/log'];
|
||||||
$preferInstall = ['dist', 'source', 'auto'];
|
$preferInstall = ['dist', 'source', 'auto'];
|
||||||
|
|
||||||
yield ['archive ', [$randomProject]];
|
yield ['archive ', [$randomVendor]];
|
||||||
yield ['archive symfony/http-', ['symfony/http-kernel', 'symfony/http-foundation']];
|
yield ['archive symfony/http-', ['symfony/http-kernel', 'symfony/http-foundation']];
|
||||||
yield ['archive --format ', ['tar', 'zip']];
|
yield ['archive --format ', ['tar', 'zip']];
|
||||||
|
|
||||||
yield ['create-project ', [$randomProject]];
|
yield ['create-project ', [$randomVendor]];
|
||||||
yield ['create-project symfony/skeleton --prefer-install ', $preferInstall];
|
yield ['create-project symfony/skeleton --prefer-install ', $preferInstall];
|
||||||
|
|
||||||
yield ['depends ', $installedPackages];
|
yield ['depends ', $installedPackages];
|
||||||
yield ['why ', $installedPackages];
|
yield ['why ', $installedPackages];
|
||||||
|
|
||||||
yield ['exec ', ['composer', 'compile']];
|
yield ['exec ', ['composer', 'jsonlint', 'phpstan', 'phpstan.phar', 'simple-phpunit', 'validate-json']];
|
||||||
|
|
||||||
yield ['browse ', $installedPackages];
|
yield ['browse ', $installedPackages];
|
||||||
yield ['home -H ', $installedPackages];
|
yield ['home -H ', $installedPackages];
|
||||||
|
|
||||||
yield ['init --require ', [$randomProject]];
|
yield ['init --require ', [$randomVendor]];
|
||||||
yield ['init --require-dev foo/bar --require-dev ', [$randomProject]];
|
yield ['init --require-dev foo/bar --require-dev ', [$randomVendor]];
|
||||||
|
|
||||||
yield ['install --prefer-install ', $preferInstall];
|
yield ['install --prefer-install ', $preferInstall];
|
||||||
yield ['install ', $installedPackages];
|
yield ['install ', $installedPackages];
|
||||||
|
|
||||||
yield ['outdated ', $installedPackages];
|
yield ['outdated ', $installedPackages];
|
||||||
|
|
||||||
yield ['prohibits ', [$randomProject]];
|
yield ['prohibits ', [$randomVendor]];
|
||||||
yield ['why-not symfony/http-ker', ['symfony/http-kernel']];
|
yield ['why-not symfony/http-ker', ['symfony/http-kernel']];
|
||||||
|
|
||||||
yield ['reinstall --prefer-install ', $preferInstall];
|
yield ['reinstall --prefer-install ', $preferInstall];
|
||||||
|
@ -63,7 +63,7 @@ class CompletionFunctionalTest extends TestCase
|
||||||
yield ['remove ', $installedPackages];
|
yield ['remove ', $installedPackages];
|
||||||
|
|
||||||
yield ['require --prefer-install ', $preferInstall];
|
yield ['require --prefer-install ', $preferInstall];
|
||||||
yield ['require ', [$randomProject]];
|
yield ['require ', [$randomVendor]];
|
||||||
yield ['require --dev symfony/http-', ['symfony/http-kernel', 'symfony/http-foundation']];
|
yield ['require --dev symfony/http-', ['symfony/http-kernel', 'symfony/http-foundation']];
|
||||||
|
|
||||||
yield ['run-script ', ['compile', 'test', 'phpstan']];
|
yield ['run-script ', ['compile', 'test', 'phpstan']];
|
||||||
|
|
Loading…
Reference in New Issue