@@ -42,6 +42,8 @@ public function __construct(
4242 private bool $ checkDynamicProperties ,
4343 #[AutowiredParameter(ref: '%featureToggles.checkNonStringableDynamicAccess% ' )]
4444 private bool $ checkNonStringableDynamicAccess ,
45+ #[AutowiredParameter]
46+ private bool $ checkThisOnly ,
4547 )
4648 {
4749 }
@@ -58,20 +60,7 @@ public function check(PropertyFetch $node, Scope $scope, bool $write): array
5860 $ names = array_map (static fn (ConstantStringType $ type ): string => $ type ->getValue (), $ scope ->getType ($ node ->name )->getConstantStrings ());
5961
6062 if (!$ write && $ this ->checkNonStringableDynamicAccess ) {
61- $ nameTypeResult = $ this ->ruleLevelHelper ->findTypeToCheck (
62- $ scope ,
63- $ node ->name ,
64- '' ,
65- static fn (Type $ type ) => $ type ->toString ()->isString ()->yes (),
66- );
67- $ nameType = $ nameTypeResult ->getType ();
68- if ($ nameType instanceof ErrorType || $ nameType ->toString () instanceof ErrorType || !$ nameType ->toString ()->isString ()->yes ()) {
69- $ originalNameType = $ scope ->getType ($ node ->name );
70- $ className = $ scope ->getType ($ node ->var )->describe (VerbosityLevel::typeOnly ());
71- $ errors [] = RuleErrorBuilder::message (sprintf ('Property name for %s must be a string, but %s was given. ' , $ className , $ originalNameType ->describe (VerbosityLevel::precise ())))
72- ->identifier ('property.nameNotString ' )
73- ->build ();
74- }
63+ $ errors = array_merge ($ errors , $ this ->checkNonStringableDynamicAccess ($ scope , $ node ->var , $ node ->name ));
7564 }
7665 }
7766
@@ -82,6 +71,44 @@ public function check(PropertyFetch $node, Scope $scope, bool $write): array
8271 return $ errors ;
8372 }
8473
74+ /**
75+ * @return list<IdentifierRuleError>
76+ */
77+ private function checkNonStringableDynamicAccess (Scope $ scope , Expr $ nodeVar , Expr $ nodeName ): array
78+ {
79+ if (
80+ $ this ->checkThisOnly
81+ && !$ this ->ruleLevelHelper ->isThis ($ nodeVar )
82+ ) {
83+ return [];
84+ }
85+
86+ $ nameTypeResult = $ this ->ruleLevelHelper ->findTypeToCheck (
87+ $ scope ,
88+ $ nodeName ,
89+ '' ,
90+ static fn (Type $ type ) => $ type ->toString ()->isString ()->yes (),
91+ );
92+ $ nameType = $ nameTypeResult ->getType ();
93+ if (
94+ !$ nameType instanceof ErrorType
95+ && !$ nameType ->toString () instanceof ErrorType
96+ && $ nameType ->toString ()->isString ()->yes ()
97+ ) {
98+ return [];
99+ }
100+
101+ $ originalNameType = $ scope ->getType ($ nodeName );
102+ $ className = $ scope ->getType ($ nodeVar )->describe (VerbosityLevel::typeOnly ());
103+ return [
104+ RuleErrorBuilder::message (sprintf (
105+ 'Property name for %s must be a string, but %s was given. ' ,
106+ $ className ,
107+ $ originalNameType ->describe (VerbosityLevel::precise ()),
108+ ))->identifier ('property.nameNotString ' )->build (),
109+ ];
110+ }
111+
85112 /**
86113 * @return list<IdentifierRuleError>
87114 */
0 commit comments