diff --git a/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/SharedShortName.php b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/SharedShortName.php new file mode 100644 index 000000000000..45d839b47c57 --- /dev/null +++ b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/SharedShortName.php @@ -0,0 +1,8 @@ + +----- + diff --git a/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/skip_same_namespaced_used_class.php.inc b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/skip_same_namespaced_used_class.php.inc new file mode 100644 index 000000000000..b2a6854d466d --- /dev/null +++ b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Fixture/skip_same_namespaced_used_class.php.inc @@ -0,0 +1,13 @@ +doTestFile($file); } - public function provideFunctions(): Iterator - { - yield [__DIR__ . '/Fixture/import_function.php.inc']; - yield [__DIR__ . '/Fixture/import_function_no_class.php.inc']; - yield [__DIR__ . '/Fixture/import_return_doc.php.inc']; - } - public function provideNamespacedClasses(): Iterator { + // same short class with namespace + yield [__DIR__ . '/Fixture/same_namespaced_class.php.inc']; + yield [__DIR__ . '/Fixture/skip_same_namespaced_used_class.php.inc']; + yield [__DIR__ . '/Fixture/fixture.php.inc']; yield [__DIR__ . '/Fixture/double_import.php.inc']; yield [__DIR__ . '/Fixture/double_import_with_existing.php.inc']; @@ -52,6 +49,13 @@ public function provideNamespacedClasses(): Iterator yield [__DIR__ . '/Fixture/instance_of.php.inc']; } + public function provideFunctions(): Iterator + { + yield [__DIR__ . '/Fixture/import_function.php.inc']; + yield [__DIR__ . '/Fixture/import_function_no_class.php.inc']; + yield [__DIR__ . '/Fixture/import_return_doc.php.inc']; + } + protected function getRectorClass(): string { return ImportFullyQualifiedNamesRector::class; diff --git a/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/SharedShortName.php b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/SharedShortName.php new file mode 100644 index 000000000000..9832f789b8e0 --- /dev/null +++ b/packages/CodingStyle/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/SharedShortName.php @@ -0,0 +1,8 @@ +phpDocInfoFactory = $phpDocInfoFactory; $this->phpDocInfoPrinter = $phpDocInfoPrinter; @@ -100,6 +120,8 @@ public function __construct( $this->stringsTypePhpDocNodeDecorator = $stringsTypePhpDocNodeDecorator; $this->nodeTraverser = $nodeTraverser; $this->useAddingCommander = $useAddingCommander; + $this->betterStandardPrinter = $betterStandardPrinter; + $this->nameResolver = $nameResolver; } public function hasTag(Node $node, string $name): bool @@ -689,9 +711,15 @@ private function processFqnNameImport( // the name is already in the same namespace implicitly $namespaceName = $node->getAttribute(AttributeKey::NAMESPACE_NAME); - // the class in the same namespace as differnt file can se used in this code, the short names would colide → skip + // the class in the same namespace as different file can se used in this code, the short names would colide → skip if (class_exists($namespaceName . '\\' . $shortName)) { - return $attributeAwareNode; + if ($this->isCurrentNamespaceSameShortClassAlreadyUsed( + $node, + $namespaceName . '\\' . $shortName, + $shortName + )) { + return $attributeAwareNode; + } } if ($this->useAddingCommander->isShortImported($node, $fullyQualifiedName)) { @@ -742,4 +770,38 @@ private function preslashFullyQualifiedNames($type): string return implode($joinChar, $types); } + + private function isCurrentNamespaceSameShortClassAlreadyUsed( + Node $node, + string $fullyQualifiedName, + string $shortName + ): bool { + /** @var ClassLike|null $classNode */ + $classNode = $node->getAttribute(AttributeKey::CLASS_NODE); + if ($classNode === null) { + // cannot say, so rather yes + return true; + } + + $className = $this->nameResolver->getName($classNode); + + if (isset($this->usedShortNameByClasses[$className][$shortName])) { + return $this->usedShortNameByClasses[$className][$shortName]; + } + + $printedClass = $this->betterStandardPrinter->print($classNode->stmts); + + // short with space " Type"| fqn + $shortNameOrFullyQualifiedNamePattern = sprintf( + '#(\s%s\b|\b%s\b)#', + preg_quote($shortName), + preg_quote($fullyQualifiedName) + ); + + $isShortClassUsed = (bool) Strings::match($printedClass, $shortNameOrFullyQualifiedNamePattern); + + $this->usedShortNameByClasses[$className][$shortName] = $isShortClassUsed; + + return $isShortClassUsed; + } } diff --git a/rector.yaml b/rector.yaml index 7abb46672bb1..16e58da7747f 100644 --- a/rector.yaml +++ b/rector.yaml @@ -13,4 +13,4 @@ parameters: php_version_features: '7.1' services: -# Rector\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector: ~ + Rector\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector: ~