4
4
5
5
namespace Rector \CodingStyle \Rector \Enum_ ;
6
6
7
+ use PHPStan \Reflection \ClassReflection ;
7
8
use PhpParser \Node ;
8
9
use PhpParser \Node \Expr \ClassConstFetch ;
9
10
use PhpParser \Node \Identifier ;
10
11
use PhpParser \Node \Name ;
11
12
use PhpParser \Node \Stmt \Enum_ ;
12
13
use PhpParser \Node \Stmt \EnumCase ;
13
- use PHPStan \BetterReflection \Reflection \ReflectionEnum ;
14
- use PHPStan \BetterReflection \Reflector \DefaultReflector ;
15
- use PHPStan \BetterReflection \Reflector \Exception \IdentifierNotFound ;
16
- use PHPStan \Reflection \ReflectionProvider ;
17
14
use Rector \Configuration \Option ;
18
15
use Rector \Configuration \Parameter \SimpleParameterProvider ;
19
- use Rector \NodeTypeResolver \Reflection \BetterReflection \SourceLocatorProvider \DynamicSourceLocatorProvider ;
20
16
use Rector \Rector \AbstractRector ;
21
17
use Rector \Skipper \FileSystem \PathNormalizer ;
22
18
use Symplify \RuleDocGenerator \ValueObject \CodeSample \CodeSample ;
27
23
*/
28
24
final class EnumCaseToPascalCaseRector extends AbstractRector
29
25
{
30
- public function __construct (
31
- private readonly ReflectionProvider $ reflectionProvider ,
32
- private readonly DynamicSourceLocatorProvider $ dynamicSourceLocatorProvider ,
33
- ) {
34
- }
35
-
36
26
public function getRuleDefinition (): RuleDefinition
37
27
{
38
28
return new RuleDefinition (
@@ -122,43 +112,40 @@ private function refactorClassConstFetch(ClassConstFetch $classConstFetch): ?Nod
122
112
return null ;
123
113
}
124
114
125
- if ($ this ->nodeTypeResolver ->getType ($ classConstFetch ->class )->isEnum ()->no ()) {
126
- return null ;
127
- }
128
-
129
115
$ constName = $ classConstFetch ->name ->toString ();
116
+ $ pascalCaseName = $ this ->convertToPascalCase ($ constName );
130
117
131
- // Skip "class" constant
132
- if ($ constName === ' class ' ) {
118
+ // short circuit if already in pascal case
119
+ if ($ constName === $ pascalCaseName ) {
133
120
return null ;
134
121
}
135
122
136
- $ enumClassName = $ classConstFetch ->class ->toString ();
137
- if (! $ this ->reflectionProvider ->hasClass ($ enumClassName )) {
123
+ $ classReflection = $ this ->nodeTypeResolver ->getType ($ classConstFetch ->class )
124
+ ->getObjectClassReflections ()[0 ] ?? null ;
125
+
126
+ if ($ classReflection === null || ! $ classReflection ->isEnum ()) {
138
127
return null ;
139
128
}
140
129
141
- $ sourceLocator = $ this ->dynamicSourceLocatorProvider ->provide ();
142
- $ defaultReflector = new DefaultReflector ($ sourceLocator );
143
-
144
- try {
145
- $ classIdentifier = $ defaultReflector ->reflectClass ($ classConstFetch ->class ->toString ());
146
- } catch (IdentifierNotFound ) {
147
- // source is outside the paths defined in withPaths(), eg: vendor
130
+ if (! $ this ->isEnumCase ($ classReflection , $ constName , $ pascalCaseName )) {
148
131
return null ;
149
132
}
150
133
151
- // ensure exactly ReflectionEnum
152
- if (! $ classIdentifier instanceof ReflectionEnum) {
134
+ if ($ this ->isUsedOutsideOfProject ($ classReflection )) {
153
135
return null ;
154
136
}
155
137
156
- // ensure not part of definition in ->withAutoloadPaths()
157
- $ fileTarget = $ classIdentifier ->getFileName ();
138
+ $ classConstFetch ->name = new Identifier ($ pascalCaseName );
139
+ return $ classConstFetch ;
140
+ }
141
+
142
+ private function isUsedOutsideOfProject (ClassReflection $ classReflection ): bool
143
+ {
144
+ $ fileTarget = $ classReflection ->getFileName ();
158
145
159
146
// possibly native
160
147
if ($ fileTarget === null ) {
161
- return null ;
148
+ return true ;
162
149
}
163
150
164
151
$ autoloadPaths = SimpleParameterProvider::provideArrayParameter (Option::AUTOLOAD_PATHS );
@@ -168,21 +155,21 @@ private function refactorClassConstFetch(ClassConstFetch $classConstFetch): ?Nod
168
155
$ normalizedAutoloadPath = PathNormalizer::normalize ($ autoloadPath );
169
156
170
157
if ($ autoloadPath === $ fileTarget ) {
171
- return null ;
158
+ return true ;
172
159
}
173
160
174
161
if (str_starts_with ($ normalizedFileTarget , $ normalizedAutoloadPath . '/ ' )) {
175
- return null ;
162
+ return true ;
176
163
}
177
164
}
178
165
179
- $ pascalCaseName = $ this ->convertToPascalCase ($ constName );
180
- if ($ constName !== $ pascalCaseName ) {
181
- $ classConstFetch ->name = new Identifier ($ pascalCaseName );
182
- return $ classConstFetch ;
183
- }
166
+ return false ;
167
+ }
184
168
185
- return null ;
169
+ private function isEnumCase (ClassReflection $ classReflection , string $ name , string $ pascalName ): bool
170
+ {
171
+ // the enum case might have already been renamed, need to check both
172
+ return $ classReflection ->hasEnumCase ($ name ) || $ classReflection ->hasEnumCase ($ pascalName );
186
173
}
187
174
188
175
private function convertToPascalCase (string $ name ): string
0 commit comments