99
1010/**
1111 * @internal
12+ * @readonly
1213 */
1314class ClassAttributeCollector
1415{
@@ -24,6 +25,7 @@ public function __construct(
2425 * array<TransientTargetClass>,
2526 * array<TransientTargetMethod>,
2627 * array<TransientTargetProperty>,
28+ * array<TransientTargetParameter>,
2729 * }
2830 *
2931 * @throws ReflectionException
@@ -33,7 +35,7 @@ public function collectAttributes(string $class): array
3335 $ classReflection = new ReflectionClass ($ class );
3436
3537 if (self ::isAttribute ($ classReflection )) {
36- return [ [], [], [] ];
38+ return [ [], [], [], [] ];
3739 }
3840
3941 $ classAttributes = [];
@@ -52,24 +54,18 @@ public function collectAttributes(string $class): array
5254 );
5355 }
5456
57+ /** @var array<TransientTargetMethod> $methodAttributes */
5558 $ methodAttributes = [];
59+ /** @var array<TransientTargetParameter> $parameterAttributes */
60+ $ parameterAttributes = [];
5661
5762 foreach ($ classReflection ->getMethods () as $ methodReflection ) {
58- foreach ($ methodReflection ->getAttributes () as $ attribute ) {
59- if (self ::isAttributeIgnored ($ attribute )) {
60- continue ;
61- }
62-
63- $ method = $ methodReflection ->name ;
64-
65- $ this ->log ->debug ("Found attribute {$ attribute ->getName ()} on $ class:: $ method " );
66-
67- $ methodAttributes [] = new TransientTargetMethod (
68- $ attribute ->getName (),
69- $ attribute ->getArguments (),
70- $ method ,
71- );
72- }
63+ $ this ->collectMethodAndParameterAttributes (
64+ $ class ,
65+ $ methodReflection ,
66+ $ methodAttributes ,
67+ $ parameterAttributes ,
68+ );
7369 }
7470
7571 $ propertyAttributes = [];
@@ -93,7 +89,7 @@ public function collectAttributes(string $class): array
9389 }
9490 }
9591
96- return [ $ classAttributes , $ methodAttributes , $ propertyAttributes ];
92+ return [ $ classAttributes , $ methodAttributes , $ propertyAttributes, $ parameterAttributes ];
9793 }
9894
9995 /**
@@ -119,8 +115,75 @@ private static function isAttributeIgnored(ReflectionAttribute $attribute): bool
119115 {
120116 static $ ignored = [
121117 \ReturnTypeWillChange::class => true ,
118+ \SensitiveParameter::class => true ,
122119 ];
123120
124121 return isset ($ ignored [$ attribute ->getName ()]); // @phpstan-ignore offsetAccess.nonOffsetAccessible
125122 }
123+
124+ /**
125+ * @param array<TransientTargetMethod> $methodAttributes
126+ * @param array<TransientTargetParameter> $parameterAttributes
127+ */
128+ private function collectMethodAndParameterAttributes (
129+ string $ class ,
130+ \ReflectionMethod $ methodReflection ,
131+ array &$ methodAttributes ,
132+ array &$ parameterAttributes ,
133+ ): void {
134+ foreach ($ methodReflection ->getAttributes () as $ attribute ) {
135+ if (self ::isAttributeIgnored ($ attribute )) {
136+ continue ;
137+ }
138+
139+ $ method = $ methodReflection ->name ;
140+
141+ $ this ->log ->debug ("Found attribute {$ attribute ->getName ()} on $ class:: $ method " );
142+
143+ $ methodAttributes [] = new TransientTargetMethod (
144+ $ attribute ->getName (),
145+ $ attribute ->getArguments (),
146+ $ method ,
147+ );
148+ }
149+
150+ $ parameterAttributes = array_merge (
151+ $ parameterAttributes ,
152+ $ this ->collectParameterAttributes ($ methodReflection ),
153+ );
154+ }
155+
156+ /**
157+ * @return array<TransientTargetParameter>
158+ */
159+ private function collectParameterAttributes (\ReflectionMethod $ reflectionFunctionAbstract ): array
160+ {
161+ $ targets = [];
162+ $ class = $ reflectionFunctionAbstract ->class ;
163+ $ method = $ reflectionFunctionAbstract ->name ;
164+
165+ foreach ($ reflectionFunctionAbstract ->getParameters () as $ parameter ) {
166+ /** @var non-empty-string $name */
167+ $ name = $ parameter ->name ;
168+
169+ $ paramLabel = $ class . ':: ' . $ method . '( ' . $ name . ') ' ;
170+
171+ foreach ($ parameter ->getAttributes () as $ attribute ) {
172+ if (self ::isAttributeIgnored ($ attribute )) {
173+ continue ;
174+ }
175+
176+ $ this ->log ->debug ("Found attribute {$ attribute ->getName ()} on $ paramLabel " );
177+
178+ $ targets [] = new TransientTargetParameter (
179+ $ attribute ->getName (),
180+ $ attribute ->getArguments (),
181+ $ method ,
182+ $ name
183+ );
184+ }
185+ }
186+
187+ return $ targets ;
188+ }
126189}
0 commit comments