Skip to content

Commit be20ef1

Browse files
authored
Add support for union and intersection types (#644)
1 parent 402dc3d commit be20ef1

File tree

3 files changed

+356
-0
lines changed

3 files changed

+356
-0
lines changed

specs/types/intersection.php

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the humbug/php-scoper package.
7+
*
8+
* Copyright (c) 2017 Théo FIDRY <[email protected]>,
9+
* Pádraic Brady <[email protected]>
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
return [
16+
'meta' => [
17+
'title' => 'Union types',
18+
// Default values. If not specified will be the one used
19+
'prefix' => 'Humbug',
20+
21+
'expose-global-constants' => false,
22+
'expose-global-classes' => false,
23+
'expose-global-functions' => false,
24+
'expose-namespaces' => [],
25+
'expose-constants' => [],
26+
'expose-classes' => [],
27+
'expose-functions' => [],
28+
29+
'exclude-namespaces' => [],
30+
'exclude-constants' => [],
31+
'exclude-classes' => [],
32+
'exclude-functions' => [],
33+
34+
'expected-recorded-classes' => [],
35+
'expected-recorded-functions' => [],
36+
],
37+
38+
'Method casts' => <<<'PHP'
39+
<?php
40+
41+
class X
42+
{
43+
public function method1(Y&Z $a, Y $b) : Y&Z
44+
{
45+
}
46+
}
47+
48+
----
49+
<?php
50+
51+
namespace Humbug;
52+
53+
class X
54+
{
55+
public function method1(Y&Z $a, Y $b) : Y&Z
56+
{
57+
}
58+
}
59+
60+
PHP,
61+
62+
'Function casts' => <<<'PHP'
63+
<?php
64+
65+
function fun1(Y&Z $a) : Y&Z
66+
{
67+
}
68+
69+
----
70+
<?php
71+
72+
namespace Humbug;
73+
74+
function fun1(Y&Z $a) : Y&Z
75+
{
76+
}
77+
78+
PHP,
79+
80+
'Property casts' => <<<'PHP'
81+
<?php
82+
83+
class X
84+
{
85+
private Y&Z $x;
86+
}
87+
88+
----
89+
<?php
90+
91+
namespace Humbug;
92+
93+
class X
94+
{
95+
private Y&Z $x;
96+
}
97+
98+
PHP,
99+
100+
'Trait casts' => <<<'PHP'
101+
<?php
102+
103+
trait X
104+
{
105+
private Y&Z $x;
106+
public function method1(Y&Z $a) : Y&Z
107+
{
108+
}
109+
}
110+
111+
----
112+
<?php
113+
114+
namespace Humbug;
115+
116+
trait X
117+
{
118+
private Y&Z $x;
119+
public function method1(Y&Z $a) : Y&Z
120+
{
121+
}
122+
}
123+
124+
PHP,
125+
126+
'Interface casts' => <<<'PHP'
127+
<?php
128+
129+
interface X
130+
{
131+
public function method1(Y&Z $a) : Y&Z;
132+
}
133+
134+
----
135+
<?php
136+
137+
namespace Humbug;
138+
139+
interface X
140+
{
141+
public function method1(Y&Z $a) : Y&Z;
142+
}
143+
144+
PHP,
145+
];

specs/types/union.php

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the humbug/php-scoper package.
7+
*
8+
* Copyright (c) 2017 Théo FIDRY <[email protected]>,
9+
* Pádraic Brady <[email protected]>
10+
*
11+
* For the full copyright and license information, please view the LICENSE
12+
* file that was distributed with this source code.
13+
*/
14+
15+
return [
16+
'meta' => [
17+
'title' => 'Union types',
18+
// Default values. If not specified will be the one used
19+
'prefix' => 'Humbug',
20+
21+
'expose-global-constants' => false,
22+
'expose-global-classes' => false,
23+
'expose-global-functions' => false,
24+
'expose-namespaces' => [],
25+
'expose-constants' => [],
26+
'expose-classes' => [],
27+
'expose-functions' => [],
28+
29+
'exclude-namespaces' => [],
30+
'exclude-constants' => [],
31+
'exclude-classes' => [],
32+
'exclude-functions' => [],
33+
34+
'expected-recorded-classes' => [],
35+
'expected-recorded-functions' => [],
36+
],
37+
38+
'Method casts' => <<<'PHP'
39+
<?php
40+
41+
class X
42+
{
43+
public function method1(Y|Z $a, null|Y $b) : null|Y|Z
44+
{
45+
}
46+
public function method2(?Y $b) : ?Z
47+
{
48+
}
49+
public function method3(self|null $b) : static|null
50+
{
51+
}
52+
}
53+
54+
----
55+
<?php
56+
57+
namespace Humbug;
58+
59+
class X
60+
{
61+
public function method1(Y|Z $a, null|Y $b) : null|Y|Z
62+
{
63+
}
64+
public function method2(?Y $b) : ?Z
65+
{
66+
}
67+
public function method3(self|null $b) : static|null
68+
{
69+
}
70+
}
71+
72+
PHP,
73+
74+
'Function casts' => <<<'PHP'
75+
<?php
76+
77+
function fun1(Y|Z $a, null|Y $b) : null|Y|Z
78+
{
79+
}
80+
function fun2(?Y $b) : ?Z
81+
{
82+
}
83+
84+
----
85+
<?php
86+
87+
namespace Humbug;
88+
89+
function fun1(Y|Z $a, null|Y $b) : null|Y|Z
90+
{
91+
}
92+
function fun2(?Y $b) : ?Z
93+
{
94+
}
95+
96+
PHP,
97+
98+
'Property casts' => <<<'PHP'
99+
<?php
100+
101+
class X
102+
{
103+
private null|Y|Z $x;
104+
private ?X $y;
105+
private null|self $z;
106+
}
107+
108+
----
109+
<?php
110+
111+
namespace Humbug;
112+
113+
class X
114+
{
115+
private null|Y|Z $x;
116+
private ?X $y;
117+
private null|self $z;
118+
}
119+
120+
PHP,
121+
122+
'Trait casts' => <<<'PHP'
123+
<?php
124+
125+
trait X
126+
{
127+
private null|Y|Z $x;
128+
private ?X $y;
129+
private null|self $z;
130+
public function method1(Y|Z $a, null|Y $b) : null|Y|Z
131+
{
132+
}
133+
public function method2(?Y $b) : ?Z
134+
{
135+
}
136+
public function method3(self|null $b) : static|null
137+
{
138+
}
139+
}
140+
141+
----
142+
<?php
143+
144+
namespace Humbug;
145+
146+
trait X
147+
{
148+
private null|Y|Z $x;
149+
private ?X $y;
150+
private null|self $z;
151+
public function method1(Y|Z $a, null|Y $b) : null|Y|Z
152+
{
153+
}
154+
public function method2(?Y $b) : ?Z
155+
{
156+
}
157+
public function method3(self|null $b) : static|null
158+
{
159+
}
160+
}
161+
162+
PHP,
163+
164+
'Interface casts' => <<<'PHP'
165+
<?php
166+
167+
interface X
168+
{
169+
public function method1(Y|Z $a, null|Y $b) : null|Y|Z;
170+
public function method2(?Y $b) : ?Z;
171+
public function method3(self|null $b) : static|null;
172+
}
173+
174+
----
175+
<?php
176+
177+
namespace Humbug;
178+
179+
interface X
180+
{
181+
public function method1(Y|Z $a, null|Y $b) : null|Y|Z;
182+
public function method2(?Y $b) : ?Z;
183+
public function method3(self|null $b) : static|null;
184+
}
185+
186+
PHP,
187+
188+
'Untouched scalar casts' => <<<'PHP'
189+
<?php
190+
191+
interface X
192+
{
193+
public function method1(string|int $b) : string|int;
194+
}
195+
196+
----
197+
<?php
198+
199+
namespace Humbug;
200+
201+
interface X
202+
{
203+
public function method1(string|int $b) : string|int;
204+
}
205+
206+
PHP,
207+
];

src/PhpParser/NodeVisitor/NameStmtPrefixer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use PhpParser\Node\Expr\New_;
3030
use PhpParser\Node\Expr\StaticCall;
3131
use PhpParser\Node\Expr\StaticPropertyFetch;
32+
use PhpParser\Node\IntersectionType;
3233
use PhpParser\Node\Name;
3334
use PhpParser\Node\Name\FullyQualified;
3435
use PhpParser\Node\NullableType;
@@ -43,6 +44,7 @@
4344
use PhpParser\Node\Stmt\TraitUseAdaptation\Alias;
4445
use PhpParser\Node\Stmt\TraitUseAdaptation\Precedence;
4546
use PhpParser\Node\Stmt\Use_;
47+
use PhpParser\Node\UnionType;
4648
use PhpParser\NodeVisitorAbstract;
4749
use function in_array;
4850
use function strtolower;
@@ -84,6 +86,8 @@ final class NameStmtPrefixer extends NodeVisitorAbstract
8486
StaticCall::class,
8587
StaticPropertyFetch::class,
8688
TraitUse::class,
89+
UnionType::class,
90+
IntersectionType::class,
8791
];
8892

8993
private string $prefix;

0 commit comments

Comments
 (0)