mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-29 06:03:30 +00:00
Add PhpVersionProvider
This commit is contained in:
parent
1f7a643817
commit
b401be37e5
|
@ -93,6 +93,13 @@ parameters:
|
|||
- 'Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector'
|
||||
```
|
||||
|
||||
By default Rector uses language features of your PHP version. If you you want to use different PHP version than your system, put it in config:
|
||||
|
||||
```yaml
|
||||
parameters:
|
||||
php_version_features: '7.2' # your version 7.3
|
||||
```
|
||||
|
||||
## Running Rector
|
||||
|
||||
### A. Prepared Sets
|
||||
|
|
|
@ -8,3 +8,4 @@ parameters:
|
|||
exclude_paths: []
|
||||
exclude_rectors: []
|
||||
autoload_paths: []
|
||||
php_version_features: ~ # what PHP version should be used for features, local PHP version is used by default
|
||||
|
|
4
ecs.yml
4
ecs.yml
|
@ -84,10 +84,6 @@ parameters:
|
|||
- 'packages/NetteToSymfony/src/Event/EventInfosFactory.php'
|
||||
|
||||
Symplify\CodingStandard\Sniffs\CleanCode\ForbiddenStaticFunctionSniff:
|
||||
# required by Composer interface
|
||||
- 'src/Php/TypeAnalyzer.php'
|
||||
# exclusive static config for type support
|
||||
- 'src/Php/PhpTypeSupport.php'
|
||||
- 'src/Util/*.php'
|
||||
|
||||
Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer:
|
||||
|
|
|
@ -68,6 +68,10 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('7.0')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->returnNode = null;
|
||||
|
||||
if ($node->keyVar === null) {
|
||||
|
|
|
@ -83,6 +83,10 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('7.0')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->reset();
|
||||
|
||||
$currentNode = $node;
|
||||
|
|
|
@ -11,6 +11,7 @@ use Rector\Exception\ShouldNotHappenException;
|
|||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\Node\NodeToStringTypeResolver;
|
||||
use Rector\NodeTypeResolver\Php\VarTypeInfo;
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
use Rector\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\PhpParser\Node\Resolver\NameResolver;
|
||||
|
||||
|
@ -36,16 +37,23 @@ final class ComplexNodeTypeResolver
|
|||
*/
|
||||
private $nodeTypeAnalyzer;
|
||||
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
private $typeAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
NodeToStringTypeResolver $nodeToStringTypeResolver,
|
||||
NameResolver $nameResolver,
|
||||
BetterNodeFinder $betterNodeFinder,
|
||||
NodeTypeAnalyzer $nodeTypeAnalyzer
|
||||
NodeTypeAnalyzer $nodeTypeAnalyzer,
|
||||
TypeAnalyzer $typeAnalyzer
|
||||
) {
|
||||
$this->nodeToStringTypeResolver = $nodeToStringTypeResolver;
|
||||
$this->nameResolver = $nameResolver;
|
||||
$this->betterNodeFinder = $betterNodeFinder;
|
||||
$this->nodeTypeAnalyzer = $nodeTypeAnalyzer;
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,6 +99,6 @@ final class ComplexNodeTypeResolver
|
|||
|
||||
$types = array_filter($types);
|
||||
|
||||
return new VarTypeInfo($types, $types, true);
|
||||
return new VarTypeInfo($types, $this->typeAnalyzer, $types, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use PhpParser\Node\Identifier;
|
|||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\NullableType;
|
||||
use Rector\Php\PhpTypeSupport;
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
use Traversable;
|
||||
|
||||
|
@ -33,6 +32,11 @@ abstract class AbstractTypeInfo
|
|||
*/
|
||||
protected $fqnTypes = [];
|
||||
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
protected $typeAnalyzer;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
|
@ -47,8 +51,13 @@ abstract class AbstractTypeInfo
|
|||
* @param string[] $types
|
||||
* @param string[] $fqnTypes
|
||||
*/
|
||||
public function __construct(array $types, array $fqnTypes = [], bool $allowTypedArrays = false)
|
||||
{
|
||||
public function __construct(
|
||||
array $types,
|
||||
TypeAnalyzer $typeAnalyzer,
|
||||
array $fqnTypes = [],
|
||||
bool $allowTypedArrays = false
|
||||
) {
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
$this->types = $this->analyzeAndNormalizeTypes($types, $allowTypedArrays);
|
||||
|
||||
// fallback
|
||||
|
@ -89,7 +98,7 @@ abstract class AbstractTypeInfo
|
|||
|
||||
$type = $types[0];
|
||||
|
||||
if (TypeAnalyzer::isPhpReservedType($type)) {
|
||||
if ($this->typeAnalyzer->isPhpReservedType($type)) {
|
||||
if ($this->isNullable) {
|
||||
return new NullableType($type);
|
||||
}
|
||||
|
@ -175,13 +184,13 @@ abstract class AbstractTypeInfo
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($type === 'object' && PhpTypeSupport::isTypeSupported('object') === false) {
|
||||
if ($type === 'object' && $this->typeAnalyzer->isPhpSupported('object') === false) {
|
||||
$this->removedTypes[] = $type;
|
||||
unset($types[$i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$types[$i] = TypeAnalyzer::normalizeType($type, $allowTypedArrays);
|
||||
$types[$i] = $this->typeAnalyzer->normalizeType($type, $allowTypedArrays);
|
||||
}
|
||||
|
||||
// remove undesired types
|
||||
|
@ -220,7 +229,7 @@ abstract class AbstractTypeInfo
|
|||
|
||||
private function normalizeCasing(string $type): string
|
||||
{
|
||||
if (TypeAnalyzer::isPhpReservedType($type)) {
|
||||
if ($this->typeAnalyzer->isPhpReservedType($type)) {
|
||||
return strtolower($type);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Rector\NodeTypeResolver\Php;
|
||||
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
|
||||
final class ParamTypeInfo extends AbstractTypeInfo
|
||||
{
|
||||
/**
|
||||
|
@ -18,11 +20,11 @@ final class ParamTypeInfo extends AbstractTypeInfo
|
|||
* @param string[] $types
|
||||
* @param string[] $fqnTypes
|
||||
*/
|
||||
public function __construct(string $name, array $types, array $fqnTypes = [])
|
||||
public function __construct(string $name, TypeAnalyzer $typeAnalyzer, array $types, array $fqnTypes = [])
|
||||
{
|
||||
$this->name = $this->normalizeName($name);
|
||||
|
||||
parent::__construct($types, $fqnTypes);
|
||||
parent::__construct($types, $typeAnalyzer, $fqnTypes);
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace Rector\NodeTypeResolver\Php;
|
||||
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
|
||||
final class VarTypeInfo extends AbstractTypeInfo
|
||||
{
|
||||
/**
|
||||
|
@ -30,7 +28,7 @@ final class VarTypeInfo extends AbstractTypeInfo
|
|||
return true;
|
||||
}
|
||||
|
||||
return TypeAnalyzer::isPhpReservedType($type);
|
||||
return $this->typeAnalyzer->isPhpSupported($type);
|
||||
}
|
||||
|
||||
public function getType(): ?string
|
||||
|
|
|
@ -14,6 +14,7 @@ use Rector\NodeTypeResolver\Node\CurrentNodeProvider;
|
|||
use Rector\NodeTypeResolver\Php\ParamTypeInfo;
|
||||
use Rector\NodeTypeResolver\Php\ReturnTypeInfo;
|
||||
use Rector\NodeTypeResolver\Php\VarTypeInfo;
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
use Symplify\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwareParamTagValueNode;
|
||||
use Symplify\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwarePhpDocTagNode;
|
||||
use Symplify\BetterPhpDocParser\Attributes\Ast\PhpDoc\AttributeAwareVarTagValueNode;
|
||||
|
@ -46,16 +47,23 @@ final class DocBlockAnalyzer
|
|||
*/
|
||||
private $currentNodeProvider;
|
||||
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
private $typeAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
PhpDocInfoFactory $phpDocInfoFactory,
|
||||
PhpDocInfoPrinter $phpDocInfoPrinter,
|
||||
PhpDocModifier $phpDocModifier,
|
||||
CurrentNodeProvider $currentNodeProvider
|
||||
CurrentNodeProvider $currentNodeProvider,
|
||||
TypeAnalyzer $typeAnalyzer
|
||||
) {
|
||||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
$this->phpDocInfoPrinter = $phpDocInfoPrinter;
|
||||
$this->phpDocModifier = $phpDocModifier;
|
||||
$this->currentNodeProvider = $currentNodeProvider;
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
}
|
||||
|
||||
public function hasTag(Node $node, string $name): bool
|
||||
|
@ -152,7 +160,7 @@ final class DocBlockAnalyzer
|
|||
|
||||
$fqnTypes = $phpDocInfo->getReturnTypes();
|
||||
|
||||
return new ReturnTypeInfo($types, $fqnTypes);
|
||||
return new ReturnTypeInfo($types, $this->typeAnalyzer, $fqnTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -181,6 +189,7 @@ final class DocBlockAnalyzer
|
|||
|
||||
$paramTypeInfo = new ParamTypeInfo(
|
||||
$paramTagValueNode->parameterName,
|
||||
$this->typeAnalyzer,
|
||||
$paramTagValueNode->getAttribute(Attribute::TYPE_AS_ARRAY),
|
||||
$fqnParamTagValueNode->getAttribute(Attribute::TYPE_AS_ARRAY)
|
||||
);
|
||||
|
@ -254,7 +263,7 @@ final class DocBlockAnalyzer
|
|||
|
||||
$fqnTypes = $phpDocInfo->getVarTypes();
|
||||
|
||||
return new VarTypeInfo($types, $fqnTypes);
|
||||
return new VarTypeInfo($types, $this->typeAnalyzer, $fqnTypes);
|
||||
}
|
||||
|
||||
private function updateNodeWithPhpDocInfo(Node $node, PhpDocInfo $phpDocInfo): void
|
||||
|
|
|
@ -35,6 +35,16 @@ final class SpecificAssertInternalTypeRector extends AbstractPHPUnitRector
|
|||
'iterable' => ['assertIsIterable', 'assertIsNotIterable'],
|
||||
];
|
||||
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
private $typeAnalyzer;
|
||||
|
||||
public function __construct(TypeAnalyzer $typeAnalyzer)
|
||||
{
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition(
|
||||
|
@ -95,7 +105,7 @@ CODE_SAMPLE
|
|||
return null;
|
||||
}
|
||||
|
||||
$type = TypeAnalyzer::normalizeType($typeNode->value);
|
||||
$type = $this->typeAnalyzer->normalizeType($typeNode->value);
|
||||
if (! isset($this->typeToMethod[$type])) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,10 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('7.4')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $node->expr instanceof Coalesce) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -81,6 +81,10 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('5.3')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isNames($node, ['reset', 'end'])) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ use Rector\NodeTypeResolver\Application\ClassLikeNodeCollector;
|
|||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\Php\AbstractTypeInfo;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockAnalyzer;
|
||||
use Rector\Php\PhpTypeSupport;
|
||||
use Rector\PhpParser\Node\Maintainer\FunctionLikeMaintainer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
||||
|
@ -53,19 +52,11 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
|
|||
public function __construct(
|
||||
DocBlockAnalyzer $docBlockAnalyzer,
|
||||
ClassLikeNodeCollector $classLikeNodeCollector,
|
||||
FunctionLikeMaintainer $functionLikeMaintainer,
|
||||
bool $enableObjectType = false
|
||||
FunctionLikeMaintainer $functionLikeMaintainer
|
||||
) {
|
||||
$this->docBlockAnalyzer = $docBlockAnalyzer;
|
||||
$this->classLikeNodeCollector = $classLikeNodeCollector;
|
||||
$this->functionLikeMaintainer = $functionLikeMaintainer;
|
||||
|
||||
if ($enableObjectType) {
|
||||
PhpTypeSupport::enableType('object');
|
||||
} else {
|
||||
// needed for multiple calls with different config
|
||||
PhpTypeSupport::disableType('object');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -88,6 +88,10 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('7.0')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (empty($node->params)) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,10 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('7.0')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// skip excluded methods
|
||||
if ($node instanceof ClassMethod && $this->isNames($node, $this->excludeClassMethodNames)) {
|
||||
return null;
|
||||
|
|
|
@ -13,7 +13,6 @@ use PhpParser\Node\Stmt\Property;
|
|||
use Rector\NodeTypeResolver\ComplexNodeTypeResolver;
|
||||
use Rector\NodeTypeResolver\Php\VarTypeInfo;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockAnalyzer;
|
||||
use Rector\Php\PhpTypeSupport;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
@ -45,12 +44,11 @@ final class TypedPropertyRector extends AbstractRector
|
|||
*/
|
||||
private $complexNodeTypeResolver;
|
||||
|
||||
public function __construct(DocBlockAnalyzer $docBlockAnalyzer, ComplexNodeTypeResolver $complexNodeTypeResolver)
|
||||
{
|
||||
public function __construct(
|
||||
DocBlockAnalyzer $docBlockAnalyzer,
|
||||
ComplexNodeTypeResolver $complexNodeTypeResolver
|
||||
) {
|
||||
$this->docBlockAnalyzer = $docBlockAnalyzer;
|
||||
|
||||
// PHP 7.4 already knows "object"
|
||||
PhpTypeSupport::enableType('object');
|
||||
$this->complexNodeTypeResolver = $complexNodeTypeResolver;
|
||||
}
|
||||
|
||||
|
@ -94,6 +92,10 @@ CODE_SAMPLE
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('7.4')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($node->type !== null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,10 @@ final class TernaryToNullCoalescingRector extends AbstractRector
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if (! $this->isAtLeastPhpVersion('7.0')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($node->cond instanceof Isset_) {
|
||||
return $this->processTernaryWithIsset($node);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace Rector\Php\Tests\Rector\ClassMethod\ReturnTypeDeclarationRector\Fixtur
|
|||
|
||||
class A {
|
||||
/** @return object */
|
||||
public function getObject($value) {
|
||||
public function getObject($value): object {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace Rector\Php\Tests\Rector\ClassMethod\ReturnTypeDeclarationRector\Fixtur
|
|||
/** @return iterable */ function my_foo2($value): iterable {
|
||||
return $value;
|
||||
}
|
||||
/** @return object */ function my_foo3($value) {
|
||||
/** @return object */ function my_foo3($value): object {
|
||||
return $value;
|
||||
}
|
||||
/** @return int */ function my_foo4($value): int {
|
||||
|
|
|
@ -24,15 +24,21 @@ final class ShowCommand extends AbstractCommand
|
|||
*/
|
||||
private $rectors = [];
|
||||
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
private $typeAnalyzer;
|
||||
|
||||
/**
|
||||
* @param RectorInterface[] $rectors
|
||||
*/
|
||||
public function __construct(SymfonyStyle $symfonyStyle, array $rectors)
|
||||
public function __construct(SymfonyStyle $symfonyStyle, array $rectors, TypeAnalyzer $typeAnalyzer)
|
||||
{
|
||||
$this->symfonyStyle = $symfonyStyle;
|
||||
$this->rectors = $rectors;
|
||||
|
||||
parent::__construct();
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
|
@ -81,7 +87,7 @@ final class ShowCommand extends AbstractCommand
|
|||
$configuration = [];
|
||||
foreach ($constructorReflection->getParameters() as $reflectionParameter) {
|
||||
$parameterType = (string) $reflectionParameter->getType();
|
||||
if (! TypeAnalyzer::isPhpReservedType($parameterType)) {
|
||||
if (! $this->typeAnalyzer->isPhpReservedType($parameterType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php;
|
||||
|
||||
/**
|
||||
* Static service to work with type support:
|
||||
*
|
||||
* - PHP 7.2: object
|
||||
*/
|
||||
final class PhpTypeSupport
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private static $types = [];
|
||||
|
||||
public static function enableType(string $name): void
|
||||
{
|
||||
self::$types[] = $name;
|
||||
}
|
||||
|
||||
public static function isTypeSupported(string $name): bool
|
||||
{
|
||||
return in_array($name, self::$types, true);
|
||||
}
|
||||
|
||||
public static function disableType(string $name): void
|
||||
{
|
||||
self::$types = array_diff(self::$types, [$name]);
|
||||
}
|
||||
}
|
35
src/Php/PhpVersionProvider.php
Normal file
35
src/Php/PhpVersionProvider.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php;
|
||||
|
||||
final class PhpVersionProvider
|
||||
{
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $phpVersionFeatures;
|
||||
|
||||
public function __construct(?string $phpVersionFeatures)
|
||||
{
|
||||
$this->phpVersionFeatures = $phpVersionFeatures;
|
||||
}
|
||||
|
||||
public function provide(): string
|
||||
{
|
||||
// for tests
|
||||
if (defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__')) {
|
||||
return '7.5';
|
||||
}
|
||||
|
||||
if ($this->phpVersionFeatures) {
|
||||
return $this->phpVersionFeatures;
|
||||
}
|
||||
|
||||
return PHP_VERSION;
|
||||
}
|
||||
|
||||
public function isAtLeast(string $version): bool
|
||||
{
|
||||
return version_compare($this->provide(), $version) === 1;
|
||||
}
|
||||
}
|
|
@ -6,37 +6,47 @@ use Nette\Utils\Strings;
|
|||
|
||||
final class TypeAnalyzer
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $phpSupportedTypes = [
|
||||
'string',
|
||||
'bool',
|
||||
'int',
|
||||
'null',
|
||||
'array',
|
||||
'false',
|
||||
'true',
|
||||
'mixed',
|
||||
'iterable',
|
||||
'float',
|
||||
'self',
|
||||
'parent',
|
||||
'callable',
|
||||
'void',
|
||||
];
|
||||
|
||||
public function __construct(PhpVersionProvider $phpVersionProvider)
|
||||
{
|
||||
if ($phpVersionProvider->isAtLeast('7.2')) {
|
||||
$this->phpSupportedTypes[] = 'object';
|
||||
}
|
||||
}
|
||||
|
||||
public function isNullableType(string $type): bool
|
||||
{
|
||||
return Strings::startsWith($type, '?');
|
||||
}
|
||||
|
||||
public static function isPhpReservedType(string $type): bool
|
||||
public function isPhpReservedType(string $type): bool
|
||||
{
|
||||
return in_array(
|
||||
strtolower($type),
|
||||
[
|
||||
'string',
|
||||
'bool',
|
||||
'null',
|
||||
'false',
|
||||
'true',
|
||||
'mixed',
|
||||
'object',
|
||||
'iterable',
|
||||
'array',
|
||||
'float',
|
||||
'int',
|
||||
'self',
|
||||
'parent',
|
||||
'callable',
|
||||
'void',
|
||||
],
|
||||
true
|
||||
);
|
||||
$type = strtolower($type);
|
||||
$extraTypes = ['object'];
|
||||
|
||||
return in_array($type, array_merge($this->phpSupportedTypes, $extraTypes), true);
|
||||
}
|
||||
|
||||
public static function normalizeType(string $type, bool $allowTypedArrays = false): string
|
||||
public function normalizeType(string $type, bool $allowTypedArrays = false): string
|
||||
{
|
||||
// reduction needed for typehint
|
||||
if ($allowTypedArrays === false) {
|
||||
|
@ -45,26 +55,31 @@ final class TypeAnalyzer
|
|||
}
|
||||
}
|
||||
|
||||
if ($type === 'boolean') {
|
||||
if (strtolower($type) === 'boolean') {
|
||||
return 'bool';
|
||||
}
|
||||
|
||||
if (in_array($type, ['double', 'real'], true)) {
|
||||
if (in_array(strtolower($type), ['double', 'real'], true)) {
|
||||
return 'float';
|
||||
}
|
||||
|
||||
if ($type === 'integer') {
|
||||
if (strtolower($type) === 'integer') {
|
||||
return 'int';
|
||||
}
|
||||
|
||||
if ($type === 'callback') {
|
||||
if (strtolower($type) === 'callback') {
|
||||
return 'callable';
|
||||
}
|
||||
|
||||
if (Strings::match($type, '#array<(.*?)>#')) {
|
||||
if (Strings::match(strtolower($type), '#array<(.*?)>#')) {
|
||||
return 'array';
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
public function isPhpSupported(string $type): bool
|
||||
{
|
||||
return in_array($type, $this->phpSupportedTypes, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use PhpParser\Node\Stmt\Return_;
|
|||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\NodeTypeAnalyzer;
|
||||
use Rector\NodeTypeResolver\Php\ReturnTypeInfo;
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
use Rector\PhpParser\Node\BetterNodeFinder;
|
||||
|
||||
final class FunctionLikeMaintainer
|
||||
|
@ -24,10 +25,19 @@ final class FunctionLikeMaintainer
|
|||
*/
|
||||
private $nodeTypeAnalyzer;
|
||||
|
||||
public function __construct(BetterNodeFinder $betterNodeFinder, NodeTypeAnalyzer $nodeTypeAnalyzer)
|
||||
{
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
private $typeAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
BetterNodeFinder $betterNodeFinder,
|
||||
NodeTypeAnalyzer $nodeTypeAnalyzer,
|
||||
TypeAnalyzer $typeAnalyzer
|
||||
) {
|
||||
$this->betterNodeFinder = $betterNodeFinder;
|
||||
$this->nodeTypeAnalyzer = $nodeTypeAnalyzer;
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,12 +66,12 @@ final class FunctionLikeMaintainer
|
|||
}
|
||||
|
||||
if ($isVoid) {
|
||||
return new ReturnTypeInfo(['void']);
|
||||
return new ReturnTypeInfo(['void'], $this->typeAnalyzer);
|
||||
}
|
||||
|
||||
$types = array_filter($types);
|
||||
|
||||
return new ReturnTypeInfo($types);
|
||||
return new ReturnTypeInfo($types, $this->typeAnalyzer);
|
||||
}
|
||||
|
||||
private function shouldSkip(FunctionLike $functionLike): bool
|
||||
|
|
|
@ -12,6 +12,7 @@ use Rector\Application\RemovedFilesCollector;
|
|||
use Rector\Contract\Rector\PhpRectorInterface;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\Php\PhpVersionProvider;
|
||||
use Rector\PhpParser\Node\Value\ValueResolver;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;
|
||||
|
@ -46,6 +47,11 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
|||
*/
|
||||
private $valueResolver;
|
||||
|
||||
/**
|
||||
* @var PhpVersionProvider
|
||||
*/
|
||||
private $phpVersionProvider;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
|
@ -53,12 +59,14 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
|||
AppliedRectorCollector $appliedRectorCollector,
|
||||
SymfonyStyle $symfonyStyle,
|
||||
ValueResolver $valueResolver,
|
||||
RemovedFilesCollector $removedFilesCollector
|
||||
RemovedFilesCollector $removedFilesCollector,
|
||||
PhpVersionProvider $phpVersionProvider
|
||||
): void {
|
||||
$this->appliedRectorCollector = $appliedRectorCollector;
|
||||
$this->symfonyStyle = $symfonyStyle;
|
||||
$this->valueResolver = $valueResolver;
|
||||
$this->removedFilesCollector = $removedFilesCollector;
|
||||
$this->phpVersionProvider = $phpVersionProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,6 +188,11 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
|||
$this->appliedRectorCollector->addRectorClass(static::class, $fileInfo);
|
||||
}
|
||||
|
||||
protected function isAtLeastPhpVersion(string $version): bool
|
||||
{
|
||||
return $this->phpVersionProvider->isAtLeast($version);
|
||||
}
|
||||
|
||||
private function isMatchingNodeType(string $nodeClass): bool
|
||||
{
|
||||
foreach ($this->getNodeTypes() as $nodeType) {
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace Rector\Rector\ClassMethod;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\NodeTypeResolver\Php\ReturnTypeInfo;
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\ConfiguredCodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
@ -20,12 +21,18 @@ final class AddReturnTypeDeclarationRector extends AbstractRector
|
|||
*/
|
||||
private $typehintForMethodByClass = [];
|
||||
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
private $typeAnalyzer;
|
||||
|
||||
/**
|
||||
* @param mixed[] $typehintForMethodByClass
|
||||
*/
|
||||
public function __construct(array $typehintForMethodByClass)
|
||||
public function __construct(array $typehintForMethodByClass, TypeAnalyzer $typeAnalyzer)
|
||||
{
|
||||
$this->typehintForMethodByClass = $typehintForMethodByClass;
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
|
@ -96,7 +103,7 @@ CODE_SAMPLE
|
|||
if ($newType === '') {
|
||||
$classMethod->returnType = null;
|
||||
} else {
|
||||
$returnTypeInfo = new ReturnTypeInfo([$newType]);
|
||||
$returnTypeInfo = new ReturnTypeInfo([$newType], $this->typeAnalyzer);
|
||||
$classMethod->returnType = $returnTypeInfo->getFqnTypeNode();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ use PhpParser\Node\Stmt\ClassMethod;
|
|||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\Php\ParamTypeInfo;
|
||||
use Rector\Php\TypeAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\ConfiguredCodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
@ -25,12 +26,18 @@ final class ParentTypehintedArgumentRector extends AbstractRector
|
|||
*/
|
||||
private $typehintForArgumentByMethodAndClass = [];
|
||||
|
||||
/**
|
||||
* @var TypeAnalyzer
|
||||
*/
|
||||
private $typeAnalyzer;
|
||||
|
||||
/**
|
||||
* @param mixed[] $typehintForArgumentByMethodAndClass
|
||||
*/
|
||||
public function __construct(array $typehintForArgumentByMethodAndClass)
|
||||
public function __construct(array $typehintForArgumentByMethodAndClass, TypeAnalyzer $typeAnalyzer)
|
||||
{
|
||||
$this->typehintForArgumentByMethodAndClass = $typehintForArgumentByMethodAndClass;
|
||||
$this->typeAnalyzer = $typeAnalyzer;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
|
@ -118,7 +125,7 @@ CODE_SAMPLE
|
|||
if ($type === '') { // remove type
|
||||
$param->type = null;
|
||||
} else {
|
||||
$paramTypeInfo = new ParamTypeInfo($parameter, [$type]);
|
||||
$paramTypeInfo = new ParamTypeInfo($parameter, $this->typeAnalyzer, [$type]);
|
||||
$param->type = $paramTypeInfo->getFqnTypeNode();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user