mirror of
https://github.com/rectorphp/rector.git
synced 2024-07-01 07:03:32 +00:00
add PHPStanStaticTypeMapperChecker packages
This commit is contained in:
parent
e1e45ff02e
commit
1678950146
15
.github/workflows/code_checks.yml
vendored
15
.github/workflows/code_checks.yml
vendored
|
@ -100,8 +100,23 @@ jobs:
|
|||
- run: composer install --no-progress
|
||||
- run: |
|
||||
php ci/check_services_in_yaml_configs.php
|
||||
- run: |
|
||||
php ci/run_all_sets.php
|
||||
|
||||
phpstan_types_checks:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
-
|
||||
uses: shivammathur/setup-php@v1
|
||||
with:
|
||||
php-version: 7.2
|
||||
coverage: none # disable xdebug, pcov
|
||||
- run: composer install --no-progress
|
||||
- run: |
|
||||
bin/rector sync-types
|
||||
- run: |
|
||||
bin/rector check-static-type-mappers
|
||||
|
||||
fatal_scan:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
@ -173,6 +173,7 @@
|
|||
"Rector\\Phalcon\\Tests\\": "packages/Phalcon/tests",
|
||||
"Rector\\DoctrineGedmoToKnplabs\\Tests\\": "packages/DoctrineGedmoToKnplabs/tests",
|
||||
"Rector\\MinimalScope\\Tests\\": "packages/MinimalScope/tests",
|
||||
"Rector\\Utils\\PHPStanStaticTypeMapperChecker\\": "utils/PHPStanStaticTypeMapperChecker/src",
|
||||
"Rector\\Polyfill\\Tests\\": "packages/Polyfill/tests"
|
||||
},
|
||||
"classmap": [
|
||||
|
|
|
@ -2,7 +2,7 @@ imports:
|
|||
- { resource: '../packages/**/config/config.yaml' }
|
||||
- { resource: 'services.yaml' }
|
||||
# only in local repository
|
||||
- { resource: '../utils/**/config/config.yaml', ignore_errors: true }
|
||||
- { resource: '../utils/**/config/config.yaml' }
|
||||
|
||||
parameters:
|
||||
# processed paths
|
||||
|
|
8
utils/PHPStanStaticTypeMapperChecker/config/config.yaml
Normal file
8
utils/PHPStanStaticTypeMapperChecker/config/config.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
services:
|
||||
_defaults:
|
||||
public: true
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Rector\Utils\PHPStanStaticTypeMapperChecker\:
|
||||
resource: '../src'
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Utils\PHPStanStaticTypeMapperChecker\Command;
|
||||
|
||||
use PHPStan\Type\NonexistentParentClassType;
|
||||
use Rector\Console\Command\AbstractCommand;
|
||||
use Rector\Console\Shell;
|
||||
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
|
||||
use Rector\Utils\PHPStanStaticTypeMapperChecker\Finder\PHPStanTypeClassFinder;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symplify\PackageBuilder\Console\Command\CommandNaming;
|
||||
|
||||
final class CheckStaticTypeMappersCommand extends AbstractCommand
|
||||
{
|
||||
/**
|
||||
* @var SymfonyStyle
|
||||
*/
|
||||
private $symfonyStyle;
|
||||
|
||||
/**
|
||||
* @var TypeMapperInterface[]
|
||||
*/
|
||||
private $typeMappers = [];
|
||||
|
||||
/**
|
||||
* @var PHPStanTypeClassFinder
|
||||
*/
|
||||
private $phpStanTypeClassFinder;
|
||||
|
||||
/**
|
||||
* @param TypeMapperInterface[] $typeMappers
|
||||
*/
|
||||
public function __construct(
|
||||
array $typeMappers,
|
||||
SymfonyStyle $symfonyStyle,
|
||||
PHPStanTypeClassFinder $phpStanTypeClassFinder
|
||||
) {
|
||||
$this->typeMappers = $typeMappers;
|
||||
$this->symfonyStyle = $symfonyStyle;
|
||||
$this->phpStanTypeClassFinder = $phpStanTypeClassFinder;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName(CommandNaming::classToName(self::class));
|
||||
$this->setDescription('[Dev] check PHPStan types to TypeMappers');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$missingNodeClasses = $this->getMissingNodeClasses();
|
||||
if ($missingNodeClasses === []) {
|
||||
$this->symfonyStyle->success('All PHPStan Types are covered by TypeMapper');
|
||||
|
||||
return Shell::CODE_SUCCESS;
|
||||
}
|
||||
|
||||
$this->symfonyStyle->error('Some classes are missing nodes');
|
||||
$this->symfonyStyle->listing($missingNodeClasses);
|
||||
|
||||
die;
|
||||
|
||||
return Shell::CODE_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getMissingNodeClasses(): array
|
||||
{
|
||||
$phpStanTypeClasses = $this->phpStanTypeClassFinder->find();
|
||||
$supportedPHPStanTypeClasses = $this->getSupportedTypeClasses();
|
||||
|
||||
$unsupportedTypeClasses = [];
|
||||
foreach ($phpStanTypeClasses as $phpStanTypeClass) {
|
||||
foreach ($supportedPHPStanTypeClasses as $supportedPHPStanTypeClass) {
|
||||
if (is_a($phpStanTypeClass, $supportedPHPStanTypeClass, true)) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
$unsupportedTypeClasses[] = $phpStanTypeClass;
|
||||
}
|
||||
|
||||
$typesToRemove = [NonexistentParentClassType::class];
|
||||
|
||||
return array_diff($unsupportedTypeClasses, $typesToRemove);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getSupportedTypeClasses(): array
|
||||
{
|
||||
$supportedPHPStanTypeClasses = [];
|
||||
foreach ($this->typeMappers as $typeMappers) {
|
||||
$supportedPHPStanTypeClasses[] = $typeMappers->getNodeClass();
|
||||
}
|
||||
|
||||
return $supportedPHPStanTypeClasses;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Utils\PHPStanStaticTypeMapperChecker\Finder;
|
||||
|
||||
use Nette\Loaders\RobotLoader;
|
||||
use Nette\Utils\Strings;
|
||||
|
||||
final class PHPStanTypeClassFinder
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function find(): array
|
||||
{
|
||||
$robotLoader = new RobotLoader();
|
||||
$robotLoader->addDirectory($this->getPHPStanPharSrcTypeDirectoryPath());
|
||||
|
||||
$robotLoader->setTempDirectory(sys_get_temp_dir() . '/_phpstan_types');
|
||||
$robotLoader->acceptFiles = ['*Type.php'];
|
||||
$robotLoader->rebuild();
|
||||
|
||||
$classLikesToFilePaths = $robotLoader->getIndexedClasses();
|
||||
$classLikes = array_keys($classLikesToFilePaths);
|
||||
|
||||
return $this->filterClassesOnly($classLikes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $classLikes
|
||||
* @return string[]
|
||||
*/
|
||||
private function filterClassesOnly(array $classLikes): array
|
||||
{
|
||||
$classes = [];
|
||||
foreach ($classLikes as $classLike) {
|
||||
if (! class_exists($classLike)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Strings::match($classLike, '#\\\\Accessory\\\\#')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classes[] = $classLike;
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/dg/nette-robot-loader/blob/593c0e40e511c0b0700610a6a3964a210219139f/tests/Loaders/RobotLoader.phar.phpt#L33
|
||||
*/
|
||||
private function getPHPStanPharSrcTypeDirectoryPath(): string
|
||||
{
|
||||
$phpstanPharRealpath = realpath(__DIR__ . '/../../../../vendor/phpstan/phpstan/phpstan.phar');
|
||||
|
||||
return 'phar://' . $phpstanPharRealpath . '/src/Type';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user