-
-
Notifications
You must be signed in to change notification settings - Fork 672
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
265 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
packages/PHPStanStaticTypeMapper/src/TypeMapper/SelfObjectTypeMapper.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\PHPStanStaticTypeMapper\TypeMapper; | ||
|
||
use PhpParser\Node; | ||
use PhpParser\Node\Identifier; | ||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; | ||
use PHPStan\PhpDocParser\Ast\Type\TypeNode; | ||
use PHPStan\Type\Type; | ||
use PHPStan\Type\VerbosityLevel; | ||
use Rector\PHPStan\Type\SelfObjectType; | ||
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; | ||
|
||
final class SelfObjectTypeMapper implements TypeMapperInterface | ||
{ | ||
public function getNodeClass(): string | ||
{ | ||
return SelfObjectType::class; | ||
} | ||
|
||
/** | ||
* @param SelfObjectType $type | ||
*/ | ||
public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode | ||
{ | ||
return new IdentifierTypeNode('self'); | ||
} | ||
|
||
/** | ||
* @param SelfObjectType $type | ||
*/ | ||
public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node | ||
{ | ||
return new Identifier('self'); | ||
} | ||
|
||
/** | ||
* @param SelfObjectType $type | ||
*/ | ||
public function mapToDocString(Type $type, ?Type $parentType = null): string | ||
{ | ||
return $type->describe(VerbosityLevel::typeOnly()); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
packages/PHPStanStaticTypeMapper/src/TypeMapper/StaticTypeMapper.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\PHPStanStaticTypeMapper\TypeMapper; | ||
|
||
use PhpParser\Node; | ||
use PhpParser\Node\Identifier; | ||
use PHPStan\PhpDocParser\Ast\Type\TypeNode; | ||
use PHPStan\Type\StaticType; | ||
use PHPStan\Type\ThisType; | ||
use PHPStan\Type\Type; | ||
use PHPStan\Type\VerbosityLevel; | ||
use Rector\Exception\NotImplementedException; | ||
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface; | ||
|
||
final class StaticTypeMapper implements TypeMapperInterface | ||
{ | ||
public function getNodeClass(): string | ||
{ | ||
return StaticType::class; | ||
} | ||
|
||
/** | ||
* @param StaticType $type | ||
*/ | ||
public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
/** | ||
* @param StaticType $type | ||
*/ | ||
public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node | ||
{ | ||
if ($type instanceof ThisType) { | ||
return new Identifier('self'); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
/** | ||
* @param StaticType $type | ||
*/ | ||
public function mapToDocString(Type $type, ?Type $parentType = null): string | ||
{ | ||
return $type->describe(VerbosityLevel::typeOnly()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
services: | ||
_defaults: | ||
public: true | ||
autowire: true | ||
autoconfigure: true | ||
|
||
Rector\Utils\PHPStanStaticTypeMapperChecker\: | ||
resource: '../src' |
90 changes: 90 additions & 0 deletions
90
utils/PHPStanStaticTypeMapperChecker/src/Command/CheckStaticTypeMappersCommand.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Rector\Utils\PHPStanStaticTypeMapperChecker\Command; | ||
|
||
use PHPStan\Type\BenevolentUnionType; | ||
use PHPStan\Type\ErrorType; | ||
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(); | ||
|
||
dump($missingNodeClasses); | ||
die; | ||
|
||
if ($missingNodeClasses === []) { | ||
$this->symfonyStyle->success( | ||
'All PHPStan Doc Parser nodes are covered with attribute aware mirror in Rector' | ||
); | ||
|
||
return Shell::CODE_SUCCESS; | ||
} | ||
|
||
return Shell::CODE_ERROR; | ||
} | ||
|
||
/** | ||
* @return string[] | ||
*/ | ||
private function getMissingNodeClasses(): array | ||
{ | ||
$phpStanTypeClasses = $this->phpStanTypeClassFinder->find(); | ||
|
||
$supportedPHPStanTypeClasses = []; | ||
foreach ($this->typeMappers as $typeMappers) { | ||
$supportedPHPStanTypeClasses[] = $typeMappers->getNodeClass(); | ||
} | ||
|
||
$typesToRemove = [ErrorType::class, BenevolentUnionType::class]; | ||
|
||
return array_diff($phpStanTypeClasses, $supportedPHPStanTypeClasses, $typesToRemove); | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
utils/PHPStanStaticTypeMapperChecker/src/Finder/PHPStanTypeClassFinder.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'; | ||
} | ||
} |