diff --git a/build/target-repository/docs/rector_rules_overview.md b/build/target-repository/docs/rector_rules_overview.md
index cb7a029c70e..f05994dbcab 100644
--- a/build/target-repository/docs/rector_rules_overview.md
+++ b/build/target-repository/docs/rector_rules_overview.md
@@ -1,4 +1,4 @@
-# 354 Rules Overview
+# 355 Rules Overview
@@ -44,7 +44,7 @@
- [Php82](#php82) (4)
-- [Php83](#php83) (2)
+- [Php83](#php83) (3)
- [Privatization](#privatization) (4)
@@ -5312,6 +5312,19 @@ Add const to type
+### CombineHostPortLdapUriRector
+
+Combine separated host and port on `ldap_connect()` args
+
+- class: [`Rector\Php83\Rector\FuncCall\CombineHostPortLdapUriRector`](../rules/Php83/Rector/FuncCall/CombineHostPortLdapUriRector.php)
+
+```diff
+-ldap_connect('ldap://ldap.example.com', 389);
++ldap_connect('ldap://ldap.example.com:389');
+```
+
+
+
## Privatization
### FinalizeClassesWithoutChildrenRector
@@ -6850,13 +6863,15 @@ Add return type based on strict parameter type
Change return type based on strict scalar returns - string, int, float or bool
+:wrench: **configure it!**
+
- class: [`Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictScalarReturnExprRector`](../rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector.php)
```diff
final class SomeClass
{
-- public function run($value)
-+ public function run($value): string
+- public function foo($value)
++ public function foo($value): string
{
if ($value) {
return 'yes';
@@ -6864,6 +6879,12 @@ Change return type based on strict scalar returns - string, int, float or bool
return 'no';
}
+
+- public function bar(string $value)
++ public function bar(string $value): int
+ {
+ return strlen($value);
+ }
}
```
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/bool.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/bool.php.inc
new file mode 100644
index 00000000000..9dc195787ba
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/bool.php.inc
@@ -0,0 +1,35 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/final_method.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/final_method.php.inc
new file mode 100644
index 00000000000..502ad71f4e0
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/final_method.php.inc
@@ -0,0 +1,49 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float.php.inc
new file mode 100644
index 00000000000..c889e3a2cb7
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float.php.inc
@@ -0,0 +1,27 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float_negative.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float_negative.php.inc
new file mode 100644
index 00000000000..c1557ebcd46
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float_negative.php.inc
@@ -0,0 +1,27 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float_positive.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float_positive.php.inc
new file mode 100644
index 00000000000..5d83a79b901
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/float_positive.php.inc
@@ -0,0 +1,27 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int.php.inc
new file mode 100644
index 00000000000..2130915d2d2
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int.php.inc
@@ -0,0 +1,27 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int_negative.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int_negative.php.inc
new file mode 100644
index 00000000000..8b519ecbc74
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int_negative.php.inc
@@ -0,0 +1,27 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int_positive.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int_positive.php.inc
new file mode 100644
index 00000000000..45c5477fe70
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/int_positive.php.inc
@@ -0,0 +1,27 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/skip_calc.php.inc b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/skip_calc.php.inc
new file mode 100644
index 00000000000..64ff5905099
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/FixtureHardCodedOnly/skip_calc.php.inc
@@ -0,0 +1,11 @@
+
+-----
+
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/HardCodedOnlyTest.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/HardCodedOnlyTest.php
new file mode 100644
index 00000000000..dd188c25927
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/HardCodedOnlyTest.php
@@ -0,0 +1,28 @@
+doTestFile($filePath);
+ }
+
+ public static function provideData(): Iterator
+ {
+ return self::yieldFilesFromDirectory(__DIR__ . '/FixtureHardCodedOnly');
+ }
+
+ public function provideConfigFilePath(): string
+ {
+ return __DIR__ . '/config/configured_rule_hard_coded_only.php';
+ }
+}
diff --git a/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/config/configured_rule_hard_coded_only.php b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/config/configured_rule_hard_coded_only.php
new file mode 100644
index 00000000000..f27974dd8e5
--- /dev/null
+++ b/rules-tests/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector/config/configured_rule_hard_coded_only.php
@@ -0,0 +1,12 @@
+ruleWithConfiguration(ReturnTypeFromStrictScalarReturnExprRector::class, [
+ ReturnTypeFromStrictScalarReturnExprRector::HARD_CODED_ONLY => true,
+ ]);
+};
diff --git a/rules/TypeDeclaration/NodeAnalyzer/ReturnTypeAnalyzer/StrictScalarReturnTypeAnalyzer.php b/rules/TypeDeclaration/NodeAnalyzer/ReturnTypeAnalyzer/StrictScalarReturnTypeAnalyzer.php
index bfa22955fa9..289f58ee640 100644
--- a/rules/TypeDeclaration/NodeAnalyzer/ReturnTypeAnalyzer/StrictScalarReturnTypeAnalyzer.php
+++ b/rules/TypeDeclaration/NodeAnalyzer/ReturnTypeAnalyzer/StrictScalarReturnTypeAnalyzer.php
@@ -6,6 +6,9 @@
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Closure;
+use PhpParser\Node\Expr\ConstFetch;
+use PhpParser\Node\Expr\UnaryMinus;
+use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Type\Type;
@@ -21,8 +24,10 @@ public function __construct(
) {
}
- public function matchAlwaysScalarReturnType(ClassMethod|Closure|Function_ $functionLike): ?Type
- {
+ public function matchAlwaysScalarReturnType(
+ ClassMethod|Closure|Function_ $functionLike,
+ bool $hardCodedOnly = false
+ ): ?Type {
$returns = $this->alwaysStrictReturnAnalyzer->matchAlwaysStrictReturns($functionLike);
if ($returns === []) {
return null;
@@ -36,6 +41,10 @@ public function matchAlwaysScalarReturnType(ClassMethod|Closure|Function_ $funct
return null;
}
+ if ($hardCodedOnly && ! $this->isHardCodedExpression($return->expr)) {
+ return null;
+ }
+
$scalarType = $this->alwaysStrictScalarExprAnalyzer->matchStrictScalarExpr($return->expr);
if (! $scalarType instanceof Type) {
return null;
@@ -46,4 +55,25 @@ public function matchAlwaysScalarReturnType(ClassMethod|Closure|Function_ $funct
return $this->typeFactory->createMixedPassedOrUnionType($scalarTypes);
}
+
+ private function isHardCodedExpression(Expr $expr): bool
+ {
+ // Normal scalar values like strings, integers and floats
+ if ($expr instanceof Scalar) {
+ return true;
+ }
+
+ // true / false / null are constants
+ if ($expr instanceof ConstFetch &&
+ in_array($expr->name->toLowerString(), ['true', 'false', 'null'], true)) {
+ return true;
+ }
+
+ // Negative numbers are wrapped in UnaryMinus, so check expression inside it
+ if (($expr instanceof UnaryMinus || $expr instanceof Expr\UnaryPlus) && $expr->expr instanceof Scalar) {
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector.php b/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector.php
index d98b90db680..db676cb55ee 100644
--- a/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector.php
+++ b/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictScalarReturnExprRector.php
@@ -11,6 +11,7 @@
use PhpParser\Node\UnionType;
use PHPStan\Analyser\Scope;
use PHPStan\Type\Type;
+use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\ValueObject\PhpVersion;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
@@ -18,14 +19,22 @@
use Rector\TypeDeclaration\NodeAnalyzer\ReturnTypeAnalyzer\StrictScalarReturnTypeAnalyzer;
use Rector\VendorLocker\NodeVendorLocker\ClassMethodReturnTypeOverrideGuard;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
-use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
+use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
+use Webmozart\Assert\Assert;
/**
* @see \Rector\Tests\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictScalarReturnExprRector\ReturnTypeFromStrictScalarReturnExprRectorTest
*/
-final class ReturnTypeFromStrictScalarReturnExprRector extends AbstractScopeAwareRector implements MinPhpVersionInterface
+final class ReturnTypeFromStrictScalarReturnExprRector extends AbstractScopeAwareRector implements MinPhpVersionInterface, ConfigurableRectorInterface
{
+ /**
+ * @var string
+ */
+ public const HARD_CODED_ONLY = 'hard_coded_only';
+
+ private bool $hardCodedOnly = false;
+
public function __construct(
private readonly StrictScalarReturnTypeAnalyzer $strictScalarReturnTypeAnalyzer,
private readonly ClassMethodReturnTypeOverrideGuard $classMethodReturnTypeOverrideGuard,
@@ -36,11 +45,11 @@ public function __construct(
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Change return type based on strict scalar returns - string, int, float or bool', [
- new CodeSample(
+ new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
final class SomeClass
{
- public function run($value)
+ public function foo($value)
{
if ($value) {
return 'yes';
@@ -48,14 +57,18 @@ public function run($value)
return 'no';
}
+
+ public function bar(string $value)
+ {
+ return strlen($value);
+ }
}
CODE_SAMPLE
-
,
<<<'CODE_SAMPLE'
final class SomeClass
{
- public function run($value): string
+ public function foo($value): string
{
if ($value) {
return 'yes';
@@ -63,8 +76,17 @@ public function run($value): string
return 'no';
}
+
+ public function bar(string $value): int
+ {
+ return strlen($value);
+ }
}
CODE_SAMPLE
+ ,
+ [
+ ReturnTypeFromStrictScalarReturnExprRector::HARD_CODED_ONLY => false,
+ ]
),
]);
}
@@ -87,7 +109,10 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node
return null;
}
- $scalarReturnType = $this->strictScalarReturnTypeAnalyzer->matchAlwaysScalarReturnType($node);
+ $scalarReturnType = $this->strictScalarReturnTypeAnalyzer->matchAlwaysScalarReturnType(
+ $node,
+ $this->hardCodedOnly
+ );
if (! $scalarReturnType instanceof Type) {
return null;
}
@@ -116,4 +141,12 @@ public function provideMinPhpVersion(): int
{
return PhpVersion::PHP_70;
}
+
+ public function configure(array $configuration): void
+ {
+ $hardCodedOnly = $configuration[self::HARD_CODED_ONLY] ?? false;
+ Assert::boolean($hardCodedOnly);
+
+ $this->hardCodedOnly = $hardCodedOnly;
+ }
}