- 在 ArgInfo 中新增 typeCheck、typeStr 和 typeNode 属性用于类型检查 - 在 FunctionDef 中新增 returnTypeCheck、returnTypeStr 和 returnTypeNode 属性 - 实现 buildTypeCheckFromNode 方法解析联合/可空类型节点 - 实现 genSingleTypeCondition 方法生成单个类型检查条件 - 实现 genUnionParamCheck 方法生成参数类型检查代码块 - 实现 genUnionReturnCheck 方法生成返回值类型检查代码块 - 在编译过程中集成参数和返回值的运行时类型检查 - 添加 union-param-check.phpt 和 union-return-check.phpt 测试用例 - 支持基本类型、类类型和特殊类型的联合类型检查 - 实现详细的错误消息生成机制pull/1/head
parent
593c6ec2a5
commit
3b5345d68e
6 changed files with 425 additions and 3 deletions
@ -0,0 +1,102 @@ |
||||
--TEST-- |
||||
Union type: parameter runtime type checking |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function expect_int_or_string(int|string $x): void { |
||||
var_dump($x); |
||||
} |
||||
|
||||
function expect_int_or_string_or_null(int|string|null $x): void { |
||||
var_dump($x); |
||||
} |
||||
|
||||
function expect_int_or_float(int|float $x): void { |
||||
var_dump($x); |
||||
} |
||||
|
||||
function expect_nullable_int(?int $x): void { |
||||
var_dump($x); |
||||
} |
||||
|
||||
function expect_nullable_string(?string $x): void { |
||||
var_dump($x); |
||||
} |
||||
|
||||
function expect_bool_or_array(bool|array $x): void { |
||||
var_dump($x); |
||||
} |
||||
|
||||
function main() { |
||||
// Valid calls - should pass |
||||
expect_int_or_string(42); |
||||
expect_int_or_string("hello"); |
||||
expect_int_or_string_or_null(42); |
||||
expect_int_or_string_or_null("hello"); |
||||
expect_int_or_string_or_null(null); |
||||
expect_int_or_float(42); |
||||
expect_int_or_float(3.14); |
||||
expect_nullable_int(42); |
||||
expect_nullable_int(null); |
||||
expect_nullable_string("test"); |
||||
expect_nullable_string(null); |
||||
expect_bool_or_array(true); |
||||
expect_bool_or_array([1, 2, 3]); |
||||
|
||||
// Invalid calls - should throw TypeError |
||||
$errors = []; |
||||
|
||||
try { |
||||
expect_int_or_string(3.14); |
||||
} catch (\TypeError $e) { |
||||
$errors[] = $e->getMessage(); |
||||
} |
||||
|
||||
try { |
||||
expect_int_or_string([]); |
||||
} catch (\TypeError $e) { |
||||
$errors[] = $e->getMessage(); |
||||
} |
||||
|
||||
try { |
||||
expect_nullable_int("hello"); |
||||
} catch (\TypeError $e) { |
||||
$errors[] = $e->getMessage(); |
||||
} |
||||
|
||||
try { |
||||
expect_bool_or_array(42); |
||||
} catch (\TypeError $e) { |
||||
$errors[] = $e->getMessage(); |
||||
} |
||||
|
||||
foreach ($errors as $err) { |
||||
var_dump($err); |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(42) |
||||
string(5) "hello" |
||||
int(42) |
||||
string(5) "hello" |
||||
NULL |
||||
int(42) |
||||
float(3.14) |
||||
int(42) |
||||
NULL |
||||
string(4) "test" |
||||
NULL |
||||
bool(true) |
||||
array(3) { |
||||
[0]=> |
||||
int(1) |
||||
[1]=> |
||||
int(2) |
||||
[2]=> |
||||
int(3) |
||||
} |
||||
string(80) "expect_int_or_string(): Argument #1 ($x) must be of type int|string, float given" |
||||
string(80) "expect_int_or_string(): Argument #1 ($x) must be of type int|string, array given" |
||||
string(74) "expect_nullable_int(): Argument #1 ($x) must be of type ?int, string given" |
||||
string(78) "expect_bool_or_array(): Argument #1 ($x) must be of type bool|array, int given" |
||||
@ -0,0 +1,69 @@ |
||||
--TEST-- |
||||
Union type: return runtime type checking |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function return_int_or_string($value): int|string { |
||||
return $value; |
||||
} |
||||
|
||||
function return_nullable_int($value): ?int { |
||||
return $value; |
||||
} |
||||
|
||||
function return_int_or_float($value): int|float { |
||||
return $value; |
||||
} |
||||
|
||||
function main() { |
||||
// Valid returns - should pass |
||||
var_dump(return_int_or_string(42)); |
||||
var_dump(return_int_or_string("hello")); |
||||
var_dump(return_nullable_int(42)); |
||||
var_dump(return_nullable_int(null)); |
||||
var_dump(return_int_or_float(42)); |
||||
var_dump(return_int_or_float(3.14)); |
||||
|
||||
// Invalid returns - should throw TypeError |
||||
$errors = []; |
||||
|
||||
try { |
||||
return_int_or_string(3.14); |
||||
} catch (\TypeError $e) { |
||||
$errors[] = $e->getMessage(); |
||||
} |
||||
|
||||
try { |
||||
return_int_or_string([]); |
||||
} catch (\TypeError $e) { |
||||
$errors[] = $e->getMessage(); |
||||
} |
||||
|
||||
try { |
||||
return_nullable_int("hello"); |
||||
} catch (\TypeError $e) { |
||||
$errors[] = $e->getMessage(); |
||||
} |
||||
|
||||
try { |
||||
return_int_or_float("hello"); |
||||
} catch (\TypeError $e) { |
||||
$errors[] = $e->getMessage(); |
||||
} |
||||
|
||||
foreach ($errors as $err) { |
||||
var_dump($err); |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(42) |
||||
string(5) "hello" |
||||
int(42) |
||||
NULL |
||||
int(42) |
||||
float(3.14) |
||||
string(76) "return_int_or_string(): Return value must be of type int|string, float given" |
||||
string(76) "return_int_or_string(): Return value must be of type int|string, array given" |
||||
string(70) "return_nullable_int(): Return value must be of type ?int, string given" |
||||
string(75) "return_int_or_float(): Return value must be of type int|float, string given" |
||||
Loading…
Reference in new issue