Updated Rector to commit d9c5d8f09bfd68e7496c07c23ddac03447cfbb32

d9c5d8f09b [Strict] Allow check '0' empty zero on BooleanInTernaryOperatorRuleFixerRector on string type (#5297)
This commit is contained in:
Tomas Votruba 2023-12-03 15:49:51 +00:00
parent cd89d88b46
commit 9d01b5b403
5 changed files with 59 additions and 41 deletions

View File

@ -3,7 +3,9 @@
declare (strict_types=1);
namespace RectorPrefix202312;
use Rector\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector;
use Rector\Php83\Rector\ClassConst\AddTypeToConstRector;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig) : void {
$rectorConfig->rules([\Rector\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector::class, \Rector\Php83\Rector\ClassConst\AddTypeToConstRector::class]);
$rectorConfig->rules([AddOverrideAttributeToOverriddenMethodsRector::class, AddTypeToConstRector::class]);
};

View File

@ -3,6 +3,16 @@
declare (strict_types=1);
namespace Rector\Php83\Rector\ClassConst;
use PhpParser\Node\Stmt\ClassConst;
use PhpParser\Node\Identifier;
use PhpParser\Node\Const_;
use PhpParser\Node\Expr;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\DNumber;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Name;
use PhpParser\Node;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\Class_;
@ -18,7 +28,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\Php83\Rector\ClassConst\AddTypeToConstRector\AddTypeToConstRectorTest
*/
class AddTypeToConstRector extends AbstractRector implements MinPhpVersionInterface
final class AddTypeToConstRector extends AbstractRector implements MinPhpVersionInterface
{
/**
* @readonly
@ -57,8 +67,8 @@ CODE_SAMPLE
if ($node->isAbstract()) {
return null;
}
$consts = \array_filter($node->stmts, function (Node $stmt) {
return $stmt instanceof Node\Stmt\ClassConst;
$consts = \array_filter($node->stmts, static function (Node $node) : bool {
return $node instanceof ClassConst;
});
if ($consts === []) {
return null;
@ -85,7 +95,7 @@ CODE_SAMPLE
}
$valueType = $this->findValueType($constNode->value);
}
if (($valueType ?? null) === null) {
if (!($valueType ?? null) instanceof Identifier) {
continue;
}
$const->type = $valueType;
@ -105,15 +115,15 @@ CODE_SAMPLE
* @param ClassReflection[] $implementations
* @param ClassReflection[] $traits
*/
public function shouldSkipDueToInheritance(Node\Const_ $constNode, array $parents, array $implementations, array $traits) : bool
public function shouldSkipDueToInheritance(Const_ $const, array $parents, array $implementations, array $traits) : bool
{
foreach ([$parents, $implementations, $traits] as $inheritance) {
foreach ($inheritance as $inheritanceItem) {
if ($constNode->name->name === '') {
if ($const->name->name === '') {
continue;
}
try {
$inheritanceItem->getConstant($constNode->name->name);
$inheritanceItem->getConstant($const->name->name);
return \true;
} catch (MissingConstantFromReflectionException $exception) {
}
@ -121,25 +131,25 @@ CODE_SAMPLE
}
return \false;
}
private function findValueType(Node\Expr $value) : ?Node\Identifier
private function findValueType(Expr $expr) : ?Identifier
{
if ($value instanceof Node\Scalar\String_) {
return new Node\Identifier('string');
if ($expr instanceof String_) {
return new Identifier('string');
}
if ($value instanceof Node\Scalar\LNumber) {
return new Node\Identifier('int');
if ($expr instanceof LNumber) {
return new Identifier('int');
}
if ($value instanceof Node\Scalar\DNumber) {
return new Node\Identifier('float');
if ($expr instanceof DNumber) {
return new Identifier('float');
}
if ($value instanceof Node\Expr\ConstFetch && $value->name->toLowerString() !== 'null') {
return new Node\Identifier('bool');
if ($expr instanceof ConstFetch && $expr->name->toLowerString() !== 'null') {
return new Identifier('bool');
}
if ($value instanceof Node\Expr\ConstFetch && $value->name->toLowerString() === 'null') {
return new Node\Identifier('null');
if ($expr instanceof ConstFetch && $expr->name->toLowerString() === 'null') {
return new Identifier('null');
}
if ($value instanceof Node\Expr\Array_) {
return new Node\Identifier('array');
if ($expr instanceof Array_) {
return new Identifier('array');
}
return null;
}
@ -149,7 +159,7 @@ CODE_SAMPLE
private function getParents(Class_ $class) : array
{
$parents = \array_filter([$class->extends]);
return \array_map(function (Node\Name $name) : ClassReflection {
return \array_map(function (Name $name) : ClassReflection {
if (!$name instanceof FullyQualified) {
throw new FullyQualifiedNameNotAutoloadedException($name);
}
@ -164,7 +174,7 @@ CODE_SAMPLE
*/
private function getImplementations(Class_ $class) : array
{
return \array_map(function (Node\Name $name) : ClassReflection {
return \array_map(function (Name $name) : ClassReflection {
if (!$name instanceof FullyQualified) {
throw new FullyQualifiedNameNotAutoloadedException($name);
}
@ -177,13 +187,13 @@ CODE_SAMPLE
/**
* @return ClassReflection[]
*/
private function getTraits(Class_ $node) : array
private function getTraits(Class_ $class) : array
{
$traits = [];
foreach ($node->getTraitUses() as $traitUse) {
foreach ($class->getTraitUses() as $traitUse) {
$traits = \array_merge($traits, $traitUse->traits);
}
return \array_map(function (Node\Name $name) : ClassReflection {
return \array_map(function (Name $name) : ClassReflection {
if (!$name instanceof FullyQualified) {
throw new FullyQualifiedNameNotAutoloadedException($name);
}
@ -193,8 +203,8 @@ CODE_SAMPLE
throw new FullyQualifiedNameNotAutoloadedException($name);
}, $traits);
}
private function canBeInheritied(Node\Stmt\ClassConst $constNode, Class_ $node) : bool
private function canBeInheritied(ClassConst $classConst, Class_ $class) : bool
{
return !$node->isFinal() && !$constNode->isPrivate();
return !$class->isFinal() && !$classConst->isPrivate();
}
}

View File

@ -34,10 +34,13 @@ final class ExactCompareFactory
/**
* @return \PhpParser\Node\Expr\BinaryOp\Identical|\PhpParser\Node\Expr\BinaryOp\BooleanOr|\PhpParser\Node\Expr\BinaryOp\NotIdentical|\PhpParser\Node\Expr\BooleanNot|\PhpParser\Node\Expr\Instanceof_|\PhpParser\Node\Expr\BinaryOp\BooleanAnd|null
*/
public function createIdenticalFalsyCompare(Type $exprType, Expr $expr, bool $treatAsNonEmpty)
public function createIdenticalFalsyCompare(Type $exprType, Expr $expr, bool $treatAsNonEmpty, bool $isOnlyString = \true)
{
if ($exprType->isString()->yes()) {
return new Identical($expr, new String_(''));
if ($treatAsNonEmpty || !$isOnlyString) {
return new Identical($expr, new String_(''));
}
return new BooleanOr(new Identical($expr, new String_('')), new Identical($expr, new String_('0')));
}
if ($exprType->isInteger()->yes()) {
return new Identical($expr, new LNumber(0));
@ -54,15 +57,18 @@ final class ExactCompareFactory
if (!$exprType instanceof UnionType) {
return null;
}
return $this->createTruthyFromUnionType($exprType, $expr, $treatAsNonEmpty);
return $this->createTruthyFromUnionType($exprType, $expr, $treatAsNonEmpty, \false);
}
/**
* @return \PhpParser\Node\Expr\BinaryOp\Identical|\PhpParser\Node\Expr\Instanceof_|\PhpParser\Node\Expr\BinaryOp\BooleanOr|\PhpParser\Node\Expr\BinaryOp\NotIdentical|\PhpParser\Node\Expr\BinaryOp\BooleanAnd|\PhpParser\Node\Expr\BooleanNot|null
*/
public function createNotIdenticalFalsyCompare(Type $exprType, Expr $expr, bool $treatAsNotEmpty)
public function createNotIdenticalFalsyCompare(Type $exprType, Expr $expr, bool $treatAsNotEmpty, bool $isOnlyString = \true)
{
if ($exprType->isString()->yes()) {
return new NotIdentical($expr, new String_(''));
if ($treatAsNotEmpty || !$isOnlyString) {
return new NotIdentical($expr, new String_(''));
}
return new BooleanAnd(new NotIdentical($expr, new String_('')), new NotIdentical($expr, new String_('0')));
}
if ($exprType->isInteger()->yes()) {
return new NotIdentical($expr, new LNumber(0));
@ -73,12 +79,12 @@ final class ExactCompareFactory
if (!$exprType instanceof UnionType) {
return null;
}
return $this->createFromUnionType($exprType, $expr, $treatAsNotEmpty);
return $this->createFromUnionType($exprType, $expr, $treatAsNotEmpty, \false);
}
/**
* @return \PhpParser\Node\Expr\BinaryOp\Identical|\PhpParser\Node\Expr\Instanceof_|\PhpParser\Node\Expr\BinaryOp\BooleanOr|\PhpParser\Node\Expr\BinaryOp\NotIdentical|\PhpParser\Node\Expr\BinaryOp\BooleanAnd|\PhpParser\Node\Expr\BooleanNot|null
*/
private function createFromUnionType(UnionType $unionType, Expr $expr, bool $treatAsNotEmpty)
private function createFromUnionType(UnionType $unionType, Expr $expr, bool $treatAsNotEmpty, bool $isOnlyString)
{
$unionType = TypeCombinator::removeNull($unionType);
if ($unionType->isBoolean()->yes()) {
@ -92,7 +98,7 @@ final class ExactCompareFactory
if ($unionType instanceof UnionType) {
return $this->resolveFromCleanedNullUnionType($unionType, $expr, $treatAsNotEmpty);
}
$compareExpr = $this->createNotIdenticalFalsyCompare($unionType, $expr, $treatAsNotEmpty);
$compareExpr = $this->createNotIdenticalFalsyCompare($unionType, $expr, $treatAsNotEmpty, $isOnlyString);
if (!$compareExpr instanceof Expr) {
return null;
}
@ -170,7 +176,7 @@ final class ExactCompareFactory
/**
* @return \PhpParser\Node\Expr\BinaryOp\BooleanOr|\PhpParser\Node\Expr\BinaryOp\NotIdentical|\PhpParser\Node\Expr\BinaryOp\Identical|\PhpParser\Node\Expr\BooleanNot|\PhpParser\Node\Expr\Instanceof_|\PhpParser\Node\Expr\BinaryOp\BooleanAnd|null
*/
private function createTruthyFromUnionType(UnionType $unionType, Expr $expr, bool $treatAsNonEmpty)
private function createTruthyFromUnionType(UnionType $unionType, Expr $expr, bool $treatAsNonEmpty, bool $isOnlyString)
{
$unionType = $this->cleanUpPossibleNullableUnionType($unionType);
if ($unionType instanceof UnionType) {
@ -188,7 +194,7 @@ final class ExactCompareFactory
return $toNullIdentical;
}
// assume we have to check empty string, integer and bools
$scalarFalsyIdentical = $this->createIdenticalFalsyCompare($unionType, $expr, $treatAsNonEmpty);
$scalarFalsyIdentical = $this->createIdenticalFalsyCompare($unionType, $expr, $treatAsNonEmpty, $isOnlyString);
if (!$scalarFalsyIdentical instanceof Expr) {
return null;
}

View File

@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = 'e3f909cf030971b542c9c508298c729abb60eefe';
public const PACKAGE_VERSION = 'd9c5d8f09bfd68e7496c07c23ddac03447cfbb32';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2023-12-03 15:59:28';
public const RELEASE_DATE = '2023-12-03 22:47:38';
/**
* @var int
*/

View File

@ -5,7 +5,7 @@ namespace Rector\Core\Exception;
use PhpParser\Node\Name;
use RuntimeException;
class FullyQualifiedNameNotAutoloadedException extends RuntimeException
final class FullyQualifiedNameNotAutoloadedException extends RuntimeException
{
/**
* @var \PhpParser\Node\Name