1
0
Fork 0

Reaching phpstan level 6 in Composer/Autoload (refs #10159) (#10179)

Co-authored-by: Jordi Boggiano <j.boggiano@seld.be>
pull/10186/head
immeëmosol 2021-10-18 23:40:22 +02:00 committed by GitHub
parent 57e417b53a
commit be25cf1d7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 121 additions and 44 deletions

View File

@ -22,7 +22,6 @@ use Composer\Package\RootPackageInterface;
use Composer\Repository\InstalledRepositoryInterface; use Composer\Repository\InstalledRepositoryInterface;
use Composer\Repository\PlatformRepository; use Composer\Repository\PlatformRepository;
use Composer\Semver\Constraint\Bound; use Composer\Semver\Constraint\Bound;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Util\Filesystem; use Composer\Util\Filesystem;
use Composer\Util\Platform; use Composer\Util\Platform;
use Composer\Script\ScriptEvents; use Composer\Script\ScriptEvents;
@ -71,7 +70,7 @@ class AutoloadGenerator
private $runScripts = false; private $runScripts = false;
/** /**
* @var bool|array * @var bool|string[]
*/ */
private $ignorePlatformReqs = false; private $ignorePlatformReqs = false;
@ -81,16 +80,20 @@ class AutoloadGenerator
$this->io = $io; $this->io = $io;
} }
/**
* @param bool $devMode
* @return void
*/
public function setDevMode($devMode = true) public function setDevMode($devMode = true)
{ {
$this->devMode = (bool) $devMode; $this->devMode = (bool) $devMode;
} }
/** /**
* Whether or not generated autoloader considers the class map * Whether generated autoloader considers the class map authoritative.
* authoritative.
* *
* @param bool $classMapAuthoritative * @param bool $classMapAuthoritative
* @return void
*/ */
public function setClassMapAuthoritative($classMapAuthoritative) public function setClassMapAuthoritative($classMapAuthoritative)
{ {
@ -98,10 +101,11 @@ class AutoloadGenerator
} }
/** /**
* Whether or not generated autoloader considers APCu caching. * Whether generated autoloader considers APCu caching.
* *
* @param bool $apcu * @param bool $apcu
* @param string|null $apcuPrefix * @param string|null $apcuPrefix
* @return void
*/ */
public function setApcu($apcu, $apcuPrefix = null) public function setApcu($apcu, $apcuPrefix = null)
{ {
@ -110,9 +114,10 @@ class AutoloadGenerator
} }
/** /**
* Set whether to run scripts or not * Whether to run scripts or not
* *
* @param bool $runScripts * @param bool $runScripts
* @return void
*/ */
public function setRunScripts($runScripts = true) public function setRunScripts($runScripts = true)
{ {
@ -120,13 +125,14 @@ class AutoloadGenerator
} }
/** /**
* Sets whether platform requirements should be ignored * Whether platform requirements should be ignored.
* *
* If this is set to true, the platform check file will not be generated * If this is set to true, the platform check file will not be generated
* If this is set to false, the platform check file will be generated with all requirements * If this is set to false, the platform check file will be generated with all requirements
* If this is set to string[], those packages will be ignored from the platform check file * If this is set to string[], those packages will be ignored from the platform check file
* *
* @param array|bool $ignorePlatformReqs * @param bool|string[] $ignorePlatformReqs
* @return void
*/ */
public function setIgnorePlatformRequirements($ignorePlatformReqs) public function setIgnorePlatformRequirements($ignorePlatformReqs)
{ {
@ -140,7 +146,11 @@ class AutoloadGenerator
} }
/** /**
* @param string $targetDir
* @param bool $scanPsrPackages
* @param string $suffix
* @return int * @return int
* @throws \Seld\JsonLint\ParsingException
*/ */
public function dump(Config $config, InstalledRepositoryInterface $localRepo, RootPackageInterface $rootPackage, InstallationManager $installationManager, $targetDir, $scanPsrPackages = false, $suffix = '') public function dump(Config $config, InstalledRepositoryInterface $localRepo, RootPackageInterface $rootPackage, InstallationManager $installationManager, $targetDir, $scanPsrPackages = false, $suffix = '')
{ {
@ -410,8 +420,16 @@ EOF;
} }
/** /**
* @param string $basePath
* @param string $vendorPath
* @param string $dir
* @param ?array<int, string> $excluded * @param ?array<int, string> $excluded
* @return array<string, string> * @param ?string $namespaceFilter
* @param ?string $autoloadType
* @param array<class-string, string> $classMap
* @param array<class-string, array<int, string>> $ambiguousClasses
* @param array<string, true> $scannedFiles
* @return array<class-string, string>
*/ */
private function addClassMapCode(Filesystem $filesystem, $basePath, $vendorPath, $dir, $excluded, $namespaceFilter, $autoloadType, array $classMap, array &$ambiguousClasses, array &$scannedFiles) private function addClassMapCode(Filesystem $filesystem, $basePath, $vendorPath, $dir, $excluded, $namespaceFilter, $autoloadType, array $classMap, array &$ambiguousClasses, array &$scannedFiles)
{ {
@ -428,7 +446,12 @@ EOF;
} }
/** /**
* @param string $dir
* @param ?array<int, string> $excluded * @param ?array<int, string> $excluded
* @param ?string $namespaceFilter
* @param ?string $autoloadType
* @param bool $showAmbiguousWarning
* @param array<string, true> $scannedFiles
* @return array<class-string, string> * @return array<class-string, string>
*/ */
private function generateClassMap($dir, $excluded, $namespaceFilter, $autoloadType, $showAmbiguousWarning, array &$scannedFiles) private function generateClassMap($dir, $excluded, $namespaceFilter, $autoloadType, $showAmbiguousWarning, array &$scannedFiles)
@ -457,7 +480,8 @@ EOF;
} }
/** /**
* @param RootPackageInterface $rootPackage * @param InstallationManager $installationManager
* @param PackageInterface[] $packages
* @return array<int, array{0: PackageInterface, 1: string}> * @return array<int, array{0: PackageInterface, 1: string}>
*/ */
public function buildPackageMap(InstallationManager $installationManager, PackageInterface $rootPackage, array $packages) public function buildPackageMap(InstallationManager $installationManager, PackageInterface $rootPackage, array $packages)
@ -481,6 +505,7 @@ EOF;
} }
/** /**
* @return void
* @throws \InvalidArgumentException Throws an exception, if the package has illegal settings. * @throws \InvalidArgumentException Throws an exception, if the package has illegal settings.
*/ */
protected function validatePackage(PackageInterface $package) protected function validatePackage(PackageInterface $package)
@ -503,12 +528,17 @@ EOF;
/** /**
* Compiles an ordered list of namespace => path mappings * Compiles an ordered list of namespace => path mappings
* *
* @param array $packageMap array of array(package, installDir-relative-to-composer.json) * @param array<int, array{0: PackageInterface, 1: string}> $packageMap array of array(package, installDir-relative-to-composer.json)
* @param RootPackageInterface $rootPackage root package instance * @param RootPackageInterface $rootPackage root package instance
* @param bool|string[] $filteredDevPackages If an array, the list of packages that must be removed. If bool, whether to filter out require-dev packages * @param bool|string[] $filteredDevPackages If an array, the list of packages that must be removed. If bool, whether to filter out require-dev packages
* @return array array('psr-0' => array('Ns\\Foo' => array('installDir'))) * @return array
* * @phpstan-return array{
* @phpstan-param array<int, array{0: PackageInterface, 1: string}> $packageMap * 'psr-0': array<int, string>|array<string, array<string>>|array<string, string>,
* 'psr-4': array<int, string>|array<string, array<string>>|array<string, string>,
* 'classmap': array<int, string>|array<string, array<string>>|array<string, string>,
* 'files': array<int, string>|array<string, array<string>>|array<string, string>,
* 'exclude-from-classmap': array<int, string>|array<string, array<string>>|array<string, string>,
* }
*/ */
public function parseAutoloads(array $packageMap, PackageInterface $rootPackage, $filteredDevPackages = false) public function parseAutoloads(array $packageMap, PackageInterface $rootPackage, $filteredDevPackages = false)
{ {
@ -543,9 +573,10 @@ EOF;
} }
/** /**
* Registers an autoloader based on an autoload map returned by parseAutoloads * Registers an autoloader based on an autoload-map returned by parseAutoloads
* *
* @param array $autoloads see parseAutoloads return value * @param array<string, array> $autoloads see parseAutoloads return value
* @param ?string $vendorDir
* @return ClassLoader * @return ClassLoader
*/ */
public function createLoader(array $autoloads, $vendorDir = null) public function createLoader(array $autoloads, $vendorDir = null)
@ -584,13 +615,12 @@ EOF;
} }
/** /**
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap
* @param string $basePath * @param string $basePath
* @param string $vendorPath * @param string $vendorPath
* @param string $vendorPathCode * @param string $vendorPathCode
* @param string $appBaseDirCode * @param string $appBaseDirCode
* @return ?string * @return ?string
*
* @phpstan-param array<int, array{0: PackageInterface, 1: string}> $packageMap
*/ */
protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode) protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
{ {
@ -703,11 +733,11 @@ EOF;
} }
/** /**
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap
* @param string[] $ignorePlatformReqs
* @param bool $checkPlatform * @param bool $checkPlatform
* @param string[] $devPackageNames * @param string[] $devPackageNames
* @return ?string * @return ?string
*
* @phpstan-param array<int, array{0: PackageInterface, 1: string}> $packageMap
*/ */
protected function getPlatformCheck(array $packageMap, array $ignorePlatformReqs, $checkPlatform, array $devPackageNames) protected function getPlatformCheck(array $packageMap, array $ignorePlatformReqs, $checkPlatform, array $devPackageNames)
{ {
@ -889,6 +919,17 @@ AUTOLOAD;
} }
/** /**
* @param bool $useClassMap
* @param bool $useIncludePath
* @param ?string $targetDirLoader
* @param bool $useIncludeFiles
* @param string $vendorPathCode unused in this method
* @param string $appBaseDirCode unused in this method
* @param string $suffix
* @param bool $useGlobalIncludePath
* @param string $prependAutoloader 'true'|'false'
* @param string $staticPhpVersion
* @param bool $checkPlatform
* @return string * @return string
*/ */
protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion, $checkPlatform) protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion, $checkPlatform)
@ -1067,6 +1108,11 @@ FOOTER;
} }
/** /**
* @param string $suffix
* @param string $targetDir
* @param string $vendorPath input for findShortestPathCode
* @param string $basePath input for findShortestPathCode
* @param string $staticPhpVersion
* @return string * @return string
*/ */
protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion) protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
@ -1165,6 +1211,8 @@ INITIALIZER;
} }
/** /**
* @param array<int, array{0: PackageInterface, 1: string}> $packageMap
* @param string $type one of: 'psr-0'|'psr-4'|'classmap'|'files'
* @return array<int, string>|array<string, array<string>>|array<string, string> * @return array<int, string>|array<string, array<string>>|array<string, string>
*/ */
protected function parseAutoloadsType(array $packageMap, $type, RootPackageInterface $rootPackage) protected function parseAutoloadsType(array $packageMap, $type, RootPackageInterface $rootPackage)
@ -1261,7 +1309,7 @@ INITIALIZER;
/** /**
* Filters out dev-dependencies * Filters out dev-dependencies
* *
* @param array $packageMap * @param array<int, array{0: PackageInterface, 1: string}> $packageMap
* @param RootPackageInterface $rootPackage * @param RootPackageInterface $rootPackage
* @return array<int, array{0: PackageInterface, 1: string}> * @return array<int, array{0: PackageInterface, 1: string}>
* *
@ -1318,10 +1366,8 @@ INITIALIZER;
* *
* Packages of equal weight retain the original order * Packages of equal weight retain the original order
* *
* @param array $packageMap * @param array<int, array{0: PackageInterface, 1: string}> $packageMap
* @return array<int, array{0: PackageInterface, 1: string}> * @return array<int, array{0: PackageInterface, 1: string}>
*
* @phpstan-param array<int, array{0: PackageInterface, 1: string}> $packageMap
*/ */
protected function sortPackageMap(array $packageMap) protected function sortPackageMap(array $packageMap)
{ {

View File

@ -35,6 +35,7 @@ class ClassMapGenerator
* *
* @param \Traversable<string>|array<string> $dirs Directories or a single path to search in * @param \Traversable<string>|array<string> $dirs Directories or a single path to search in
* @param string $file The name of the class map file * @param string $file The name of the class map file
* @return void
*/ */
public static function dump($dirs, $file) public static function dump($dirs, $file)
{ {
@ -50,16 +51,14 @@ class ClassMapGenerator
/** /**
* Iterate over all files in the given directory searching for classes * Iterate over all files in the given directory searching for classes
* *
* @param \Traversable|string|array<string> $path The path to search in or an iterator * @param \Traversable<\SplFileInfo>|string|array<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 string $excluded Regex that matches file paths to be excluded from the classmap
* @param ?IOInterface $io IO object * @param ?IOInterface $io IO object
* @param ?string $namespace Optional namespace prefix to filter by * @param ?string $namespace Optional namespace prefix to filter by
* @param ?string $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules * @param ?string $autoloadType psr-0|psr-4 Optional autoload standard to use mapping rules
* * @param array<string, true> $scannedFiles
* @return array<class-string, string> A class map array
* @throws \RuntimeException When the path is neither an existing file nor directory * @throws \RuntimeException When the path is neither an existing file nor directory
* @return array A class map array
*
* @phpstan-param \Traversable<\SplFileInfo>|string|array<string> $path
*/ */
public static function createMap($path, $excluded = null, IOInterface $io = null, $namespace = null, $autoloadType = null, &$scannedFiles = array()) public static function createMap($path, $excluded = null, IOInterface $io = null, $namespace = null, $autoloadType = null, &$scannedFiles = array())
{ {
@ -149,13 +148,13 @@ class ClassMapGenerator
/** /**
* Remove classes which could not have been loaded by namespace autoloaders * Remove classes which could not have been loaded by namespace autoloaders
* *
* @param array $classes found classes in given file * @param array<int, class-string> $classes found classes in given file
* @param string $filePath current file * @param string $filePath current file
* @param string $baseNamespace prefix of given autoload mapping * @param string $baseNamespace prefix of given autoload mapping
* @param string $namespaceType psr-0|psr-4 * @param string $namespaceType psr-0|psr-4
* @param string $basePath root directory of given autoload mapping * @param string $basePath root directory of given autoload mapping
* @param ?IOInterface $io IO object * @param ?IOInterface $io IO object
* @return array valid classes * @return array<int, class-string> valid classes
*/ */
private static function filterByNamespace($classes, $filePath, $baseNamespace, $namespaceType, $basePath, $io) private static function filterByNamespace($classes, $filePath, $baseNamespace, $namespaceType, $basePath, $io)
{ {
@ -212,7 +211,7 @@ class ClassMapGenerator
* *
* @param string $path The file to check * @param string $path The file to check
* @throws \RuntimeException * @throws \RuntimeException
* @return array The found classes * @return array<int, class-string> The found classes
*/ */
private static function findClasses($path) private static function findClasses($path)
{ {
@ -285,6 +284,9 @@ class ClassMapGenerator
return $classes; return $classes;
} }
/**
* @return string
*/
private static function getExtraTypes() private static function getExtraTypes()
{ {
static $extraTypes = null; static $extraTypes = null;

View File

@ -10,6 +10,7 @@ class PhpFileCleaner
{ {
/** @var array<array{name: string, length: int, pattern: string}> */ /** @var array<array{name: string, length: int, pattern: string}> */
private static $typeConfig; private static $typeConfig;
/** @var string */ /** @var string */
private static $restPattern; private static $restPattern;
@ -34,6 +35,10 @@ class PhpFileCleaner
/** @var int */ /** @var int */
private $index = 0; private $index = 0;
/**
* @param string[] $types
* @return void
*/
public static function setTypeConfig($types) public static function setTypeConfig($types)
{ {
foreach ($types as $type) { foreach ($types as $type) {
@ -47,6 +52,10 @@ class PhpFileCleaner
self::$restPattern = '{[^?"\'</'.implode('', array_keys(self::$typeConfig)).']+}A'; self::$restPattern = '{[^?"\'</'.implode('', array_keys(self::$typeConfig)).']+}A';
} }
/**
* @param string $contents
* @param int $maxMatches
*/
public function __construct($contents, $maxMatches) public function __construct($contents, $maxMatches)
{ {
$this->contents = $contents; $this->contents = $contents;
@ -126,6 +135,9 @@ class PhpFileCleaner
return $clean; return $clean;
} }
/**
* @return void
*/
private function skipToPhp() private function skipToPhp()
{ {
while ($this->index < $this->len) { while ($this->index < $this->len) {
@ -138,6 +150,10 @@ class PhpFileCleaner
} }
} }
/**
* @param string $delimiter
* @return void
*/
private function skipString($delimiter) private function skipString($delimiter)
{ {
$this->index += 1; $this->index += 1;
@ -154,6 +170,9 @@ class PhpFileCleaner
} }
} }
/**
* @return void
*/
private function skipComment() private function skipComment()
{ {
$this->index += 2; $this->index += 2;
@ -167,6 +186,9 @@ class PhpFileCleaner
} }
} }
/**
* @return void
*/
private function skipToNewline() private function skipToNewline()
{ {
while ($this->index < $this->len) { while ($this->index < $this->len) {
@ -177,6 +199,10 @@ class PhpFileCleaner
} }
} }
/**
* @param string $delimiter
* @return void
*/
private function skipHeredoc($delimiter) private function skipHeredoc($delimiter)
{ {
$firstDelimiterChar = $delimiter[0]; $firstDelimiterChar = $delimiter[0];
@ -216,6 +242,7 @@ class PhpFileCleaner
} }
/** /**
* @param string $char
* @return bool * @return bool
*/ */
private function peek($char) private function peek($char)
@ -224,6 +251,8 @@ class PhpFileCleaner
} }
/** /**
* @param string $regex
* @param ?array<int, string> $match
* @return bool * @return bool
*/ */
private function match($regex, array &$match = null) private function match($regex, array &$match = null)