1717use PHPUnit \Framework \Attributes \DataProvider ;
1818use PHPUnit \Framework \Attributes \Test ;
1919use PHPUnit \Framework \TestCase ;
20+ use Respect \Stringifier \Helpers \ObjectHelper ;
2021use Respect \Stringifier \Stringifiers \CallableStringifier ;
2122use Respect \Stringifier \Test \Double \FakeQuoter ;
2223use Respect \Stringifier \Test \Double \FakeStringifier ;
@@ -32,14 +33,14 @@ final class CallableStringifierTest extends TestCase
3233 #[Test]
3334 public function itShouldNotStringifyWhenRawValueIsNotCallable (): void
3435 {
35- $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter ());
36+ $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter (), closureOnly: false );
3637
3738 self ::assertNull ($ sut ->stringify (1 , self ::DEPTH ));
3839 }
3940
4041 #[Test]
41- #[DataProvider('callableRawValuesProvider ' )]
42- public function itShouldStringifyWhenRawValueIsCallable (callable $ raw , string $ expectedWithoutQuotes ): void
42+ #[DataProvider('closureRawValuesProvider ' )]
43+ public function itShouldStringifyWhenRawValueIsClosure (callable $ raw , string $ expectedWithoutQuotes ): void
4344 {
4445 $ quoter = new FakeQuoter ();
4546
@@ -51,6 +52,31 @@ public function itShouldStringifyWhenRawValueIsCallable(callable $raw, string $e
5152 self ::assertEquals ($ expected , $ actual );
5253 }
5354
55+ #[Test]
56+ #[DataProvider('nonClosureCallableRawValuesProvider ' )]
57+ public function itShouldNotStringifyNonClosureCallableByDefault (callable $ raw , string $ useless ): void
58+ {
59+ $ sut = new CallableStringifier (new FakeStringifier (), new FakeQuoter ());
60+
61+ self ::assertNull ($ sut ->stringify ($ raw , self ::DEPTH ));
62+ }
63+
64+ #[Test]
65+ #[DataProvider('nonClosureCallableRawValuesProvider ' )]
66+ public function itShouldStringifyNonClosureCallableWhenClosureOnlyIsFalse (
67+ callable $ raw ,
68+ string $ expectedWithoutQuotes ,
69+ ): void {
70+ $ quoter = new FakeQuoter ();
71+
72+ $ sut = new CallableStringifier (new FakeStringifier (), $ quoter , closureOnly: false );
73+
74+ $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
75+ $ expected = $ quoter ->quote ($ expectedWithoutQuotes , self ::DEPTH );
76+
77+ self ::assertEquals ($ expected , $ actual );
78+ }
79+
5480 #[Test]
5581 public function itShouldStringifyWhenRawValueIsCallableWithDefaultValues (): void
5682 {
@@ -63,7 +89,7 @@ public function itShouldStringifyWhenRawValueIsCallableWithDefaultValues(): void
6389
6490 $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
6591 $ expected = $ quoter ->quote (
66- sprintf ('function (int $value = %s): int ' , $ stringifier ->stringify (1 , self ::DEPTH + 1 )),
92+ sprintf ('Closure { static fn (int $value = %s): int } ' , $ stringifier ->stringify (1 , self ::DEPTH + 1 )),
6793 self ::DEPTH ,
6894 );
6995
@@ -77,7 +103,7 @@ public function itShouldStringifyWhenRawValueIsCallableThatDoesNotHaveAnAccessib
77103
78104 $ quoter = new FakeQuoter ();
79105
80- $ sut = new CallableStringifier (new FakeStringifier (), $ quoter );
106+ $ sut = new CallableStringifier (new FakeStringifier (), $ quoter, closureOnly: false );
81107
82108 $ actual = $ sut ->stringify ($ raw , self ::DEPTH );
83109 $ expected = $ quoter ->quote (
@@ -88,40 +114,87 @@ public function itShouldStringifyWhenRawValueIsCallableThatDoesNotHaveAnAccessib
88114 self ::assertEquals ($ expected , $ actual );
89115 }
90116
91- /** @return array<int , array{0: callable, 1: string}> */
92- public static function callableRawValuesProvider (): array
117+ /** @return array<string , array{0: callable, 1: string}> */
118+ public static function closureRawValuesProvider (): array
93119 {
94120 $ var1 = 1 ;
95121 $ var2 = 2 ;
96122
97123 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- [
124+ 'static closure without parameters ' => [
125+ static fn () => 1 ,
126+ 'Closure { static fn() } ' ,
127+ ],
128+ 'non-static closure without parameters ' => [
129+ fn () => 1 ,
130+ 'Closure { fn() } ' ,
131+ ],
132+ 'static closure with return type ' => [
133+ static fn (): int => 1 ,
134+ 'Closure { static fn(): int } ' ,
135+ ],
136+ 'non-static closure with return type ' => [
137+ fn (): int => 1 ,
138+ 'Closure { fn(): int } ' ,
139+ ],
140+ 'static closure with typed parameter ' => [
141+ static fn (float $ value ): int => (int ) $ value ,
142+ 'Closure { static fn(float $value): int } ' ,
143+ ],
144+ 'static closure with reference parameter ' => [
145+ static fn (float &$ value ): int => (int ) $ value ,
146+ 'Closure { static fn(float &$value): int } ' ,
147+ ],
148+ 'static closure with nullable parameter ' => [
149+ static fn (float |null $ value ): int => (int ) $ value ,
150+ 'Closure { static fn(?float $value): int } ' ,
151+ ],
152+ 'static closure with constant default value ' => [
153+ static fn (int $ value = self ::DEPTH ): int => $ value ,
154+ 'Closure { static fn(int $value = self::DEPTH): int } ' ,
155+ ],
156+ 'static closure with union type parameter ' => [
157+ static fn (int |float $ value ): int => (int ) $ value ,
158+ 'Closure { static fn(int|float $value): int } ' ,
159+ ],
160+ 'static closure with intersection type parameter ' => [
161+ static fn (Countable &Iterator $ value ): int => $ value ->count (),
162+ 'Closure { static fn(Countable&Iterator $value): int } ' ,
163+ ],
164+ 'static closure with variadic parameter ' => [
165+ static fn (int ...$ value ): int => array_sum ($ value ),
166+ 'Closure { static fn(int ...$value): int } ' ,
167+ ],
168+ 'static closure with multiple parameters ' => [
109169 static fn (float $ value1 , float $ value2 ): float => $ value1 + $ value2 ,
110- 'function (float $value1, float $value2): float ' ,
170+ 'Closure { static fn (float $value1, float $value2): float } ' ,
111171 ],
112- [
172+ ' static closure with single use variable ' => [
113173 static function (int $ value ) use ($ var1 ): int {
114174 return $ value + $ var1 ;
115175 },
116- 'function (int $value) use ($var1): int ' ,
176+ 'Closure { static fn (int $value) use ($var1): int } ' ,
117177 ],
118- [
178+ ' static closure with multiple use variables ' => [
119179 static function (int $ value ) use ($ var1 , $ var2 ): int {
120180 return $ value + $ var1 + $ var2 ;
121181 },
122- 'function (int $value) use ($var1, $var2): int ' ,
182+ 'Closure { static fn (int $value) use ($var1, $var2): int } ' ,
123183 ],
124- [
184+ 'non-static closure with use variable ' => [
185+ function (int $ value ) use ($ var1 ): int {
186+ return $ value + $ var1 ;
187+ },
188+ 'Closure { fn(int $value) use ($var1): int } ' ,
189+ ],
190+ ];
191+ }
192+
193+ /** @return array<string, array{0: callable, 1: string}> */
194+ public static function nonClosureCallableRawValuesProvider (): array
195+ {
196+ return [
197+ 'invokable object ' => [
125198 new class {
126199 public function __invoke (int $ parameter ): never
127200 {
@@ -130,19 +203,22 @@ public function __invoke(int $parameter): never
130203 },
131204 'class->__invoke(int $parameter): never ' ,
132205 ],
133- [
206+ ' object method as array ' => [
134207 [new DateTime (), 'format ' ],
135208 'DateTime->format(string $format) ' ,
136209 ],
137- [
210+ ' static method as array ' => [
138211 ['DateTime ' , 'createFromImmutable ' ],
139212 'DateTime::createFromImmutable(DateTimeImmutable $object) ' ,
140213 ],
141- [
214+ ' static method as string ' => [
142215 'DateTimeImmutable::getLastErrors ' ,
143216 'DateTimeImmutable::getLastErrors() ' ,
144217 ],
145- ['chr ' , 'chr(int $codepoint): string ' ],
218+ 'function name as string ' => [
219+ 'chr ' ,
220+ 'chr(int $codepoint): string ' ,
221+ ],
146222 ];
147223 }
148224}
0 commit comments