1010use Prophecy \Doubler \Generator \Node \ClassNode ;
1111use Prophecy \Doubler \Generator \Node \MethodNode ;
1212use Prophecy \Doubler \Generator \Node \ReturnTypeNode ;
13+ use Prophecy \Doubler \Generator \Node \Type \BuiltinType ;
14+ use Prophecy \Doubler \Generator \Node \Type \IntersectionType ;
15+ use Prophecy \Doubler \Generator \Node \Type \ObjectType ;
16+ use Prophecy \Doubler \Generator \Node \Type \SimpleType ;
17+ use Prophecy \Doubler \Generator \Node \Type \UnionType ;
1318
1419class ClassCodeGeneratorSpec extends ObjectBehavior
1520{
@@ -39,7 +44,10 @@ function it_generates_proper_php_code_for_specific_ClassNode(
3944 $ method1 ->returnsReference ()->willReturn (false );
4045 $ method1 ->isStatic ()->willReturn (true );
4146 $ method1 ->getArguments ()->willReturn (array ($ argument11 , $ argument12 , $ argument13 ));
42- $ method1 ->getReturnTypeNode ()->willReturn (new ReturnTypeNode ('string ' , 'null ' ));
47+ $ method1 ->getReturnTypeNode ()->willReturn (new ReturnTypeNode (new UnionType ([
48+ new BuiltinType ('string ' ),
49+ new BuiltinType ('null ' ),
50+ ])));
4351 $ method1 ->getCode ()->willReturn ('return $this->name; ' );
4452
4553 $ method2 ->getName ()->willReturn ('getEmail ' );
@@ -55,49 +63,52 @@ function it_generates_proper_php_code_for_specific_ClassNode(
5563 $ method3 ->returnsReference ()->willReturn (true );
5664 $ method3 ->isStatic ()->willReturn (false );
5765 $ method3 ->getArguments ()->willReturn (array ($ argument31 ));
58- $ method3 ->getReturnTypeNode ()->willReturn (new ReturnTypeNode ('string ' ));
66+ $ method3 ->getReturnTypeNode ()->willReturn (new ReturnTypeNode (new BuiltinType ( 'string ' ) ));
5967 $ method3 ->getCode ()->willReturn ('return $this->refValue; ' );
6068
6169 $ method4 ->getName ()->willReturn ('doSomething ' );
6270 $ method4 ->getVisibility ()->willReturn ('public ' );
6371 $ method4 ->returnsReference ()->willReturn (false );
6472 $ method4 ->isStatic ()->willReturn (false );
6573 $ method4 ->getArguments ()->willReturn (array ());
66- $ method4 ->getReturnTypeNode ()->willReturn (new ReturnTypeNode ('void ' ));
74+ $ method4 ->getReturnTypeNode ()->willReturn (new ReturnTypeNode (new BuiltinType ( 'void ' ) ));
6775 $ method4 ->getCode ()->willReturn ('return; ' );
6876
6977 $ method5 ->getName ()->willReturn ('returnObject ' );
7078 $ method5 ->getVisibility ()->willReturn ('public ' );
7179 $ method5 ->returnsReference ()->willReturn (false );
7280 $ method5 ->isStatic ()->willReturn (false );
7381 $ method5 ->getArguments ()->willReturn (array ());
74- $ method5 ->getReturnTypeNode ()->willReturn (new ReturnTypeNode ('object ' ));
82+ $ method5 ->getReturnTypeNode ()->willReturn (new ReturnTypeNode (new BuiltinType ( 'object ' ) ));
7583 $ method5 ->getCode ()->willReturn ('return; ' );
7684
7785 $ argument11 ->getName ()->willReturn ('fullname ' );
7886 $ argument11 ->isOptional ()->willReturn (false );
7987 $ argument11 ->isPassedByReference ()->willReturn (false );
8088 $ argument11 ->isVariadic ()->willReturn (false );
81- $ argument11 ->getTypeNode ()->willReturn (new ArgumentTypeNode ('array ' ));
89+ $ argument11 ->getTypeNode ()->willReturn (new ArgumentTypeNode (new BuiltinType ( 'array ' ) ));
8290
8391 $ argument12 ->getName ()->willReturn ('class ' );
8492 $ argument12 ->isOptional ()->willReturn (false );
8593 $ argument12 ->isPassedByReference ()->willReturn (false );
8694 $ argument12 ->isVariadic ()->willReturn (false );
87- $ argument12 ->getTypeNode ()->willReturn (new ArgumentTypeNode ('ReflectionClass ' ));
95+ $ argument12 ->getTypeNode ()->willReturn (new ArgumentTypeNode (new ObjectType ( 'ReflectionClass ' ) ));
8896
8997 $ argument13 ->getName ()->willReturn ('instance ' );
9098 $ argument13 ->isOptional ()->willReturn (false );
9199 $ argument13 ->isPassedByReference ()->willReturn (false );
92100 $ argument13 ->isVariadic ()->willReturn (false );
93- $ argument13 ->getTypeNode ()->willReturn (new ArgumentTypeNode ('object ' ));
101+ $ argument13 ->getTypeNode ()->willReturn (new ArgumentTypeNode (new BuiltinType ( 'object ' ) ));
94102
95103 $ argument21 ->getName ()->willReturn ('default ' );
96104 $ argument21 ->isOptional ()->willReturn (true );
97105 $ argument21 ->getDefault ()->willReturn ('ever.zet@gmail.com ' );
98106 $ argument21 ->isPassedByReference ()->willReturn (false );
99107 $ argument21 ->isVariadic ()->willReturn (false );
100- $ argument21 ->getTypeNode ()->willReturn (new ArgumentTypeNode ('string ' , 'null ' ));
108+ $ argument21 ->getTypeNode ()->willReturn (new ArgumentTypeNode (new UnionType ([
109+ new BuiltinType ('string ' ),
110+ new BuiltinType ('null ' ),
111+ ])));
101112
102113 $ argument31 ->getName ()->willReturn ('refValue ' );
103114 $ argument31 ->isOptional ()->willReturn (false );
@@ -115,10 +126,10 @@ class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generat
115126public $name;
116127private $email;
117128
118- public static function getName(array $fullname, \ReflectionClass $class, object $instance): ? string {
129+ public static function getName(array $fullname, \ReflectionClass $class, object $instance): string|null {
119130return $this->name;
120131}
121- protected function getEmail(? string $default = 'ever.zet@gmail.com') {
132+ protected function getEmail(string|null $default = 'ever.zet@gmail.com') {
122133return $this->email;
123134}
124135public function &getRefValue( $refValue): string {
@@ -206,13 +217,13 @@ function it_generates_proper_php_code_for_variadics(
206217 $ argument3 ->isOptional ()->willReturn (false );
207218 $ argument3 ->isPassedByReference ()->willReturn (false );
208219 $ argument3 ->isVariadic ()->willReturn (true );
209- $ argument3 ->getTypeNode ()->willReturn (new ArgumentTypeNode ('ReflectionClass ' ));
220+ $ argument3 ->getTypeNode ()->willReturn (new ArgumentTypeNode (new ObjectType ( 'ReflectionClass ' ) ));
210221
211222 $ argument4 ->getName ()->willReturn ('args ' );
212223 $ argument4 ->isOptional ()->willReturn (false );
213224 $ argument4 ->isPassedByReference ()->willReturn (true );
214225 $ argument4 ->isVariadic ()->willReturn (true );
215- $ argument4 ->getTypeNode ()->willReturn (new ArgumentTypeNode ('ReflectionClass ' ));
226+ $ argument4 ->getTypeNode ()->willReturn (new ArgumentTypeNode (new ObjectType ( 'ReflectionClass ' ) ));
216227
217228
218229 $ code = $ this ->generate ('CustomClass ' , $ class );
@@ -264,14 +275,17 @@ function it_overrides_properly_methods_with_args_passed_by_reference(
264275 $ argument ->getDefault ()->willReturn (null );
265276 $ argument ->isPassedByReference ()->willReturn (true );
266277 $ argument ->isVariadic ()->willReturn (false );
267- $ argument ->getTypeNode ()->willReturn (new ArgumentTypeNode ('array ' , 'null ' ));
278+ $ argument ->getTypeNode ()->willReturn (new ArgumentTypeNode (new UnionType ([
279+ new BuiltinType ('array ' ),
280+ new BuiltinType ('null ' ),
281+ ])));
268282
269283 $ code = $ this ->generate ('CustomClass ' , $ class );
270284 $ expected = <<<'PHP'
271285namespace {
272286class CustomClass extends \RuntimeException implements \Prophecy\Doubler\Generator\MirroredInterface {
273287
274- public function getName(? array &$fullname = NULL) {
288+ public function getName(array|null &$fullname = NULL) {
275289return $this->name;
276290}
277291
@@ -296,7 +310,11 @@ function it_generates_proper_code_for_union_return_types(
296310 $ method ->getVisibility ()->willReturn ('public ' );
297311 $ method ->isStatic ()->willReturn (false );
298312 $ method ->getArguments ()->willReturn ([]);
299- $ method ->getReturnTypeNode ()->willReturn (new ReturnTypeNode ('int ' , 'string ' , 'null ' ));
313+ $ method ->getReturnTypeNode ()->willReturn (new ReturnTypeNode (new UnionType ([
314+ new BuiltinType ('int ' ),
315+ new BuiltinType ('string ' ),
316+ new BuiltinType ('null ' ),
317+ ])));
300318 $ method ->returnsReference ()->willReturn (false );
301319 $ method ->getCode ()->willReturn ('' );
302320
@@ -310,6 +328,86 @@ public function foo(): int|string|null {
310328
311329}
312330
331+ }
332+ }
333+ PHP;
334+ $ expected = strtr ($ expected , array ("\r\n" => "\n" , "\r" => "\n" ));
335+
336+ $ code ->shouldBe ($ expected );
337+ }
338+
339+ function it_generates_proper_code_for_dnf_types (
340+ ClassNode $ class ,
341+ MethodNode $ method
342+ ) {
343+ $ class ->getParentClass ()->willReturn ('stdClass ' );
344+ $ class ->getInterfaces ()->willReturn ([]);
345+ $ class ->getProperties ()->willReturn ([]);
346+ $ class ->getMethods ()->willReturn (array ($ method ));
347+ $ class ->isReadOnly ()->willReturn (false );
348+
349+ $ method ->getName ()->willReturn ('foo ' );
350+ $ method ->getVisibility ()->willReturn ('public ' );
351+ $ method ->isStatic ()->willReturn (false );
352+ $ method ->getArguments ()->willReturn ([]);
353+ $ method ->getReturnTypeNode ()->willReturn (new ReturnTypeNode (
354+ new UnionType ([
355+ new IntersectionType ([new ObjectType ('Foo ' ), new ObjectType ('Bar ' )]),
356+ new BuiltinType ('string ' ),
357+ ])
358+ ));
359+ $ method ->returnsReference ()->willReturn (false );
360+ $ method ->getCode ()->willReturn ('' );
361+
362+ $ code = $ this ->generate ('CustomClass ' , $ class );
363+
364+ $ expected = <<<'PHP'
365+ namespace {
366+ class CustomClass extends \stdClass implements {
367+
368+ public function foo(): (\Foo&\Bar)|string {
369+
370+ }
371+
372+ }
373+ }
374+ PHP;
375+ $ expected = strtr ($ expected , array ("\r\n" => "\n" , "\r" => "\n" ));
376+
377+ $ code ->shouldBe ($ expected );
378+ }
379+
380+
381+ function it_generates_proper_code_for_intersection_return_types (
382+ ClassNode $ class ,
383+ MethodNode $ method
384+ ) {
385+ $ class ->getParentClass ()->willReturn ('stdClass ' );
386+ $ class ->getInterfaces ()->willReturn ([]);
387+ $ class ->getProperties ()->willReturn ([]);
388+ $ class ->getMethods ()->willReturn (array ($ method ));
389+ $ class ->isReadOnly ()->willReturn (false );
390+
391+ $ method ->getName ()->willReturn ('foo ' );
392+ $ method ->getVisibility ()->willReturn ('public ' );
393+ $ method ->isStatic ()->willReturn (false );
394+ $ method ->getArguments ()->willReturn ([]);
395+ $ method ->getReturnTypeNode ()->willReturn (new ReturnTypeNode (
396+ new IntersectionType ([new ObjectType ('Foo ' ), new ObjectType ('Bar ' )])
397+ ));
398+ $ method ->returnsReference ()->willReturn (false );
399+ $ method ->getCode ()->willReturn ('' );
400+
401+ $ code = $ this ->generate ('CustomClass ' , $ class );
402+
403+ $ expected = <<<'PHP'
404+ namespace {
405+ class CustomClass extends \stdClass implements {
406+
407+ public function foo(): \Foo&\Bar {
408+
409+ }
410+
313411}
314412}
315413PHP;
@@ -337,7 +435,11 @@ function it_generates_proper_code_for_union_argument_types(
337435 $ method ->returnsReference ()->willReturn (false );
338436 $ method ->getCode ()->willReturn ('' );
339437
340- $ argument ->getTypeNode ()->willReturn (new ArgumentTypeNode ('int ' , 'string ' , 'null ' ));
438+ $ argument ->getTypeNode ()->willReturn (new ArgumentTypeNode (new UnionType ([
439+ new BuiltinType ('int ' ),
440+ new BuiltinType ('string ' ),
441+ new BuiltinType ('null ' ),
442+ ])));
341443 $ argument ->getName ()->willReturn ('arg ' );
342444 $ argument ->isPassedByReference ()->willReturn (false );
343445 $ argument ->isVariadic ()->willReturn (false );
0 commit comments