From fc7a47fa08560f3bdbf9ea45b9fb6fb4cdfabbfe Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Mon, 29 Jun 2026 00:16:50 +0200 Subject: [PATCH] [dx] optimize cheaper early returns --- .../Expression/InlineIfToExplicitIfRector.php | 10 +++++----- .../LogicalAnd/LogicalToBooleanRector.php | 9 +++++---- .../NumberCompareToMaxFuncCallRector.php | 11 ++++++++--- .../FuncCall/ConsistentImplodeRector.php | 8 ++++---- .../RemoveNextSameValueConditionRector.php | 18 +++++++++--------- .../ExportToReflectionFunctionRector.php | 8 ++++---- ...pertyAssignToConstructorPromotionRector.php | 4 ++-- .../New_/FilesystemIteratorSkipDotsRector.php | 4 ++-- .../FuncCall/AddEscapeArgumentRector.php | 8 ++++---- .../Rector/FuncCall/OrdSingleByteRector.php | 15 ++++++++------- .../RemoveFinfoBufferContextArgRector.php | 9 ++++----- ...aramArrayDocblockFromDataProviderRector.php | 4 ++-- ...DocblockForArrayDimAssignedObjectRector.php | 10 +++++----- ...ocblockForCommonObjectDenominatorRector.php | 8 ++++---- .../AddReturnDocblockForJsonArrayRector.php | 7 ++----- ...urnDocblockFromMethodCallDocblockRector.php | 8 ++++---- 16 files changed, 72 insertions(+), 69 deletions(-) diff --git a/rules/CodeQuality/Rector/Expression/InlineIfToExplicitIfRector.php b/rules/CodeQuality/Rector/Expression/InlineIfToExplicitIfRector.php index d99eaa94bd1..cd7d2268b20 100644 --- a/rules/CodeQuality/Rector/Expression/InlineIfToExplicitIfRector.php +++ b/rules/CodeQuality/Rector/Expression/InlineIfToExplicitIfRector.php @@ -89,11 +89,6 @@ private function processExplicitIf(Expression $expression): ?Node /** @var BooleanAnd|BooleanOr $booleanExpr */ $booleanExpr = $expression->expr; - $leftStaticType = $this->getType($booleanExpr->left); - if (! $leftStaticType->isBoolean()->yes()) { - return null; - } - $exprLeft = $booleanExpr->left instanceof BooleanNot ? $booleanExpr->left->expr : $booleanExpr->left; @@ -102,6 +97,11 @@ private function processExplicitIf(Expression $expression): ?Node return null; } + $leftStaticType = $this->getType($booleanExpr->left); + if (! $leftStaticType->isBoolean()->yes()) { + return null; + } + /** @var Expr $expr */ $expr = $booleanExpr instanceof BooleanAnd ? $booleanExpr->left diff --git a/rules/CodeQuality/Rector/LogicalAnd/LogicalToBooleanRector.php b/rules/CodeQuality/Rector/LogicalAnd/LogicalToBooleanRector.php index aea7cced284..46be40f26b6 100644 --- a/rules/CodeQuality/Rector/LogicalAnd/LogicalToBooleanRector.php +++ b/rules/CodeQuality/Rector/LogicalAnd/LogicalToBooleanRector.php @@ -54,10 +54,11 @@ public function getNodeTypes(): array */ public function refactor(Node $node): BooleanAnd|BooleanOr|null { - $type = $this->nodeTypeResolver->getNativeType($node->left); - - if ($node->left instanceof Assign && ! $type->isBoolean()->yes()) { - return null; + if ($node->left instanceof Assign) { + $type = $this->nodeTypeResolver->getNativeType($node->left); + if (! $type->isBoolean()->yes()) { + return null; + } } return $this->refactorLogicalToBoolean($node); diff --git a/rules/CodeQuality/Rector/Ternary/NumberCompareToMaxFuncCallRector.php b/rules/CodeQuality/Rector/Ternary/NumberCompareToMaxFuncCallRector.php index 263c98546c4..45216652b5e 100644 --- a/rules/CodeQuality/Rector/Ternary/NumberCompareToMaxFuncCallRector.php +++ b/rules/CodeQuality/Rector/Ternary/NumberCompareToMaxFuncCallRector.php @@ -66,9 +66,6 @@ public function refactor(Node $node): ?Node } $binaryOp = $node->cond; - if (! $this->areIntegersCompared($binaryOp)) { - return null; - } if ($binaryOp instanceof Smaller || $binaryOp instanceof SmallerOrEqual) { if (! $this->nodeComparator->areNodesEqual($binaryOp->left, $node->else)) { @@ -79,6 +76,10 @@ public function refactor(Node $node): ?Node return null; } + if (! $this->areIntegersCompared($binaryOp)) { + return null; + } + return $this->nodeFactory->createFuncCall('max', [$node->if, $node->else]); } @@ -91,6 +92,10 @@ public function refactor(Node $node): ?Node return null; } + if (! $this->areIntegersCompared($binaryOp)) { + return null; + } + return $this->nodeFactory->createFuncCall('max', [$node->if, $node->else]); } diff --git a/rules/CodingStyle/Rector/FuncCall/ConsistentImplodeRector.php b/rules/CodingStyle/Rector/FuncCall/ConsistentImplodeRector.php index 2140ec4dde2..8a18810a736 100644 --- a/rules/CodingStyle/Rector/FuncCall/ConsistentImplodeRector.php +++ b/rules/CodingStyle/Rector/FuncCall/ConsistentImplodeRector.php @@ -84,6 +84,10 @@ public function refactor(Node $node): ?Node return $node; } + if (count($node->getArgs()) !== 2) { + return null; + } + $firstArg = $node->getArgs()[0]; $firstArgumentValue = $firstArg->value; @@ -92,10 +96,6 @@ public function refactor(Node $node): ?Node return null; } - if (count($node->getArgs()) !== 2) { - return null; - } - $secondArg = $node->getArgs()[1]; if ($this->stringTypeAnalyzer->isStringOrUnionStringOnlyType($secondArg->value)) { diff --git a/rules/DeadCode/Rector/Stmt/RemoveNextSameValueConditionRector.php b/rules/DeadCode/Rector/Stmt/RemoveNextSameValueConditionRector.php index bfb0a1485b8..9f80dd08301 100644 --- a/rules/DeadCode/Rector/Stmt/RemoveNextSameValueConditionRector.php +++ b/rules/DeadCode/Rector/Stmt/RemoveNextSameValueConditionRector.php @@ -101,15 +101,6 @@ public function refactor(Node $node): ?Node continue; } - // first condition must be without side effect - if ($this->sideEffectNodeDetector->detect($stmt->cond)) { - continue; - } - - if ($this->isCondVariableUsedInIfBody($stmt)) { - continue; - } - $nextStmt = $node->stmts[$key + 1] ?? null; if (! $nextStmt instanceof If_) { continue; @@ -128,6 +119,15 @@ public function refactor(Node $node): ?Node continue; } + // first condition must be without side effect + if ($this->sideEffectNodeDetector->detect($stmt->cond)) { + continue; + } + + if ($this->isCondVariableUsedInIfBody($stmt)) { + continue; + } + $stmt->setAttribute(AttributeKey::COMMENTS, array_merge( $stmt->getAttribute(AttributeKey::COMMENTS) ?? [], $nextStmt->getAttribute(AttributeKey::COMMENTS) ?? [] diff --git a/rules/Php74/Rector/StaticCall/ExportToReflectionFunctionRector.php b/rules/Php74/Rector/StaticCall/ExportToReflectionFunctionRector.php index 06bf2182372..1919e2fc83d 100644 --- a/rules/Php74/Rector/StaticCall/ExportToReflectionFunctionRector.php +++ b/rules/Php74/Rector/StaticCall/ExportToReflectionFunctionRector.php @@ -70,16 +70,16 @@ public function refactor(Node $node): ?Node return null; } - $callerType = $this->nodeTypeResolver->getType($node->class); - if (! $callerType->isSuperTypeOf(new ObjectType('ReflectionFunction'))->yes()) { + if (! $this->isName($node->name, 'export')) { return null; } - if (! $this->isName($node->name, 'export')) { + if ($node->isFirstClassCallable()) { return null; } - if ($node->isFirstClassCallable()) { + $callerType = $this->nodeTypeResolver->getType($node->class); + if (! $callerType->isSuperTypeOf(new ObjectType('ReflectionFunction'))->yes()) { return null; } diff --git a/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php b/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php index 8ccc1c27ba7..7e26ea9b871 100644 --- a/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php +++ b/rules/Php80/Rector/Class_/ClassPropertyAssignToConstructorPromotionRector.php @@ -177,13 +177,13 @@ public function refactor(Node $node): ?Node return null; } - $constructorPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($constructClassMethod); - $classReflection = $this->reflectionResolver->resolveClassReflection($node); if (! $classReflection instanceof ClassReflection) { return null; } + $constructorPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($constructClassMethod); + $hasChanged = false; foreach ($promotionCandidates as $promotionCandidate) { $param = $promotionCandidate->getParam(); diff --git a/rules/Php82/Rector/New_/FilesystemIteratorSkipDotsRector.php b/rules/Php82/Rector/New_/FilesystemIteratorSkipDotsRector.php index c12253ce959..4e48f505fc2 100644 --- a/rules/Php82/Rector/New_/FilesystemIteratorSkipDotsRector.php +++ b/rules/Php82/Rector/New_/FilesystemIteratorSkipDotsRector.php @@ -58,11 +58,11 @@ public function refactor(Node $node): ?New_ return null; } - if (! $this->isObjectType($node->class, new ObjectType('FilesystemIterator'))) { + if (! isset($node->args[1])) { return null; } - if (! isset($node->args[1])) { + if (! $this->isObjectType($node->class, new ObjectType('FilesystemIterator'))) { return null; } diff --git a/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php b/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php index 786244d45c5..262da4fdbc0 100644 --- a/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php +++ b/rules/Php84/Rector/FuncCall/AddEscapeArgumentRector.php @@ -75,16 +75,16 @@ public function refactor(Node $node): null|FuncCall|MethodCall return $node; } - if (! $this->isObjectType($node->var, new ObjectType('SplFileObject'))) { - return null; - } - $name = $this->getName($node->name); if (! in_array($name, ['setCsvControl', 'fputcsv', 'fgetcsv'], true)) { return null; } + if (! $this->isObjectType($node->var, new ObjectType('SplFileObject'))) { + return null; + } + if ($this->shouldSkipNamedArg($node)) { return null; } diff --git a/rules/Php85/Rector/FuncCall/OrdSingleByteRector.php b/rules/Php85/Rector/FuncCall/OrdSingleByteRector.php index 6b413368af6..1391b540ecd 100644 --- a/rules/Php85/Rector/FuncCall/OrdSingleByteRector.php +++ b/rules/Php85/Rector/FuncCall/OrdSingleByteRector.php @@ -74,23 +74,24 @@ public function refactor(Node $node): ?Node $firstArg = $args[0]; $argExpr = $firstArg->value; - $type = $this->nodeTypeResolver->getNativeType($argExpr); - if (! $type->isString()->yes() && ! $type->isInteger()->yes()) { + if ($argExpr instanceof String_ && strlen($argExpr->value) === 1) { return null; } - $value = $this->valueResolver->getValue($argExpr); - $isInt = is_int($value); - - if ($argExpr instanceof String_ && strlen($argExpr->value) === 1) { + if ($argExpr instanceof Int_ && strlen((string) $argExpr->value) === 1) { return null; } - if ($argExpr instanceof Int_ && strlen((string) $argExpr->value) === 1) { + $type = $this->nodeTypeResolver->getNativeType($argExpr); + + if (! $type->isString()->yes() && ! $type->isInteger()->yes()) { return null; } + $value = $this->valueResolver->getValue($argExpr); + $isInt = is_int($value); + if (! $argExpr instanceof Int_) { return $this->refactorStringType($argExpr, $isInt, $args, $node); } diff --git a/rules/Php85/Rector/FuncCall/RemoveFinfoBufferContextArgRector.php b/rules/Php85/Rector/FuncCall/RemoveFinfoBufferContextArgRector.php index 7db9eb0514c..cb3bf119a4e 100644 --- a/rules/Php85/Rector/FuncCall/RemoveFinfoBufferContextArgRector.php +++ b/rules/Php85/Rector/FuncCall/RemoveFinfoBufferContextArgRector.php @@ -65,11 +65,10 @@ public function refactor(Node $node): ?Node return null; } - $objectType = new ObjectType('finfo'); - if ($node instanceof MethodCall && (! $this->nodeTypeResolver->isObjectType( - $node->var, - $objectType - ) || ! $this->isName($node->name, 'buffer'))) { + if ($node instanceof MethodCall && (! $this->isName( + $node->name, + 'buffer' + ) || ! $this->nodeTypeResolver->isObjectType($node->var, new ObjectType('finfo')))) { return null; } diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromDataProviderRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromDataProviderRector.php index 93fd0236517..8a5a9e5f6e6 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromDataProviderRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddParamArrayDocblockFromDataProviderRector.php @@ -109,13 +109,13 @@ public function refactor(Node $node): ?Node continue; } - $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod); - $dataProviderNodes = $this->dataProviderMethodsFinder->findDataProviderNodes($node, $classMethod); if ($dataProviderNodes->getClassMethods() === []) { continue; } + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod); + foreach ($classMethod->getParams() as $paramPosition => $param) { // we are interested only in array params if (! $param->type instanceof Node) { diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php index 5809dc3f431..07be9997c54 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForArrayDimAssignedObjectRector.php @@ -98,6 +98,11 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { + // definitely not an array return + if ($node->returnType instanceof Node && ! $this->isName($node->returnType, 'array')) { + return null; + } + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); $returnType = $phpDocInfo->getReturnType(); @@ -109,11 +114,6 @@ public function refactor(Node $node): ?Node return null; } - // definitely not an array return - if ($node->returnType instanceof Node && ! $this->isName($node->returnType, 'array')) { - return null; - } - $onlyReturnWithExpr = $this->returnNodeFinder->findOnlyReturnWithExpr($node); if (! $onlyReturnWithExpr instanceof Return_ || ! $onlyReturnWithExpr->expr instanceof Variable) { return null; diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php index a2b9441b9d3..f45d7733070 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForCommonObjectDenominatorRector.php @@ -109,13 +109,13 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); - if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) { + // definitely not an array return + if ($node->returnType instanceof Node && ! $this->isName($node->returnType, 'array')) { return null; } - // definitely not an array return - if ($node->returnType instanceof Node && ! $this->isName($node->returnType, 'array')) { + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); + if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) { return null; } diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForJsonArrayRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForJsonArrayRector.php index 2351f65b957..a60f8964302 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForJsonArrayRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockForJsonArrayRector.php @@ -85,8 +85,6 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); - // definitely not an array return if ($node->returnType instanceof Node && ! $this->isName($node->returnType, 'array')) { return null; @@ -106,9 +104,8 @@ public function refactor(Node $node): ?Node return null; } - $classMethodDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); - - if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($classMethodDocInfo->getReturnTagValue())) { + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); + if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) { return null; } diff --git a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockFromMethodCallDocblockRector.php b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockFromMethodCallDocblockRector.php index 2040a39a407..d7f624089b1 100644 --- a/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockFromMethodCallDocblockRector.php +++ b/rules/TypeDeclarationDocblocks/Rector/ClassMethod/AddReturnDocblockFromMethodCallDocblockRector.php @@ -105,13 +105,13 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); - if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) { + // definitely not an array return + if (! $node->returnType instanceof Node || ! $this->isName($node->returnType, 'array')) { return null; } - // definitely not an array return - if (! $node->returnType instanceof Node || ! $this->isName($node->returnType, 'array')) { + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); + if ($this->usefulArrayTagNodeAnalyzer->isUsefulArrayTag($phpDocInfo->getReturnTagValue())) { return null; }