diff --git a/rules-tests/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector/Fixture/case_on_self.php.inc b/rules-tests/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector/Fixture/case_on_self.php.inc new file mode 100644 index 00000000000..e07d8d31f14 --- /dev/null +++ b/rules-tests/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector/Fixture/case_on_self.php.inc @@ -0,0 +1,31 @@ + +----- + diff --git a/rules-tests/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector/Fixture/skip_enum_const.php.inc b/rules-tests/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector/Fixture/skip_enum_const.php.inc new file mode 100644 index 00000000000..cebfb93ff2c --- /dev/null +++ b/rules-tests/CodingStyle/Rector/Enum_/EnumCaseToPascalCaseRector/Fixture/skip_enum_const.php.inc @@ -0,0 +1,15 @@ +nodeTypeResolver->getType($classConstFetch->class)->isEnum()->no()) { + $constName = $classConstFetch->name->toString(); + $pascalCaseName = $this->convertToPascalCase($constName); + + // short circuit if already in pascal case + if ($constName === $pascalCaseName) { return null; } - $constName = $classConstFetch->name->toString(); + $classReflection = $this->nodeTypeResolver->getType($classConstFetch->class) + ->getObjectClassReflections()[0] ?? null; + + if ($classReflection === null || ! $classReflection->isEnum()) { + return null; + } - // Skip "class" constant - if ($constName === 'class') { + if (! $this->isEnumCase($classReflection, $constName, $pascalCaseName)) { return null; } - $enumClassName = $classConstFetch->class->toString(); - if (! $this->reflectionProvider->hasClass($enumClassName)) { + if ($this->isUsedOutsideOfProject($classConstFetch->class)) { return null; } + $classConstFetch->name = new Identifier($pascalCaseName); + return $classConstFetch; + } + + private function isUsedOutsideOfProject(Name $name): bool + { + if (in_array($name->toString(), ['self', 'static'], true)) { + return false; + } + $sourceLocator = $this->dynamicSourceLocatorProvider->provide(); $defaultReflector = new DefaultReflector($sourceLocator); try { - $classIdentifier = $defaultReflector->reflectClass($classConstFetch->class->toString()); + $classIdentifier = $defaultReflector->reflectClass($name->toString()); } catch (IdentifierNotFound) { // source is outside the paths defined in withPaths(), eg: vendor - return null; - } - - // ensure exactly ReflectionEnum - if (! $classIdentifier instanceof ReflectionEnum) { - return null; + return true; } - // ensure not part of definition in ->withAutoloadPaths() $fileTarget = $classIdentifier->getFileName(); // possibly native if ($fileTarget === null) { - return null; + return true; } $autoloadPaths = SimpleParameterProvider::provideArrayParameter(Option::AUTOLOAD_PATHS); @@ -168,21 +178,21 @@ private function refactorClassConstFetch(ClassConstFetch $classConstFetch): ?Nod $normalizedAutoloadPath = PathNormalizer::normalize($autoloadPath); if ($autoloadPath === $fileTarget) { - return null; + return true; } if (str_starts_with($normalizedFileTarget, $normalizedAutoloadPath . '/')) { - return null; + return true; } } - $pascalCaseName = $this->convertToPascalCase($constName); - if ($constName !== $pascalCaseName) { - $classConstFetch->name = new Identifier($pascalCaseName); - return $classConstFetch; - } + return false; + } - return null; + private function isEnumCase(ClassReflection $classReflection, string $name, string $pascalName): bool + { + // the enum case might have already been renamed, need to check both + return $classReflection->hasEnumCase($name) || $classReflection->hasEnumCase($pascalName); } private function convertToPascalCase(string $name): string