Skip to content

Commit b4a63c5

Browse files
committed
More tests
1 parent c53db34 commit b4a63c5

24 files changed

+1162
-4
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
--TEST--
2+
ReflectionTypes of relative class types (self, parent) in classes, by-ref parameter types
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
8+
}
9+
10+
class B extends A {
11+
public function foo(self &$o) { return $o; }
12+
}
13+
14+
class C extends B {
15+
public function bar(parent &$o) { return $o; }
16+
public function ping(self &$o) { return $o; }
17+
}
18+
19+
class D extends C {}
20+
21+
$instances = [
22+
new A,
23+
new B,
24+
new C,
25+
new D,
26+
];
27+
28+
foreach ($instances as $instance) {
29+
echo 'Class: ', $instance::class, PHP_EOL;
30+
$rc = new ReflectionClass($instance);
31+
$methods = $rc->getMethods();
32+
foreach ($methods as $method) {
33+
echo "\tMethod: ", $method->name, PHP_EOL;
34+
$parameters = $method->getParameters();
35+
foreach ($parameters as $param) {
36+
$type = $param->getType();
37+
echo "\t\tType: ", $type, PHP_EOL;
38+
echo "\t\tInstance of: ", $type::class, PHP_EOL;
39+
$resolvedType = $type->resolveToNamedType();
40+
echo "\t\t\tResolved Type: ", $resolvedType, PHP_EOL;
41+
echo "\t\t\tInstance of: ", $resolvedType::class, PHP_EOL;
42+
43+
foreach ($instances as $arg) {
44+
try {
45+
$instance->{$method->name}($arg);
46+
} catch (\TypeError $e) {
47+
echo "\t\t\t\t", $e->getMessage(), PHP_EOL;
48+
}
49+
}
50+
}
51+
}
52+
}
53+
54+
?>
55+
--EXPECTF--
56+
Class: A
57+
Class: B
58+
Method: foo
59+
Type: self
60+
Instance of: ReflectionRelativeClassType
61+
Resolved Type: B
62+
Instance of: ReflectionNamedType
63+
B::foo(): Argument #1 ($o) must be of type B, A given, called in %s on line %d
64+
Class: C
65+
Method: bar
66+
Type: parent
67+
Instance of: ReflectionRelativeClassType
68+
Resolved Type: B
69+
Instance of: ReflectionNamedType
70+
C::bar(): Argument #1 ($o) must be of type B, A given, called in %s on line %d
71+
Method: ping
72+
Type: self
73+
Instance of: ReflectionRelativeClassType
74+
Resolved Type: C
75+
Instance of: ReflectionNamedType
76+
C::ping(): Argument #1 ($o) must be of type C, A given, called in %s on line %d
77+
C::ping(): Argument #1 ($o) must be of type C, B given, called in %s on line %d
78+
Method: foo
79+
Type: self
80+
Instance of: ReflectionRelativeClassType
81+
Resolved Type: B
82+
Instance of: ReflectionNamedType
83+
B::foo(): Argument #1 ($o) must be of type B, A given, called in %s on line %d
84+
Class: D
85+
Method: bar
86+
Type: parent
87+
Instance of: ReflectionRelativeClassType
88+
Resolved Type: B
89+
Instance of: ReflectionNamedType
90+
C::bar(): Argument #1 ($o) must be of type B, A given, called in %s on line %d
91+
Method: ping
92+
Type: self
93+
Instance of: ReflectionRelativeClassType
94+
Resolved Type: C
95+
Instance of: ReflectionNamedType
96+
C::ping(): Argument #1 ($o) must be of type C, A given, called in %s on line %d
97+
C::ping(): Argument #1 ($o) must be of type C, B given, called in %s on line %d
98+
Method: foo
99+
Type: self
100+
Instance of: ReflectionRelativeClassType
101+
Resolved Type: B
102+
Instance of: ReflectionNamedType
103+
B::foo(): Argument #1 ($o) must be of type B, A given, called in %s on line %d
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
--TEST--
2+
ReflectionTypes of relative class types (self, parent) in classes, by-ref parameter nullable types
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
8+
}
9+
10+
class B extends A {
11+
public function foo(?self &$o) { return $o; }
12+
}
13+
14+
class C extends B {
15+
public function bar(?parent &$o) { return $o; }
16+
public function ping(?self &$o) { return $o; }
17+
}
18+
19+
class D extends C {}
20+
21+
$instances = [
22+
new A,
23+
new B,
24+
new C,
25+
new D,
26+
];
27+
28+
foreach ($instances as $instance) {
29+
echo 'Class: ', $instance::class, PHP_EOL;
30+
$rc = new ReflectionClass($instance);
31+
$methods = $rc->getMethods();
32+
foreach ($methods as $method) {
33+
echo "\tMethod: ", $method->name, PHP_EOL;
34+
$parameters = $method->getParameters();
35+
foreach ($parameters as $param) {
36+
$type = $param->getType();
37+
echo "\t\tType: ", $type, PHP_EOL;
38+
echo "\t\tInstance of: ", $type::class, PHP_EOL;
39+
$resolvedType = $type->resolveToNamedType();
40+
echo "\t\t\tResolved Type: ", $resolvedType, PHP_EOL;
41+
echo "\t\t\tInstance of: ", $resolvedType::class, PHP_EOL;
42+
43+
foreach ($instances as $arg) {
44+
try {
45+
$instance->{$method->name}($arg);
46+
} catch (\TypeError $e) {
47+
echo "\t\t\t\t", $e->getMessage(), PHP_EOL;
48+
}
49+
}
50+
}
51+
}
52+
}
53+
54+
?>
55+
--EXPECTF--
56+
Class: A
57+
Class: B
58+
Method: foo
59+
Type: ?self
60+
Instance of: ReflectionRelativeClassType
61+
Resolved Type: ?B
62+
Instance of: ReflectionNamedType
63+
B::foo(): Argument #1 ($o) must be of type ?B, A given, called in %s on line %d
64+
Class: C
65+
Method: bar
66+
Type: ?parent
67+
Instance of: ReflectionRelativeClassType
68+
Resolved Type: ?B
69+
Instance of: ReflectionNamedType
70+
C::bar(): Argument #1 ($o) must be of type ?B, A given, called in %s on line %d
71+
Method: ping
72+
Type: ?self
73+
Instance of: ReflectionRelativeClassType
74+
Resolved Type: ?C
75+
Instance of: ReflectionNamedType
76+
C::ping(): Argument #1 ($o) must be of type ?C, A given, called in %s on line %d
77+
C::ping(): Argument #1 ($o) must be of type ?C, B given, called in %s on line %d
78+
Method: foo
79+
Type: ?self
80+
Instance of: ReflectionRelativeClassType
81+
Resolved Type: ?B
82+
Instance of: ReflectionNamedType
83+
B::foo(): Argument #1 ($o) must be of type ?B, A given, called in %s on line %d
84+
Class: D
85+
Method: bar
86+
Type: ?parent
87+
Instance of: ReflectionRelativeClassType
88+
Resolved Type: ?B
89+
Instance of: ReflectionNamedType
90+
C::bar(): Argument #1 ($o) must be of type ?B, A given, called in %s on line %d
91+
Method: ping
92+
Type: ?self
93+
Instance of: ReflectionRelativeClassType
94+
Resolved Type: ?C
95+
Instance of: ReflectionNamedType
96+
C::ping(): Argument #1 ($o) must be of type ?C, A given, called in %s on line %d
97+
C::ping(): Argument #1 ($o) must be of type ?C, B given, called in %s on line %d
98+
Method: foo
99+
Type: ?self
100+
Instance of: ReflectionRelativeClassType
101+
Resolved Type: ?B
102+
Instance of: ReflectionNamedType
103+
B::foo(): Argument #1 ($o) must be of type ?B, A given, called in %s on line %d
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
--TEST--
2+
ReflectionTypes of relative class types (self, parent) in classes, by-ref parameter union types
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
8+
}
9+
10+
class B extends A {
11+
public function foo(int|self &$o) { return $o; }
12+
}
13+
14+
class C extends B {
15+
public function bar(int|parent &$o) { return $o; }
16+
public function ping(int|self &$o) { return $o; }
17+
}
18+
19+
class D extends C {}
20+
21+
$instances = [
22+
new A,
23+
new B,
24+
new C,
25+
new D,
26+
];
27+
28+
foreach ($instances as $instance) {
29+
echo 'Class: ', $instance::class, PHP_EOL;
30+
$rc = new ReflectionClass($instance);
31+
$methods = $rc->getMethods();
32+
foreach ($methods as $method) {
33+
echo "\tMethod: ", $method->name, PHP_EOL;
34+
$parameters = $method->getParameters();
35+
foreach ($parameters as $param) {
36+
$unionType = $param->getType();
37+
$types = $unionType->getTypes();
38+
foreach ($types as $type) {
39+
if (!($type instanceof ReflectionRelativeClassType)) {
40+
// Do not care about "int" type here;
41+
continue;
42+
}
43+
echo "\t\tType: ", $type, PHP_EOL;
44+
echo "\t\tInstance of: ", $type::class, PHP_EOL;
45+
$resolvedType = $type->resolveToNamedType();
46+
echo "\t\t\tResolved Type: ", $resolvedType, PHP_EOL;
47+
echo "\t\t\tInstance of: ", $resolvedType::class, PHP_EOL;
48+
49+
foreach ($instances as $arg) {
50+
try {
51+
$instance->{$method->name}($arg);
52+
} catch (\TypeError $e) {
53+
echo "\t\t\t\t", $e->getMessage(), PHP_EOL;
54+
}
55+
}
56+
}
57+
}
58+
}
59+
}
60+
61+
?>
62+
--EXPECTF--
63+
Class: A
64+
Class: B
65+
Method: foo
66+
Type: self
67+
Instance of: ReflectionRelativeClassType
68+
Resolved Type: B
69+
Instance of: ReflectionNamedType
70+
B::foo(): Argument #1 ($o) must be of type B|int, A given, called in %s on line %d
71+
Class: C
72+
Method: bar
73+
Type: parent
74+
Instance of: ReflectionRelativeClassType
75+
Resolved Type: B
76+
Instance of: ReflectionNamedType
77+
C::bar(): Argument #1 ($o) must be of type B|int, A given, called in %s on line %d
78+
Method: ping
79+
Type: self
80+
Instance of: ReflectionRelativeClassType
81+
Resolved Type: C
82+
Instance of: ReflectionNamedType
83+
C::ping(): Argument #1 ($o) must be of type C|int, A given, called in %s on line %d
84+
C::ping(): Argument #1 ($o) must be of type C|int, B given, called in %s on line %d
85+
Method: foo
86+
Type: self
87+
Instance of: ReflectionRelativeClassType
88+
Resolved Type: B
89+
Instance of: ReflectionNamedType
90+
B::foo(): Argument #1 ($o) must be of type B|int, A given, called in %s on line %d
91+
Class: D
92+
Method: bar
93+
Type: parent
94+
Instance of: ReflectionRelativeClassType
95+
Resolved Type: B
96+
Instance of: ReflectionNamedType
97+
C::bar(): Argument #1 ($o) must be of type B|int, A given, called in %s on line %d
98+
Method: ping
99+
Type: self
100+
Instance of: ReflectionRelativeClassType
101+
Resolved Type: C
102+
Instance of: ReflectionNamedType
103+
C::ping(): Argument #1 ($o) must be of type C|int, A given, called in %s on line %d
104+
C::ping(): Argument #1 ($o) must be of type C|int, B given, called in %s on line %d
105+
Method: foo
106+
Type: self
107+
Instance of: ReflectionRelativeClassType
108+
Resolved Type: B
109+
Instance of: ReflectionNamedType
110+
B::foo(): Argument #1 ($o) must be of type B|int, A given, called in %s on line %d

0 commit comments

Comments
 (0)