diff --git a/rules-tests/TypeDeclaration/Rector/ArrowFunction/AddArrowFunctionReturnTypeRector/Fixture/return_by_array_shape_type.php.inc b/rules-tests/TypeDeclaration/Rector/ArrowFunction/AddArrowFunctionReturnTypeRector/Fixture/return_by_array_shape_type.php.inc deleted file mode 100644 index bb3cdad9084..00000000000 --- a/rules-tests/TypeDeclaration/Rector/ArrowFunction/AddArrowFunctionReturnTypeRector/Fixture/return_by_array_shape_type.php.inc +++ /dev/null @@ -1,33 +0,0 @@ - $values - */ - private function foo(array $values): void - { - $bars = array_map(fn($value) => $value['bar'], $values); - } -} - -?> ------ - $values - */ - private function foo(array $values): void - { - $bars = array_map(fn($value): int => $value['bar'], $values); - } -} - -?> diff --git a/rules/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector.php b/rules/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector.php index e3b48e80ded..93def346301 100644 --- a/rules/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector.php +++ b/rules/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector.php @@ -208,9 +208,9 @@ private function convertToPascalCase(string $name): string fn ($part): string => // If part is all uppercase, convert to ucfirst(strtolower()) // If part is already mixed or PascalCase, keep as is except ucfirst - ctype_upper($part) - ? ucfirst(strtolower($part)) - : ucfirst($part), + ctype_upper((string) $part) + ? ucfirst(strtolower((string) $part)) + : ucfirst((string) $part), $parts ) ); diff --git a/rules/TypeDeclaration/Rector/FuncCall/AddArrowFunctionParamArrayWhereDimFetchRector.php b/rules/TypeDeclaration/Rector/FuncCall/AddArrowFunctionParamArrayWhereDimFetchRector.php index 1fa3c45f010..58d691f303a 100644 --- a/rules/TypeDeclaration/Rector/FuncCall/AddArrowFunctionParamArrayWhereDimFetchRector.php +++ b/rules/TypeDeclaration/Rector/FuncCall/AddArrowFunctionParamArrayWhereDimFetchRector.php @@ -12,6 +12,7 @@ use PhpParser\Node\Expr\Instanceof_; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Identifier; +use PhpParser\Node\Scalar\String_; use PHPStan\Type\ArrayType; use Rector\PhpParser\Node\BetterNodeFinder; use Rector\Rector\AbstractRector; @@ -148,7 +149,8 @@ private function resolveDimFetchVariableNames(Closure|ArrowFunction $closureExpr if ($arrayDimFetch->var instanceof Variable) { $type = $this->nodeTypeResolver->getNativeType($arrayDimFetch->var); - if ($type->isString()->yes()) { + // skip string values + if (! $arrayDimFetch->dim instanceof String_ && ($type->isString()->yes() || $type->isString()->maybe())) { continue; } diff --git a/src/DependencyInjection/PHPStan/PHPStanContainerMemento.php b/src/DependencyInjection/PHPStan/PHPStanContainerMemento.php new file mode 100644 index 00000000000..0edd4491c97 --- /dev/null +++ b/src/DependencyInjection/PHPStan/PHPStanContainerMemento.php @@ -0,0 +1,51 @@ +getPrivateProperty($richParser, 'container'); + + /** @var NetteContainer $originalContainer */ + $originalContainer = $privatesAccessor->getPrivateProperty($container, 'originalContainer'); + + /** @var NetteContainer $originalContainer */ + $deeperContainer = $privatesAccessor->getPrivateProperty($originalContainer, 'container'); + + // get tags property + $tags = $privatesAccessor->getPrivateProperty($deeperContainer, 'tags'); + + // keep visitors that are useful + // remove all the rest, https://github.com/phpstan/phpstan-src/tree/1d86de8bb9371534983a8dbcd879e057d2ff028f/src/Parser + $nodeVisitorsToKeep = [ + $container->findServiceNamesByType(AnonymousClassVisitor::class)[0] => true, + $container->findServiceNamesByType(VariadicFunctionsVisitor::class)[0] => true, + $container->findServiceNamesByType(VariadicMethodsVisitor::class)[0] => true, + ]; + + $tags[RichParser::VISITOR_SERVICE_TAG] = $nodeVisitorsToKeep; + + $privatesAccessor->setPrivateProperty($deeperContainer, 'tags', $tags); + } +} diff --git a/src/PhpParser/Parser/RectorParser.php b/src/PhpParser/Parser/RectorParser.php index 3594e2d00de..81f72aeb206 100644 --- a/src/PhpParser/Parser/RectorParser.php +++ b/src/PhpParser/Parser/RectorParser.php @@ -8,15 +8,22 @@ use PhpParser\ParserFactory; use PhpParser\PhpVersion; use PHPStan\Parser\Parser; +use PHPStan\Parser\RichParser; +use Rector\DependencyInjection\PHPStan\PHPStanContainerMemento; use Rector\PhpParser\ValueObject\StmtsAndTokens; use Rector\Util\Reflection\PrivatesAccessor; final readonly class RectorParser { + /** + * @param RichParser $parser + */ public function __construct( private Parser $parser, private PrivatesAccessor $privatesAccessor ) { + + PHPStanContainerMemento::removeRichVisitors($parser); } /** diff --git a/tests/PhpParser/Printer/Fixture/some_array_map.php b/tests/PhpParser/Printer/Fixture/some_array_map.php index 824ecfc90d8..c5a50902dd6 100644 --- a/tests/PhpParser/Printer/Fixture/some_array_map.php +++ b/tests/PhpParser/Printer/Fixture/some_array_map.php @@ -1,5 +1,3 @@ $value); +$result = \array_map(array: [1, 2, 3], callback: fn(int $value) => $value); diff --git a/tests/PhpParser/Printer/PHPStanPrinterTest.php b/tests/PhpParser/Printer/PHPStanPrinterTest.php index 15a021fa855..d95bdafaf0d 100644 --- a/tests/PhpParser/Printer/PHPStanPrinterTest.php +++ b/tests/PhpParser/Printer/PHPStanPrinterTest.php @@ -7,12 +7,15 @@ use PhpParser\PrettyPrinter\Standard; use PHPStan\Parser\Parser; use PHPStan\Parser\RichParser; +use Rector\DependencyInjection\PHPStan\PHPStanContainerMemento; use Rector\Testing\PHPUnit\AbstractLazyTestCase; use ReflectionProperty; /** * Test case for: https://github.com/rectorphp/rector/issues/9492 * Most likely caused by https://github.com/phpstan/phpstan-src/pull/3763 + * + * @see https://github.com/phpstan/phpstan-src/blob/2.1.x/src/Parser/ArrayMapArgVisitor.php */ final class PHPStanPrinterTest extends AbstractLazyTestCase { @@ -21,6 +24,8 @@ public function testAddingCommentOnSomeNodesFail(): void /** @var RichParser $phpstanParser */ $phpstanParser = $this->make(Parser::class); + PHPStanContainerMemento::removeRichVisitors($phpstanParser); + $stmts = $phpstanParser->parseFile(__DIR__ . '/Fixture/some_array_map.php'); // get private property "parser"