@@ -32,14 +32,14 @@ final class CallableStringifierTest extends TestCase
3232 #[Test]
3333 public function itShouldNotStringifyWhenRawValueIsNotCallable (): void
3434 {
35- $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter ());
35+ $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter (), closureOnly: false );
3636
3737 self ::assertNull ($ sut ->stringify (1 , self ::DEPTH ));
3838 }
3939
4040 #[Test]
41- #[DataProvider('callableRawValuesProvider ' )]
42- public function itShouldStringifyWhenRawValueIsCallable (callable $ raw , string $ expectedWithoutQuotes ): void
41+ #[DataProvider('closureRawValuesProvider ' )]
42+ public function itShouldStringifyWhenRawValueIsClosure (callable $ raw , string $ expectedWithoutQuotes ): void
4343 {
4444 $ quoter = new FakeQuoter ();
4545
@@ -51,6 +51,31 @@ public function itShouldStringifyWhenRawValueIsCallable(callable $raw, string $e
5151 self ::assertEquals ($ expected , $ actual );
5252 }
5353
54+ #[Test]
55+ #[DataProvider('nonClosureCallableRawValuesProvider ' )]
56+ public function itShouldNotStringifyNonClosureCallableByDefault (callable $ raw , string $ useless ): void
57+ {
58+ $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter ());
59+
60+ self ::assertNull ($ sut ->stringify ($ raw , self ::DEPTH ));
61+ }
62+
63+ #[Test]
64+ #[DataProvider('nonClosureCallableRawValuesProvider ' )]
65+ public function itShouldStringifyNonClosureCallableWhenClosureOnlyIsFalse (
66+ callable $ raw ,
67+ string $ expectedWithoutQuotes ,
68+ ): void {
69+ $ quoter = new FakeQuoter ();
70+
71+ $ sut = new CallableStringifier (new FakeStringifier (), $ quoter , closureOnly: false );
72+
73+ $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
74+ $ expected = $ quoter ->quote ($ expectedWithoutQuotes , self ::DEPTH );
75+
76+ self ::assertEquals ($ expected , $ actual );
77+ }
78+
5479 #[Test]
5580 public function itShouldStringifyWhenRawValueIsCallableWithDefaultValues (): void
5681 {
@@ -63,7 +88,7 @@ public function itShouldStringifyWhenRawValueIsCallableWithDefaultValues(): void
6388
6489 $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
6590 $ expected = $ quoter ->quote (
66- sprintf ('function (int $value = %s): int ' , $ stringifier ->stringify (1 , self ::DEPTH + 1 )),
91+ sprintf ('Closure { static fn (int $value = %s): int } ' , $ stringifier ->stringify (1 , self ::DEPTH + 1 )),
6792 self ::DEPTH ,
6893 );
6994
@@ -77,7 +102,7 @@ public function itShouldStringifyWhenRawValueIsCallableThatDoesNotHaveAnAccessib
77102
78103 $ quoter = new FakeQuoter ();
79104
80- $ sut = new CallableStringifier (new FakeStringifier (), $ quoter );
105+ $ sut = new CallableStringifier (new FakeStringifier (), $ quoter, closureOnly: false );
81106
82107 $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
83108 $ expected = $ quoter ->quote (
@@ -88,40 +113,87 @@ public function itShouldStringifyWhenRawValueIsCallableThatDoesNotHaveAnAccessib
88113 self ::assertEquals ($ expected , $ actual );
89114 }
90115
91- /** @return array<int , array{0: callable, 1: string}> */
92- public static function callableRawValuesProvider (): array
116+ /** @return array<string , array{0: callable, 1: string}> */
117+ public static function closureRawValuesProvider (): array
93118 {
94119 $ var1 = 1 ;
95120 $ var2 = 2 ;
96121
97122 return [
98- [static fn () => 1 , 'function () ' ],
99- [static fn (): int => 1 , 'function (): int ' ],
100- [static fn (float $ value ): int => (int ) $ value , 'function (float $value): int ' ],
101- [static fn (float &$ value ): int => (int ) $ value , 'function (float &$value): int ' ],
102- // phpcs:ignore SlevomatCodingStandard.TypeHints.DNFTypeHintFormat
103- [static fn (?float $ value ): int => (int ) $ value , 'function (?float $value): int ' ],
104- [static fn (int $ value = self ::DEPTH ): int => $ value , 'function (int $value = self::DEPTH): int ' ],
105- [static fn (int |float $ value ): int => (int ) $ value , 'function (int|float $value): int ' ],
106- [static fn (Countable &Iterator $ value ): int => $ value ->count (), 'function (Countable&Iterator $value): int ' ],
107- [static fn (int ...$ value ): int => array_sum ($ value ), 'function (int ...$value): int ' ],
108- [
123+ 'static closure without parameters ' => [
124+ static fn () => 1 ,
125+ 'Closure { static fn() } ' ,
126+ ],
127+ 'non-static closure without parameters ' => [
128+ fn () => 1 ,
129+ 'Closure { fn() } ' ,
130+ ],
131+ 'static closure with return type ' => [
132+ static fn (): int => 1 ,
133+ 'Closure { static fn(): int } ' ,
134+ ],
135+ 'non-static closure with return type ' => [
136+ fn (): int => 1 ,
137+ 'Closure { fn(): int } ' ,
138+ ],
139+ 'static closure with typed parameter ' => [
140+ static fn (float $ value ): int => (int ) $ value ,
141+ 'Closure { static fn(float $value): int } ' ,
142+ ],
143+ 'static closure with reference parameter ' => [
144+ static fn (float &$ value ): int => (int ) $ value ,
145+ 'Closure { static fn(float &$value): int } ' ,
146+ ],
147+ 'static closure with nullable parameter ' => [
148+ static fn (float |null $ value ): int => (int ) $ value ,
149+ 'Closure { static fn(?float $value): int } ' ,
150+ ],
151+ 'static closure with constant default value ' => [
152+ static fn (int $ value = self ::DEPTH ): int => $ value ,
153+ 'Closure { static fn(int $value = self::DEPTH): int } ' ,
154+ ],
155+ 'static closure with union type parameter ' => [
156+ static fn (int |float $ value ): int => (int ) $ value ,
157+ 'Closure { static fn(int|float $value): int } ' ,
158+ ],
159+ 'static closure with intersection type parameter ' => [
160+ static fn (Countable &Iterator $ value ): int => $ value ->count (),
161+ 'Closure { static fn(Countable&Iterator $value): int } ' ,
162+ ],
163+ 'static closure with variadic parameter ' => [
164+ static fn (int ...$ value ): int => array_sum ($ value ),
165+ 'Closure { static fn(int ...$value): int } ' ,
166+ ],
167+ 'static closure with multiple parameters ' => [
109168 static fn (float $ value1 , float $ value2 ): float => $ value1 + $ value2 ,
110- 'function (float $value1, float $value2): float ' ,
169+ 'Closure { static fn (float $value1, float $value2): float } ' ,
111170 ],
112- [
171+ ' static closure with single use variable ' => [
113172 static function (int $ value ) use ($ var1 ): int {
114173 return $ value + $ var1 ;
115174 },
116- 'function (int $value) use ($var1): int ' ,
175+ 'Closure { static fn (int $value) use ($var1): int } ' ,
117176 ],
118- [
177+ ' static closure with multiple use variables ' => [
119178 static function (int $ value ) use ($ var1 , $ var2 ): int {
120179 return $ value + $ var1 + $ var2 ;
121180 },
122- 'function (int $value) use ($var1, $var2): int ' ,
181+ 'Closure { static fn (int $value) use ($var1, $var2): int } ' ,
123182 ],
124- [
183+ 'non-static closure with use variable ' => [
184+ function (int $ value ) use ($ var1 ): int {
185+ return $ value + $ var1 ;
186+ },
187+ 'Closure { fn(int $value) use ($var1): int } ' ,
188+ ],
189+ ];
190+ }
191+
192+ /** @return array<string, array{0: callable, 1: string}> */
193+ public static function nonClosureCallableRawValuesProvider (): array
194+ {
195+ return [
196+ 'invokable object ' => [
125197 new class {
126198 public function __invoke (int $ parameter ): never
127199 {
@@ -130,19 +202,22 @@ public function __invoke(int $parameter): never
130202 },
131203 'class->__invoke(int $parameter): never ' ,
132204 ],
133- [
205+ ' object method as array ' => [
134206 [new DateTime (), 'format ' ],
135207 'DateTime->format(string $format) ' ,
136208 ],
137- [
209+ ' static method as array ' => [
138210 ['DateTime ' , 'createFromImmutable ' ],
139211 'DateTime::createFromImmutable(DateTimeImmutable $object) ' ,
140212 ],
141- [
213+ ' static method as string ' => [
142214 'DateTimeImmutable::getLastErrors ' ,
143215 'DateTimeImmutable::getLastErrors() ' ,
144216 ],
145- ['chr ' , 'chr(int $codepoint): string ' ],
217+ 'function name as string ' => [
218+ 'chr ' ,
219+ 'chr(int $codepoint): string ' ,
220+ ],
146221 ];
147222 }
148223}
0 commit comments