2525use function array_sum ;
2626use function sprintf ;
2727
28- use const PHP_MAJOR_VERSION ;
29- use const PHP_MINOR_VERSION ;
30-
3128#[CoversClass(ObjectHelper::class)]
3229#[CoversClass(CallableStringifier::class)]
3330final class CallableStringifierTest extends TestCase
@@ -37,14 +34,14 @@ final class CallableStringifierTest extends TestCase
3734 #[Test]
3835 public function itShouldNotStringifyWhenRawValueIsNotCallable (): void
3936 {
40- $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter ());
37+ $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter (), closureOnly: false );
4138
4239 self ::assertNull ($ sut ->stringify (1 , self ::DEPTH ));
4340 }
4441
4542 #[Test]
46- #[DataProvider('callableRawValuesProvider ' )]
47- public function itShouldStringifyWhenRawValueIsCallable (callable $ raw , string $ expectedWithoutQuotes ): void
43+ #[DataProvider('closureRawValuesProvider ' )]
44+ public function itShouldStringifyWhenRawValueIsClosure (callable $ raw , string $ expectedWithoutQuotes ): void
4845 {
4946 $ quoter = new FakeQuoter ();
5047
@@ -56,6 +53,31 @@ public function itShouldStringifyWhenRawValueIsCallable(callable $raw, string $e
5653 self ::assertEquals ($ expected , $ actual );
5754 }
5855
56+ #[Test]
57+ #[DataProvider('nonClosureCallableRawValuesProvider ' )]
58+ public function itShouldNotStringifyNonClosureCallableByDefault (callable $ raw , string $ _ ): void
59+ {
60+ $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter ());
61+
62+ self ::assertNull ($ sut ->stringify ($ raw , self ::DEPTH ));
63+ }
64+
65+ #[Test]
66+ #[DataProvider('nonClosureCallableRawValuesProvider ' )]
67+ public function itShouldStringifyNonClosureCallableWhenClosureOnlyIsFalse (
68+ callable $ raw ,
69+ string $ expectedWithoutQuotes ,
70+ ): void {
71+ $ quoter = new FakeQuoter ();
72+
73+ $ sut = new CallableStringifier (new FakeStringifier (), $ quoter , closureOnly: false );
74+
75+ $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
76+ $ expected = $ quoter ->quote ($ expectedWithoutQuotes , self ::DEPTH );
77+
78+ self ::assertEquals ($ expected , $ actual );
79+ }
80+
5981 #[Test]
6082 public function itShouldStringifyWhenRawValueIsCallableWithDefaultValues (): void
6183 {
@@ -68,7 +90,7 @@ public function itShouldStringifyWhenRawValueIsCallableWithDefaultValues(): void
6890
6991 $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
7092 $ expected = $ quoter ->quote (
71- sprintf ('function (int $value = %s): int ' , $ stringifier ->stringify (1 , self ::DEPTH + 1 )),
93+ sprintf ('Closure { static fn (int $value = %s): int } ' , $ stringifier ->stringify (1 , self ::DEPTH + 1 )),
7294 self ::DEPTH
7395 );
7496
@@ -86,7 +108,7 @@ public function itShouldStringifyWhenRawValueIsCallableThatDoesNotHaveAnAccessib
86108
87109 $ quoter = new FakeQuoter ();
88110
89- $ sut = new CallableStringifier (new FakeStringifier (), $ quoter );
111+ $ sut = new CallableStringifier (new FakeStringifier (), $ quoter, closureOnly: false );
90112
91113 $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
92114 $ expected = $ quoter ->quote (
@@ -98,40 +120,90 @@ public function itShouldStringifyWhenRawValueIsCallableThatDoesNotHaveAnAccessib
98120 }
99121
100122 /**
101- * @return array<int , array{0: callable, 1: string}>
123+ * @return array<string , array{0: callable, 1: string}>
102124 */
103- public static function callableRawValuesProvider (): array
125+ public static function closureRawValuesProvider (): array
104126 {
105127 $ var1 = 1 ;
106128 $ var2 = 2 ;
107129
108130 return [
109- [static fn () => 1 , 'function () ' ],
110- [static fn (): int => 1 , 'function (): int ' ],
111- [static fn (float $ value ): int => (int ) $ value , 'function (float $value): int ' ],
112- [static fn (float &$ value ): int => (int ) $ value , 'function (float &$value): int ' ],
113- [static fn (?float $ value ): int => (int ) $ value , 'function (?float $value): int ' ],
114- [static fn (int $ value = self ::DEPTH ): int => $ value , 'function (int $value = self::DEPTH): int ' ],
115- [static fn (int |float $ value ): int => (int ) $ value , 'function (int|float $value): int ' ],
116- [static fn (Countable &Iterator $ value ): int => $ value ->count (), 'function (Countable&Iterator $value): int ' ],
117- [static fn (int ...$ value ): int => array_sum ($ value ), 'function (int ...$value): int ' ],
118- [
131+ 'static closure without parameters ' => [
132+ static fn () => 1 ,
133+ 'Closure { static fn () } ' ,
134+ ],
135+ 'non-static closure without parameters ' => [
136+ fn () => 1 ,
137+ 'Closure { fn () } ' ,
138+ ],
139+ 'static closure with return type ' => [
140+ static fn (): int => 1 ,
141+ 'Closure { static fn (): int } ' ,
142+ ],
143+ 'non-static closure with return type ' => [
144+ fn (): int => 1 ,
145+ 'Closure { fn (): int } ' ,
146+ ],
147+ 'static closure with typed parameter ' => [
148+ static fn (float $ value ): int => (int ) $ value ,
149+ 'Closure { static fn (float $value): int } ' ,
150+ ],
151+ 'static closure with reference parameter ' => [
152+ static fn (float &$ value ): int => (int ) $ value ,
153+ 'Closure { static fn (float &$value): int } ' ,
154+ ],
155+ 'static closure with nullable parameter ' => [
156+ static fn (?float $ value ): int => (int ) $ value ,
157+ 'Closure { static fn (?float $value): int } ' ,
158+ ],
159+ 'static closure with constant default value ' => [
160+ static fn (int $ value = self ::DEPTH ): int => $ value ,
161+ 'Closure { static fn (int $value = self::DEPTH): int } ' ,
162+ ],
163+ 'static closure with union type parameter ' => [
164+ static fn (int |float $ value ): int => (int ) $ value ,
165+ 'Closure { static fn (int|float $value): int } ' ,
166+ ],
167+ 'static closure with intersection type parameter ' => [
168+ static fn (Countable &Iterator $ value ): int => $ value ->count (),
169+ 'Closure { static fn (Countable&Iterator $value): int } ' ,
170+ ],
171+ 'static closure with variadic parameter ' => [
172+ static fn (int ...$ value ): int => array_sum ($ value ),
173+ 'Closure { static fn (int ...$value): int } ' ,
174+ ],
175+ 'static closure with multiple parameters ' => [
119176 static fn (float $ value1 , float $ value2 ): float => $ value1 + $ value2 ,
120- 'function (float $value1, float $value2): float ' ,
177+ 'Closure { static fn (float $value1, float $value2): float } ' ,
121178 ],
122- [
179+ ' static closure with single use variable ' => [
123180 static function (int $ value ) use ($ var1 ): int {
124181 return $ value + $ var1 ;
125182 },
126- 'function (int $value) use ($var1): int ' ,
183+ 'Closure { static fn (int $value) use ($var1): int } ' ,
127184 ],
128- [
185+ ' static closure with multiple use variables ' => [
129186 static function (int $ value ) use ($ var1 , $ var2 ): int {
130187 return $ value + $ var1 + $ var2 ;
131188 },
132- 'function (int $value) use ($var1, $var2): int ' ,
189+ 'Closure { static fn (int $value) use ($var1, $var2): int } ' ,
190+ ],
191+ 'non-static closure with use variable ' => [
192+ function (int $ value ) use ($ var1 ): int {
193+ return $ value + $ var1 ;
194+ },
195+ 'Closure { fn (int $value) use ($var1): int } ' ,
133196 ],
134- [
197+ ];
198+ }
199+
200+ /**
201+ * @return array<string, array{0: callable, 1: string}>
202+ */
203+ public static function nonClosureCallableRawValuesProvider (): array
204+ {
205+ return [
206+ 'invokable object ' => [
135207 new class {
136208 public function __invoke (int $ parameter ): never
137209 {
@@ -140,19 +212,22 @@ public function __invoke(int $parameter): never
140212 },
141213 'class->__invoke(int $parameter): never ' ,
142214 ],
143- [
215+ ' object method as array ' => [
144216 [new DateTime (), 'format ' ],
145217 'DateTime->format(string $format) ' ,
146218 ],
147- [
219+ ' static method as array ' => [
148220 ['DateTime ' , 'createFromImmutable ' ],
149221 'DateTime::createFromImmutable(DateTimeImmutable $object) ' ,
150222 ],
151- [
223+ ' static method as string ' => [
152224 'DateTimeImmutable::getLastErrors ' ,
153225 'DateTimeImmutable::getLastErrors() ' ,
154226 ],
155- ['chr ' , 'chr(int $codepoint): string ' ],
227+ 'function name as string ' => [
228+ 'chr ' ,
229+ 'chr(int $codepoint): string ' ,
230+ ],
156231 ];
157232 }
158233}
0 commit comments