diff --git a/packages/CodingStyle/src/Rector/Namespace_/ImportFullyQualifiedNamesRector.php b/packages/CodingStyle/src/Rector/Namespace_/ImportFullyQualifiedNamesRector.php index a9af31e88016..32912c6ae938 100644 --- a/packages/CodingStyle/src/Rector/Namespace_/ImportFullyQualifiedNamesRector.php +++ b/packages/CodingStyle/src/Rector/Namespace_/ImportFullyQualifiedNamesRector.php @@ -19,15 +19,24 @@ final class ImportFullyQualifiedNamesRector extends AbstractRector */ private $shouldImportDocBlocks = true; + /** + * @var bool + */ + private $shouldImportRootNamespaceClasses = true; + /** * @var NameImporter */ private $nameImporter; - public function __construct(NameImporter $nameImporter, bool $shouldImportDocBlocks = true) - { + public function __construct( + NameImporter $nameImporter, + bool $shouldImportDocBlocks = true, + bool $shouldImportRootNamespaceClasses = true + ) { $this->nameImporter = $nameImporter; $this->shouldImportDocBlocks = $shouldImportDocBlocks; + $this->shouldImportRootNamespaceClasses = $shouldImportRootNamespaceClasses; } public function getDefinition(): RectorDefinition @@ -75,12 +84,20 @@ public function refactor(Node $node): ?Node $this->useAddingCommander->analyseFileInfoUseStatements($node); if ($node instanceof Name) { + // Importing root namespace classes (like \DateTime) is optional + if (! $this->shouldImportRootNamespaceClasses) { + $name = $this->getName($node); + if ($name !== null && substr_count($name, '\\') === 0) { + return null; + } + } + return $this->nameImporter->importName($node); } // process doc blocks if ($this->shouldImportDocBlocks) { - $this->docBlockManipulator->importNames($node); + $this->docBlockManipulator->importNames($node, $this->shouldImportRootNamespaceClasses); return $node; } diff --git a/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_root_namespace_classes_disabled.php.inc b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_root_namespace_classes_disabled.php.inc new file mode 100644 index 000000000000..658e32bfb4e5 --- /dev/null +++ b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_root_namespace_classes_disabled.php.inc @@ -0,0 +1,100 @@ +date = $currentDate; + $this->response = $response; + } + + public function setDate(?\DateTime $date): void + { + $this->date = $date; + } + + public function getDate(): ?\DateTime + { + return $this->date; + } + + public function setResponse(?\Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source\Response $response): void + { + $this->response = $response; + } + + public function getResponse(): ?\Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source\Response + { + return $this->response; + } +} +?> +----- +date = $currentDate; + $this->response = $response; + } + + public function setDate(?\DateTime $date): void + { + $this->date = $date; + } + + public function getDate(): ?\DateTime + { + return $this->date; + } + + public function setResponse(?Response $response): void + { + $this->response = $response; + } + + public function getResponse(): ?Response + { + return $this->response; + } +} +?> diff --git a/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_root_namespace_classes_enabled.php.inc b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_root_namespace_classes_enabled.php.inc new file mode 100644 index 000000000000..7c1629c8d0b8 --- /dev/null +++ b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/import_root_namespace_classes_enabled.php.inc @@ -0,0 +1,62 @@ +date = $currentDate; + } + + public function setDate(?\DateTime $date): void + { + $this->date = $date; + } + + public function getDate(): ?\DateTime + { + return $this->date; + } +} +?> +----- +date = $currentDate; + } + + public function setDate(?DateTime $date): void + { + $this->date = $date; + } + + public function getDate(): ?DateTime + { + return $this->date; + } +} +?> diff --git a/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/ImportFullyQualifiedNamesRectorTest.php b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/ImportFullyQualifiedNamesRectorTest.php index 9d032e265e3b..9aa5bcd3be53 100644 --- a/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/ImportFullyQualifiedNamesRectorTest.php +++ b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/ImportFullyQualifiedNamesRectorTest.php @@ -58,6 +58,8 @@ public function provideNamespacedClasses(): Iterator yield [__DIR__ . '/Fixture/keep_static_method.php.inc']; yield [__DIR__ . '/Fixture/keep_various_request.php.inc']; yield [__DIR__ . '/Fixture/instance_of.php.inc']; + + yield [__DIR__ . '/Fixture/import_root_namespace_classes_enabled.php.inc']; } public function provideFunctions(): Iterator diff --git a/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/ImportRootNamespaceClassesDisabledTest.php b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/ImportRootNamespaceClassesDisabledTest.php new file mode 100644 index 000000000000..70356e0305dc --- /dev/null +++ b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/ImportRootNamespaceClassesDisabledTest.php @@ -0,0 +1,33 @@ +doTestFile($file); + } + + public function provideDataForTest(): iterable + { + yield [__DIR__ . '/Fixture/import_root_namespace_classes_disabled.php.inc']; + } + + protected function getRectorsWithConfiguration(): array + { + return [ + ImportFullyQualifiedNamesRector::class => [ + '$shouldImportRootNamespaceClasses' => false, + ], + ]; + } +} diff --git a/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php b/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php index c6df8894b14d..73dc30ffa445 100644 --- a/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php +++ b/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockManipulator.php @@ -345,14 +345,18 @@ public function replaceTagByAnother(PhpDocNode $phpDocNode, string $oldTag, stri } } - public function importNames(Node $node): void + public function importNames(Node $node, bool $shouldImportRootNamespaceClasses = true): void { if ($node->getDocComment() === null) { return; } $phpDocInfo = $this->createPhpDocInfoFromNode($node); - $hasNodeChanged = $this->docBlockNameImporter->importNames($phpDocInfo, $node); + $hasNodeChanged = $this->docBlockNameImporter->importNames( + $phpDocInfo, + $node, + $shouldImportRootNamespaceClasses + ); if ($hasNodeChanged) { $this->updateNodeWithPhpDocInfo($node, $phpDocInfo); diff --git a/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockNameImporter.php b/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockNameImporter.php index 926aa2b08f06..dea930b72d59 100644 --- a/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockNameImporter.php +++ b/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/DocBlockNameImporter.php @@ -77,12 +77,16 @@ public function __construct( $this->importSkipper = $importSkipper; } - public function importNames(PhpDocInfo $phpDocInfo, Node $phpParserNode): bool - { + public function importNames( + PhpDocInfo $phpDocInfo, + Node $phpParserNode, + bool $shouldImportRootNamespaceClasses = true + ): bool { $phpDocNode = $phpDocInfo->getPhpDocNode(); $this->phpDocNodeTraverser->traverseWithCallable($phpDocNode, function (PhpDocParserNode $docNode) use ( - $phpParserNode + $phpParserNode, + $shouldImportRootNamespaceClasses ): PhpDocParserNode { if (! $docNode instanceof IdentifierTypeNode) { return $docNode; @@ -93,6 +97,11 @@ public function importNames(PhpDocInfo $phpDocInfo, Node $phpParserNode): bool return $docNode; } + // Importing root namespace classes (like \DateTime) is optional + if (! $shouldImportRootNamespaceClasses && substr_count($staticType->getClassName(), '\\') === 0) { + return $docNode; + } + return $this->processFqnNameImport($phpParserNode, $docNode, $staticType); });