@@ -44,33 +44,73 @@ public function processNode(Node $node, Scope $scope): array
4444 }
4545
4646 $ classReflection = $ scope ->getClassReflection ();
47- $ traitConstants = [];
47+ $ recursiveTraitConstants = [];
4848 foreach ($ classReflection ->getTraits (true ) as $ trait ) {
4949 foreach ($ trait ->getNativeReflection ()->getReflectionConstants () as $ constant ) {
50- $ traitConstants [] = $ constant ;
50+ $ recursiveTraitConstants [] = $ constant ;
5151 }
5252 }
5353
5454 $ errors = [];
5555 foreach ($ node ->consts as $ const ) {
56- foreach ($ traitConstants as $ traitConstant ) {
57- if ($ traitConstant ->getName () !== $ const ->name ->toString ()) {
56+ foreach ($ recursiveTraitConstants as $ recursiveTraitConstant ) {
57+ if ($ recursiveTraitConstant ->getName () !== $ const ->name ->toString ()) {
5858 continue ;
5959 }
6060
61- foreach ($ this ->processSingleConstant ($ classReflection , $ traitConstant , $ node, $ const -> value ) as $ error ) {
61+ foreach ($ this ->processSingleConstant ($ classReflection , $ recursiveTraitConstant , $ node ) as $ error ) {
6262 $ errors [] = $ error ;
6363 }
6464 }
6565 }
6666
67+ $ immediateTraitConstants = [];
68+ foreach ($ classReflection ->getTraits () as $ trait ) {
69+ foreach ($ trait ->getNativeReflection ()->getReflectionConstants () as $ constant ) {
70+ $ immediateTraitConstants [] = $ constant ;
71+ }
72+ }
73+
74+ foreach ($ node ->consts as $ const ) {
75+ foreach ($ immediateTraitConstants as $ immediateTraitConstant ) {
76+ if ($ immediateTraitConstant ->getName () !== $ const ->name ->toString ()) {
77+ continue ;
78+ }
79+
80+ $ classConstantValueType = $ this ->initializerExprTypeResolver ->getType ($ const ->value , InitializerExprContext::fromClassReflection ($ classReflection ));
81+ $ traitConstantValueType = $ this ->initializerExprTypeResolver ->getType (
82+ $ immediateTraitConstant ->getValueExpression (),
83+ InitializerExprContext::fromClass (
84+ $ immediateTraitConstant ->getDeclaringClass ()->getName (),
85+ $ immediateTraitConstant ->getDeclaringClass ()->getFileName () !== false ? $ immediateTraitConstant ->getDeclaringClass ()->getFileName () : null ,
86+ ),
87+ );
88+ if ($ classConstantValueType ->equals ($ traitConstantValueType )) {
89+ continue ;
90+ }
91+
92+ $ errors [] = RuleErrorBuilder::message (sprintf (
93+ 'Constant %s::%s with value %s overriding constant %s::%s with different value %s should have the same value. ' ,
94+ $ classReflection ->getDisplayName (),
95+ $ immediateTraitConstant ->getName (),
96+ $ classConstantValueType ->describe (VerbosityLevel::value ()),
97+ $ immediateTraitConstant ->getDeclaringClass ()->getName (),
98+ $ immediateTraitConstant ->getName (),
99+ $ traitConstantValueType ->describe (VerbosityLevel::value ()),
100+ ))
101+ ->nonIgnorable ()
102+ ->identifier ('classConstant.value ' )
103+ ->build ();
104+ }
105+ }
106+
67107 return $ errors ;
68108 }
69109
70110 /**
71111 * @return list<IdentifierRuleError>
72112 */
73- private function processSingleConstant (ClassReflection $ classReflection , ReflectionClassConstant $ traitConstant , Node \Stmt \ClassConst $ classConst, Node \ Expr $ valueExpr ): array
113+ private function processSingleConstant (ClassReflection $ classReflection , ReflectionClassConstant $ traitConstant , Node \Stmt \ClassConst $ classConst ): array
74114 {
75115 $ errors = [];
76116 if ($ traitConstant ->isPublic ()) {
@@ -225,29 +265,6 @@ private function processSingleConstant(ClassReflection $classReflection, Reflect
225265 }
226266 }
227267
228- $ classConstantValueType = $ this ->initializerExprTypeResolver ->getType ($ valueExpr , InitializerExprContext::fromClassReflection ($ classReflection ));
229- $ traitConstantValueType = $ this ->initializerExprTypeResolver ->getType (
230- $ traitConstant ->getValueExpression (),
231- InitializerExprContext::fromClass (
232- $ traitDeclaringClass ->getName (),
233- $ traitDeclaringClass ->getFileName () !== false ? $ traitDeclaringClass ->getFileName () : null ,
234- ),
235- );
236- if (!$ classConstantValueType ->equals ($ traitConstantValueType )) {
237- $ errors [] = RuleErrorBuilder::message (sprintf (
238- 'Constant %s::%s with value %s overriding constant %s::%s with different value %s should have the same value. ' ,
239- $ classReflection ->getDisplayName (),
240- $ traitConstant ->getName (),
241- $ classConstantValueType ->describe (VerbosityLevel::value ()),
242- $ traitConstant ->getDeclaringClass ()->getName (),
243- $ traitConstant ->getName (),
244- $ traitConstantValueType ->describe (VerbosityLevel::value ()),
245- ))
246- ->nonIgnorable ()
247- ->identifier ('classConstant.value ' )
248- ->build ();
249- }
250-
251268 return $ errors ;
252269 }
253270
0 commit comments