|
5 | 5 |
|
6 | 6 | use PhpParser\Node; |
7 | 7 | use PhpParser\Node\Expr\ClassConstFetch; |
8 | | -use PhpParser\Node\Identifier; |
9 | | -use PhpParser\Node\Name; |
10 | 8 | use PhpParser\Node\Stmt\Enum_; |
11 | | -use PhpParser\Node\Stmt\EnumCase; |
12 | | -use PHPStan\BetterReflection\Reflector\DefaultReflector; |
13 | | -use PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound; |
14 | | -use PHPStan\Reflection\ClassReflection; |
15 | | -use Rector\Configuration\Option; |
16 | | -use Rector\Configuration\Parameter\SimpleParameterProvider; |
17 | | -use Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocatorProvider\DynamicSourceLocatorProvider; |
| 9 | +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; |
| 10 | +use Rector\Exception\ShouldNotHappenException; |
18 | 11 | use Rector\Rector\AbstractRector; |
19 | | -use Rector\Skipper\FileSystem\PathNormalizer; |
20 | 12 | use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; |
21 | 13 | use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; |
22 | 14 | /** |
23 | | - * @see \Rector\Tests\CodingStyle\Rector\Enum_\EnumCaseToPascalCaseRector\EnumCaseToPascalCaseRectorTest |
24 | | - * @see \Rector\Tests\CodingStyle\Rector\Enum_\EnumCaseToPascalCaseRector\WithAutoloadPathsTest |
| 15 | + * @deprecated as risky change that does not handle enum usage across the whole context. Handle it via IDE with full context, manually, or a custom rule instead. |
25 | 16 | */ |
26 | | -final class EnumCaseToPascalCaseRector extends AbstractRector |
| 17 | +final class EnumCaseToPascalCaseRector extends AbstractRector implements DeprecatedInterface |
27 | 18 | { |
28 | | - /** |
29 | | - * @readonly |
30 | | - */ |
31 | | - private DynamicSourceLocatorProvider $dynamicSourceLocatorProvider; |
32 | | - public function __construct(DynamicSourceLocatorProvider $dynamicSourceLocatorProvider) |
33 | | - { |
34 | | - $this->dynamicSourceLocatorProvider = $dynamicSourceLocatorProvider; |
35 | | - } |
36 | 19 | public function getRuleDefinition(): RuleDefinition |
37 | 20 | { |
38 | 21 | return new RuleDefinition('Convert enum cases to PascalCase and update their usages', [new CodeSample(<<<'CODE_SAMPLE' |
@@ -64,104 +47,6 @@ public function getNodeTypes(): array |
64 | 47 | */ |
65 | 48 | public function refactor(Node $node): ?Node |
66 | 49 | { |
67 | | - if ($node instanceof Enum_) { |
68 | | - return $this->refactorEnum($node); |
69 | | - } |
70 | | - if ($node instanceof ClassConstFetch) { |
71 | | - return $this->refactorClassConstFetch($node); |
72 | | - } |
73 | | - return null; |
74 | | - } |
75 | | - public function refactorEnum(Enum_ $enum): ?\PhpParser\Node\Stmt\Enum_ |
76 | | - { |
77 | | - $enumName = $this->getName($enum); |
78 | | - if ($enumName === null) { |
79 | | - return null; |
80 | | - } |
81 | | - $hasChanged = \false; |
82 | | - foreach ($enum->stmts as $stmt) { |
83 | | - if (!$stmt instanceof EnumCase) { |
84 | | - continue; |
85 | | - } |
86 | | - $currentName = $stmt->name->toString(); |
87 | | - $pascalCaseName = $this->convertToPascalCase($currentName); |
88 | | - if ($currentName === $pascalCaseName) { |
89 | | - continue; |
90 | | - } |
91 | | - $stmt->name = new Identifier($pascalCaseName); |
92 | | - $hasChanged = \true; |
93 | | - } |
94 | | - return $hasChanged ? $enum : null; |
95 | | - } |
96 | | - private function refactorClassConstFetch(ClassConstFetch $classConstFetch): ?Node |
97 | | - { |
98 | | - if (!$classConstFetch->class instanceof Name) { |
99 | | - return null; |
100 | | - } |
101 | | - if (!$classConstFetch->name instanceof Identifier) { |
102 | | - return null; |
103 | | - } |
104 | | - $constName = $classConstFetch->name->toString(); |
105 | | - $pascalCaseName = $this->convertToPascalCase($constName); |
106 | | - // short circuit if already in pascal case |
107 | | - if ($constName === $pascalCaseName) { |
108 | | - return null; |
109 | | - } |
110 | | - $classReflection = $this->nodeTypeResolver->getType($classConstFetch->class)->getObjectClassReflections()[0] ?? null; |
111 | | - if ($classReflection === null || !$classReflection->isEnum()) { |
112 | | - return null; |
113 | | - } |
114 | | - if (!$this->isEnumCase($classReflection, $constName, $pascalCaseName)) { |
115 | | - return null; |
116 | | - } |
117 | | - if ($this->isUsedOutsideOfProject($classConstFetch->class)) { |
118 | | - return null; |
119 | | - } |
120 | | - $classConstFetch->name = new Identifier($pascalCaseName); |
121 | | - return $classConstFetch; |
122 | | - } |
123 | | - private function isUsedOutsideOfProject(Name $name): bool |
124 | | - { |
125 | | - if (in_array($name->toString(), ['self', 'static'], \true)) { |
126 | | - return \false; |
127 | | - } |
128 | | - $sourceLocator = $this->dynamicSourceLocatorProvider->provide(); |
129 | | - $defaultReflector = new DefaultReflector($sourceLocator); |
130 | | - try { |
131 | | - $classIdentifier = $defaultReflector->reflectClass($name->toString()); |
132 | | - } catch (IdentifierNotFound $exception) { |
133 | | - // source is outside the paths defined in withPaths(), eg: vendor |
134 | | - return \true; |
135 | | - } |
136 | | - $fileTarget = $classIdentifier->getFileName(); |
137 | | - // possibly native |
138 | | - if ($fileTarget === null) { |
139 | | - return \true; |
140 | | - } |
141 | | - $autoloadPaths = SimpleParameterProvider::provideArrayParameter(Option::AUTOLOAD_PATHS); |
142 | | - $normalizedFileTarget = PathNormalizer::normalize((string) realpath($fileTarget)); |
143 | | - foreach ($autoloadPaths as $autoloadPath) { |
144 | | - $normalizedAutoloadPath = PathNormalizer::normalize($autoloadPath); |
145 | | - if ($autoloadPath === $fileTarget) { |
146 | | - return \true; |
147 | | - } |
148 | | - if (strncmp($normalizedFileTarget, $normalizedAutoloadPath . '/', strlen($normalizedAutoloadPath . '/')) === 0) { |
149 | | - return \true; |
150 | | - } |
151 | | - } |
152 | | - return \false; |
153 | | - } |
154 | | - private function isEnumCase(ClassReflection $classReflection, string $name, string $pascalName): bool |
155 | | - { |
156 | | - // the enum case might have already been renamed, need to check both |
157 | | - if ($classReflection->hasEnumCase($name)) { |
158 | | - return \true; |
159 | | - } |
160 | | - return $classReflection->hasEnumCase($pascalName); |
161 | | - } |
162 | | - private function convertToPascalCase(string $name): string |
163 | | - { |
164 | | - $parts = explode('_', $name); |
165 | | - return implode('', array_map(fn($part): string => ctype_upper($part) ? ucfirst(strtolower($part)) : ucfirst($part), $parts)); |
| 50 | + throw new ShouldNotHappenException(sprintf('"%s" is deprecated as risky change that does not handle enum usage across the whole context. Handle it via IDE with full context, manually, or a custom rule instead', self::class)); |
166 | 51 | } |
167 | 52 | } |
0 commit comments