mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
- Added scalar typehinting.
This commit is contained in:
parent
f291a1253d
commit
1bc9247651
1
NEWS
1
NEWS
@ -36,6 +36,7 @@
|
||||
FR #51815. (Pierrick)
|
||||
- Added iterator support in MySQLi. mysqli_result implements Traversable.
|
||||
(Andrey, Johannes)
|
||||
- Added scalar typehinting. (Ilia, Derick)
|
||||
|
||||
- default_charset if not specified is now UTF-8 instead of ISO-8859-1. (Rasmus)
|
||||
|
||||
|
@ -12,4 +12,4 @@ foo(123);
|
||||
--EXPECTF--
|
||||
3
|
||||
|
||||
Catchable fatal error: Argument 1 passed to foo() must be an array, integer given, called in %sarray_type_hint_001.php on line 7 and defined in %sarray_type_hint_001.php on line 2
|
||||
Catchable fatal error: Argument 1 passed to foo() must be of the type array, integer given, called in %sarray_type_hint_001.php on line 7 and defined in %sarray_type_hint_001.php on line 2
|
||||
|
38
Zend/tests/hint/param_type_hint_001.phpt
Normal file
38
Zend/tests/hint/param_type_hint_001.phpt
Normal file
@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing integer hint
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test_int($x, int $a = 1) {
|
||||
}
|
||||
|
||||
test_int(1);
|
||||
print "Ok\n";
|
||||
|
||||
test_int('1211');
|
||||
print "Ok\n";
|
||||
|
||||
test_int(null);
|
||||
print "Ok\n";
|
||||
|
||||
test_int(1, 1);
|
||||
print "Ok\n";
|
||||
|
||||
test_int(null, '1211');
|
||||
print "Ok\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Ok
|
||||
Ok
|
||||
Ok
|
||||
Ok
|
||||
|
||||
Catchable fatal error: Argument 2 passed to test_int() must be of the type integer, string given, called in %s on line %d and defined in %s on line %d
|
||||
--UEXPECTF--
|
||||
Ok
|
||||
Ok
|
||||
Ok
|
||||
Ok
|
||||
|
||||
Catchable fatal error: Argument 2 passed to test_int() must be of the type integer, Unicode string given, called in %s on line %d and defined in %s on line %d
|
97
Zend/tests/hint/param_type_hint_002.phpt
Normal file
97
Zend/tests/hint/param_type_hint_002.phpt
Normal file
@ -0,0 +1,97 @@
|
||||
--TEST--
|
||||
Parameter type hint - Reflection
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(int $a, double $b, string $c, boolean $d = true, resource $e, array $f = array(), object $g) {
|
||||
}
|
||||
|
||||
$func = new ReflectionFunction('test');
|
||||
Reflection::Export($func);
|
||||
|
||||
foreach ($func->getParameters() as $i => $param) {
|
||||
printf(
|
||||
"-- Parameter #%d: %s {\n".
|
||||
" Allows NULL: %s\n".
|
||||
" Hint Type: %s\n".
|
||||
" Passed to by reference: %s\n".
|
||||
" Is optional?: %s\n",
|
||||
$i,
|
||||
$param->getName(),
|
||||
var_export($param->getClass(), 1),
|
||||
$param->getTypeHint(),
|
||||
var_export($param->allowsNull(), 1),
|
||||
var_export($param->isPassedByReference(), 1),
|
||||
$param->isOptional() ? 'yes' : 'no'
|
||||
);
|
||||
printf(" Int: %d | Double: %d | Bool: %d | String: %d | Resource: %d | Array: %d | Object: %d\n",
|
||||
$param->isInt(), $param->isDouble(), $param->isBool(), $param->isString(),
|
||||
$param->isResource(), $param->isArray(), $param->isObject());
|
||||
print "}\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Function [ <user> function test ] {
|
||||
@@ %s 3 - 4
|
||||
|
||||
- Parameters [7] {
|
||||
Parameter #0 [ <required> integer $a ]
|
||||
Parameter #1 [ <required> double $b ]
|
||||
Parameter #2 [ <required> string $c ]
|
||||
Parameter #3 [ <required> boolean $d ]
|
||||
Parameter #4 [ <required> resource $e ]
|
||||
Parameter #5 [ <required> array $f ]
|
||||
Parameter #6 [ <required> object $g ]
|
||||
}
|
||||
}
|
||||
|
||||
-- Parameter #0: a {
|
||||
Allows NULL: NULL
|
||||
Hint Type: integer
|
||||
Passed to by reference: false
|
||||
Is optional?: false
|
||||
Int: 1 | Double: 0 | Bool: 0 | String: 0 | Resource: 0 | Array: 0 | Object: 0
|
||||
}
|
||||
-- Parameter #1: b {
|
||||
Allows NULL: NULL
|
||||
Hint Type: double
|
||||
Passed to by reference: false
|
||||
Is optional?: false
|
||||
Int: 0 | Double: 1 | Bool: 0 | String: 0 | Resource: 0 | Array: 0 | Object: 0
|
||||
}
|
||||
-- Parameter #2: c {
|
||||
Allows NULL: NULL
|
||||
Hint Type: string
|
||||
Passed to by reference: false
|
||||
Is optional?: false
|
||||
Int: 0 | Double: 0 | Bool: 0 | String: 1 | Resource: 0 | Array: 0 | Object: 0
|
||||
}
|
||||
-- Parameter #3: d {
|
||||
Allows NULL: NULL
|
||||
Hint Type: boolean
|
||||
Passed to by reference: false
|
||||
Is optional?: false
|
||||
Int: 0 | Double: 0 | Bool: 1 | String: 0 | Resource: 0 | Array: 0 | Object: 0
|
||||
}
|
||||
-- Parameter #4: e {
|
||||
Allows NULL: NULL
|
||||
Hint Type: resource
|
||||
Passed to by reference: false
|
||||
Is optional?: false
|
||||
Int: 0 | Double: 0 | Bool: 0 | String: 0 | Resource: 1 | Array: 0 | Object: 0
|
||||
}
|
||||
-- Parameter #5: f {
|
||||
Allows NULL: NULL
|
||||
Hint Type: array
|
||||
Passed to by reference: false
|
||||
Is optional?: false
|
||||
Int: 0 | Double: 0 | Bool: 0 | String: 0 | Resource: 0 | Array: 1 | Object: 0
|
||||
}
|
||||
-- Parameter #6: g {
|
||||
Allows NULL: NULL
|
||||
Hint Type: object
|
||||
Passed to by reference: false
|
||||
Is optional?: false
|
||||
Int: 0 | Double: 0 | Bool: 0 | String: 0 | Resource: 0 | Array: 0 | Object: 1
|
||||
}
|
16
Zend/tests/hint/param_type_hint_003.phpt
Normal file
16
Zend/tests/hint/param_type_hint_003.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Parameter type hint - Wrong parameter for integer
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test_int(int $a) {
|
||||
echo $a, "\n";
|
||||
}
|
||||
|
||||
test_int('+1');
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Catchable fatal error: Argument 1 passed to test_int() must be of the type integer, string given, called in %s on line %d and defined in %s on line %d
|
||||
--UEXPECTF--
|
||||
Catchable fatal error: Argument 1 passed to test_int() must be of the type integer, Unicode string given, called in %s on line %d and defined in %s on line %d
|
16
Zend/tests/hint/param_type_hint_004.phpt
Normal file
16
Zend/tests/hint/param_type_hint_004.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Parameter type hint - Wrong parameter for double
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test_double(real $a) {
|
||||
echo $a, "\n";
|
||||
}
|
||||
|
||||
test_double('+1.1');
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Catchable fatal error: Argument 1 passed to test_double() must be of the type double, string given, called in %s on line %d and defined in %s on line %d
|
||||
--UEXPECTF--
|
||||
Catchable fatal error: Argument 1 passed to test_double() must be of the type double, Unicode string given, called in %s on line %d and defined in %s on line %d
|
23
Zend/tests/hint/param_type_hint_005.phpt
Normal file
23
Zend/tests/hint/param_type_hint_005.phpt
Normal file
@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
Parameter type hint - Wrong parameter for string
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test_str(string $a) {
|
||||
echo $a, "\n";
|
||||
}
|
||||
|
||||
test_str('+1.1');
|
||||
test_str('-.1');
|
||||
test_str('11213111112321312');
|
||||
test_str('');
|
||||
test_str(null);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
+1.1
|
||||
-.1
|
||||
11213111112321312
|
||||
|
||||
|
||||
Catchable fatal error: Argument 1 passed to test_str() must be of the type string, null given, called in %s on line %d and defined in %s on line %d
|
22
Zend/tests/hint/param_type_hint_006.phpt
Normal file
22
Zend/tests/hint/param_type_hint_006.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing NULL when allowed
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test_int(int $a = null) {
|
||||
}
|
||||
test_int(null);
|
||||
|
||||
function test_double(double $a = null) {
|
||||
}
|
||||
test_double(null);
|
||||
|
||||
function test_bool(bool $a = null) {
|
||||
}
|
||||
test_bool(null);
|
||||
|
||||
print "Done";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
46
Zend/tests/hint/param_type_hint_007.phpt
Normal file
46
Zend/tests/hint/param_type_hint_007.phpt
Normal file
@ -0,0 +1,46 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing parameter with reference
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/* string */
|
||||
function test_string(string &$a) {
|
||||
$a .= '!!!';
|
||||
}
|
||||
|
||||
$str = 'foo';
|
||||
test_string($str);
|
||||
var_dump($str);
|
||||
|
||||
/* integer */
|
||||
function test_int(int &$b) {
|
||||
$b += 2;
|
||||
}
|
||||
|
||||
$b = 2;
|
||||
test_int($b);
|
||||
var_dump($b);
|
||||
|
||||
/* object */
|
||||
function test_obj(object &$c) {
|
||||
$c->tested = 1;
|
||||
}
|
||||
$c = new stdclass;
|
||||
test_obj($c);
|
||||
var_dump($c);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(6) "foo!!!"
|
||||
int(4)
|
||||
object(stdClass)#1 (1) {
|
||||
["tested"]=>
|
||||
int(1)
|
||||
}
|
||||
--UEXPECT--
|
||||
unicode(6) "foo!!!"
|
||||
int(4)
|
||||
object(stdClass)#1 (1) {
|
||||
[u"tested"]=>
|
||||
int(1)
|
||||
}
|
20
Zend/tests/hint/param_type_hint_008.phpt
Normal file
20
Zend/tests/hint/param_type_hint_008.phpt
Normal file
@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing string type hint with reference
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(string &$a) {
|
||||
$a .= '!!!';
|
||||
}
|
||||
|
||||
$x = 'foo';
|
||||
|
||||
test($x);
|
||||
|
||||
var_dump($x);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(6) "foo!!!"
|
||||
--UEXPECT--
|
||||
unicode(6) "foo!!!"
|
17
Zend/tests/hint/param_type_hint_009.phpt
Normal file
17
Zend/tests/hint/param_type_hint_009.phpt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing default parameter value
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(string &$a, integer $x = 1) {
|
||||
var_dump($x);
|
||||
}
|
||||
|
||||
$y = 'foo';
|
||||
test($y, 2);
|
||||
test($y);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(2)
|
||||
int(1)
|
28
Zend/tests/hint/param_type_hint_010.phpt
Normal file
28
Zend/tests/hint/param_type_hint_010.phpt
Normal file
@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing with heredoc
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(string $str) {
|
||||
}
|
||||
|
||||
test(<<<FOO
|
||||
test!
|
||||
FOO
|
||||
);
|
||||
|
||||
test(<<<'FOO'
|
||||
test!
|
||||
FOO
|
||||
);
|
||||
|
||||
test(<<<"FOO"
|
||||
test!
|
||||
FOO
|
||||
);
|
||||
|
||||
print "Ok!";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Ok!
|
15
Zend/tests/hint/param_type_hint_011.phpt
Normal file
15
Zend/tests/hint/param_type_hint_011.phpt
Normal file
@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing with undefined variable
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(string $a) {
|
||||
}
|
||||
|
||||
test($x);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Notice: Undefined variable: x in %s on line %d
|
||||
|
||||
Catchable fatal error: Argument 1 passed to test() must be of the type string, null given, called in %s on line %d and defined in %s on line %d
|
18
Zend/tests/hint/param_type_hint_012.phpt
Normal file
18
Zend/tests/hint/param_type_hint_012.phpt
Normal file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing with lambda function
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$test = create_function('integer $i', 'return $i + 1;');
|
||||
var_dump($test(1));
|
||||
var_dump($test('foo'));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(2)
|
||||
|
||||
Catchable fatal error: Argument 1 passed to __lambda_func() must be of the type integer, string given, called in %s on line %d and defined in %s(%d) : runtime-created function on line %d
|
||||
--UEXPECTF--
|
||||
int(2)
|
||||
|
||||
Catchable fatal error: Argument 1 passed to __lambda_func() must be of the type integer, Unicode string given, called in %s on line %d and defined in %s(%d) : runtime-created function on line %d
|
16
Zend/tests/hint/param_type_hint_013.phpt
Normal file
16
Zend/tests/hint/param_type_hint_013.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing with lambda function using 2 parameters
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$test = create_function('integer $i, string $j', 'return $i + $j;');
|
||||
var_dump($test(1, 'foo'));
|
||||
var_dump($test(1, '1'));
|
||||
var_dump($test(1, NULL));
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(1)
|
||||
int(2)
|
||||
|
||||
Catchable fatal error: Argument 2 passed to __lambda_func() must be of the type string, null given, called in %s on line %d and defined in %s(%d) : runtime-created function on line %d
|
16
Zend/tests/hint/param_type_hint_014.phpt
Normal file
16
Zend/tests/hint/param_type_hint_014.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing in function inside function
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function a() {
|
||||
function b(real $c) {
|
||||
}
|
||||
return b(1);
|
||||
}
|
||||
|
||||
a();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Catchable fatal error: Argument 1 passed to b() must be of the type double, integer given, called in %s on line %d and defined in %s on line %d
|
19
Zend/tests/hint/param_type_hint_015.phpt
Normal file
19
Zend/tests/hint/param_type_hint_015.phpt
Normal file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing with call_user_func()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(bool $b) {
|
||||
print "ok\n";
|
||||
}
|
||||
|
||||
call_user_func('test', true);
|
||||
call_user_func('test', false);
|
||||
call_user_func('test', NULL);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
ok
|
||||
ok
|
||||
|
||||
Catchable fatal error: Argument 1 passed to test() must be of the type boolean, null given in %s on line %d
|
22
Zend/tests/hint/param_type_hint_016.phpt
Normal file
22
Zend/tests/hint/param_type_hint_016.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing default parameter values
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(string $a, bool $b = NULL, integer $c, double $d = NULL, $e) {
|
||||
print "ok\n";
|
||||
}
|
||||
|
||||
test('foo', NULL, 1, NULL, 'bar');
|
||||
test('foo', true, 0, -1., NULL);
|
||||
test('true', false, -1, 2.2222, 1.1);
|
||||
test('1.1', false, -1, 11111111111111111111111111, true);
|
||||
test('1', false, -1, NULL, new stdClass);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
||||
ok
|
14
Zend/tests/hint/param_type_hint_017.phpt
Normal file
14
Zend/tests/hint/param_type_hint_017.phpt
Normal file
@ -0,0 +1,14 @@
|
||||
--TEST--
|
||||
Parameter type hint - Testing default parameter values as constants
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function test(int $foo = PHP_INT_MAX) {
|
||||
print "ok\n";
|
||||
}
|
||||
|
||||
test();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
ok
|
@ -18,4 +18,4 @@ new bar(new \stdclass);
|
||||
--EXPECTF--
|
||||
NULL
|
||||
|
||||
Catchable fatal error: Argument 1 passed to foo\bar::__construct() must be an array, object given, called in %s on line %d and defined in %s on line %d
|
||||
Catchable fatal error: Argument 1 passed to foo\bar::__construct() must be of the type array, object given, called in %s on line %d and defined in %s on line %d
|
||||
|
@ -566,6 +566,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
|
||||
#define IS_RESOURCE 7
|
||||
#define IS_CONSTANT 8
|
||||
#define IS_CONSTANT_ARRAY 9
|
||||
/* used for type-hinting only */
|
||||
#define IS_CLASS 10
|
||||
|
||||
/* Ugly hack to support constants as static array indices */
|
||||
#define IS_CONSTANT_TYPE_MASK 0x00f
|
||||
|
@ -206,6 +206,7 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
|
||||
case IS_STRING:
|
||||
return "string";
|
||||
case IS_OBJECT:
|
||||
case IS_CLASS:
|
||||
return "object";
|
||||
case IS_RESOURCE:
|
||||
return "resource";
|
||||
|
@ -98,8 +98,9 @@ typedef struct _zend_fcall_info_cache {
|
||||
|
||||
#define ZEND_ARG_INFO(pass_by_ref, name) { #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
|
||||
#define ZEND_ARG_PASS_INFO(pass_by_ref) { NULL, 0, NULL, 0, 0, 0, pass_by_ref, 0, 0 },
|
||||
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, 0, allow_null, pass_by_ref, 0, 0 },
|
||||
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, 1, allow_null, pass_by_ref, 0, 0 },
|
||||
#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_CLASS, allow_null, pass_by_ref, 0, 0 },
|
||||
#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, allow_null, pass_by_ref, 0, 0 },
|
||||
#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, sizeof(#name)-1, NULL, 0, type_hint, allow_null, pass_by_ref, 0, 0 },
|
||||
#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \
|
||||
static const zend_arg_info name[] = { \
|
||||
{ NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args },
|
||||
|
@ -1807,7 +1807,7 @@ void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, con
|
||||
cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
|
||||
cur_arg_info->name = CG(new_interned_string)(estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len), varname->u.constant.value.str.len + 1, 1 TSRMLS_CC);
|
||||
cur_arg_info->name_len = varname->u.constant.value.str.len;
|
||||
cur_arg_info->array_type_hint = 0;
|
||||
cur_arg_info->type_hint = 0;
|
||||
cur_arg_info->allow_null = 1;
|
||||
cur_arg_info->pass_by_reference = pass_by_reference;
|
||||
cur_arg_info->class_name = NULL;
|
||||
@ -1815,7 +1815,10 @@ void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, con
|
||||
|
||||
if (class_type->op_type != IS_UNUSED) {
|
||||
cur_arg_info->allow_null = 0;
|
||||
if (class_type->u.constant.type == IS_STRING) {
|
||||
cur_arg_info->type_hint = class_type->u.constant.type;
|
||||
|
||||
switch (class_type->u.constant.type) {
|
||||
case IS_CLASS:
|
||||
if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
|
||||
zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC);
|
||||
}
|
||||
@ -1829,10 +1832,9 @@ void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, con
|
||||
zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cur_arg_info->array_type_hint = 1;
|
||||
cur_arg_info->class_name = NULL;
|
||||
cur_arg_info->class_name_len = 0;
|
||||
break;
|
||||
|
||||
case IS_ARRAY:
|
||||
if (op == ZEND_RECV_INIT) {
|
||||
if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
|
||||
cur_arg_info->allow_null = 1;
|
||||
@ -1840,6 +1842,26 @@ void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, con
|
||||
zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* scalar type hinting */
|
||||
case IS_BOOL:
|
||||
case IS_STRING:
|
||||
case IS_LONG:
|
||||
case IS_DOUBLE:
|
||||
case IS_RESOURCE:
|
||||
case IS_OBJECT:
|
||||
if (op == ZEND_RECV_INIT) {
|
||||
if (Z_TYPE(initialization->u.constant) != class_type->u.constant.type && Z_TYPE(initialization->u.constant) != IS_NULL && (Z_TYPE(initialization->u.constant) & IS_CONSTANT_TYPE_MASK) != IS_CONSTANT) {
|
||||
zend_error(E_COMPILE_ERROR, "Default value for parameters with %s type hint can only be %s or NULL", zend_get_type_by_const(class_type->u.constant.type), zend_get_type_by_const(class_type->u.constant.type));
|
||||
} else if (Z_TYPE(initialization->u.constant) == IS_NULL) {
|
||||
cur_arg_info->allow_null = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
zend_error(E_COMPILE_ERROR, "Unknown type hint");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2868,8 +2890,8 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (fe->common.arg_info[i].array_type_hint != proto->common.arg_info[i].array_type_hint) {
|
||||
/* Only one has an array type hint and the other one doesn't */
|
||||
if (fe->common.arg_info[i].type_hint != proto->common.arg_info[i].type_hint) {
|
||||
/* Incompatible type hint */
|
||||
return 0;
|
||||
}
|
||||
if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) {
|
||||
|
@ -194,7 +194,7 @@ typedef struct _zend_arg_info {
|
||||
zend_uint name_len;
|
||||
const char *class_name;
|
||||
zend_uint class_name_len;
|
||||
zend_bool array_type_hint;
|
||||
zend_uint type_hint;
|
||||
zend_bool allow_null;
|
||||
zend_bool pass_by_reference;
|
||||
zend_bool return_reference;
|
||||
|
@ -671,13 +671,21 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva
|
||||
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
|
||||
return zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
|
||||
}
|
||||
} else if (cur_arg_info->array_type_hint) {
|
||||
} else if (cur_arg_info->type_hint) {
|
||||
if (!arg) {
|
||||
return zend_verify_arg_error(zf, arg_num, "be an array", "", "none", "" TSRMLS_CC);
|
||||
return zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "" TSRMLS_CC);
|
||||
}
|
||||
if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
|
||||
return zend_verify_arg_error(zf, arg_num, "be an array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
|
||||
|
||||
/* existing type already matches the hint or forced type */
|
||||
if (Z_TYPE_P(arg) == cur_arg_info->type_hint) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* NULL type given, check if parameter is optional */
|
||||
if (Z_TYPE_P(arg) == IS_NULL && cur_arg_info->allow_null) {
|
||||
return 1;
|
||||
}
|
||||
return zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "", zend_zval_type_name(arg) TSRMLS_CC);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -130,6 +130,12 @@
|
||||
%token T_DOUBLE_ARROW
|
||||
%token T_LIST
|
||||
%token T_ARRAY
|
||||
%token T_BOOL_HINT
|
||||
%token T_STRING_HINT
|
||||
%token T_INT_HINT
|
||||
%token T_DOUBLE_HINT
|
||||
%token T_RESOURCE_HINT
|
||||
%token T_OBJECT_HINT
|
||||
%token T_CLASS_C
|
||||
%token T_METHOD_C
|
||||
%token T_FUNC_C
|
||||
@ -466,8 +472,14 @@ non_empty_parameter_list:
|
||||
|
||||
optional_class_type:
|
||||
/* empty */ { $$.op_type = IS_UNUSED; }
|
||||
| fully_qualified_class_name { $$ = $1; }
|
||||
| T_ARRAY { $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_NULL;}
|
||||
| T_ARRAY { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_ARRAY; }
|
||||
| T_BOOL_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_BOOL; }
|
||||
| T_STRING_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_STRING; }
|
||||
| T_INT_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_LONG; }
|
||||
| T_DOUBLE_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_DOUBLE; }
|
||||
| T_RESOURCE_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_RESOURCE; }
|
||||
| T_OBJECT_HINT { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_OBJECT; }
|
||||
| fully_qualified_class_name { $$ = $1; $$.op_type = IS_CONST; Z_TYPE($$.u.constant)=IS_CLASS; }
|
||||
;
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1172,6 +1172,52 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
return T_ARRAY;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>("bool"|"boolean"){TABS_AND_SPACES}[ \t&]+"$" {
|
||||
if (yytext[4] == 'e') {
|
||||
yyless((sizeof("boolean") - 1));
|
||||
} else {
|
||||
yyless((sizeof("bool") - 1));
|
||||
}
|
||||
return T_BOOL_HINT;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>("string"|"binary"){TABS_AND_SPACES}[ \t&]+"$" {
|
||||
yyless(6);
|
||||
return T_STRING_HINT;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>("int"|"integer"|"long"){TABS_AND_SPACES}[ \t&]+"$" {
|
||||
if (yytext[3] == 'e') {
|
||||
yyless((sizeof("integer") - 1));
|
||||
} else if (yytext[3] == 'g') {
|
||||
yyless((sizeof("long") - 1));
|
||||
} else {
|
||||
yyless(3);
|
||||
}
|
||||
return T_INT_HINT;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>("real"|"double"|"float"){TABS_AND_SPACES}[ \t&]+"$" {
|
||||
if (yytext[4] == 'l') {
|
||||
yyless((sizeof("double") - 1));
|
||||
} else if (yytext[4] == 't') {
|
||||
yyless((sizeof("float") - 1));
|
||||
} else {
|
||||
yyless(4);
|
||||
}
|
||||
return T_DOUBLE_HINT;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"resource"{TABS_AND_SPACES}[ \t&]+"$" {
|
||||
yyless((sizeof("resource") - 1));
|
||||
return T_RESOURCE_HINT;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"object"{TABS_AND_SPACES}[ \t&]+"$" {
|
||||
yyless((sizeof("object") - 1));
|
||||
return T_OBJECT_HINT;
|
||||
}
|
||||
|
||||
<ST_IN_SCRIPTING>"++" {
|
||||
return T_INC;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Generated by re2c 0.13.5 on Thu Apr 22 23:49:41 2010 */
|
||||
/* Generated by re2c 0.13.5 on Thu May 20 09:19:36 2010 */
|
||||
#line 3 "Zend/zend_language_scanner_defs.h"
|
||||
|
||||
enum YYCONDTYPE {
|
||||
|
@ -674,8 +674,8 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
|
||||
if (arg_info->allow_null) {
|
||||
string_printf(str, "or NULL ");
|
||||
}
|
||||
} else if (arg_info->array_type_hint) {
|
||||
string_printf(str, "array ");
|
||||
} else if (arg_info->type_hint) {
|
||||
string_printf(str, "%s ", zend_get_type_by_const(arg_info->type_hint));
|
||||
if (arg_info->allow_null) {
|
||||
string_printf(str, "or NULL ");
|
||||
}
|
||||
@ -2338,7 +2338,102 @@ ZEND_METHOD(reflection_parameter, isArray)
|
||||
}
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
RETVAL_BOOL(param->arg_info->array_type_hint);
|
||||
RETVAL_BOOL(param->arg_info->type_hint == IS_ARRAY);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::isInt()
|
||||
Returns whether parameter MUST be a long */
|
||||
ZEND_METHOD(reflection_parameter, isInt)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
RETVAL_BOOL(param->arg_info->type_hint == IS_LONG);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::isDouble()
|
||||
Returns whether parameter MUST be a double */
|
||||
ZEND_METHOD(reflection_parameter, isDouble)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
RETVAL_BOOL(param->arg_info->type_hint == IS_DOUBLE);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::isBool()
|
||||
Returns whether parameter MUST be a boolean */
|
||||
ZEND_METHOD(reflection_parameter, isBool)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
RETVAL_BOOL(param->arg_info->type_hint == IS_BOOL);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::isObject()
|
||||
Returns whether parameter MUST be a boolean */
|
||||
ZEND_METHOD(reflection_parameter, isObject)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
RETVAL_BOOL(param->arg_info->type_hint == IS_OBJECT);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::isString()
|
||||
Returns whether parameter MUST be a string */
|
||||
ZEND_METHOD(reflection_parameter, isString)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
RETVAL_BOOL(param->arg_info->type_hint == IS_STRING);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::isResource()
|
||||
Returns whether parameter MUST be a resource */
|
||||
ZEND_METHOD(reflection_parameter, isResource)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
RETVAL_BOOL(param->arg_info->type_hint == IS_RESOURCE);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public string ReflectionParameter::getTypeHint()
|
||||
Returns what type hint is defined for this parameter */
|
||||
ZEND_METHOD(reflection_parameter, getTypeHint)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
if (!param->arg_info->type_hint) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
RETURN_STRING(zend_get_type_by_const(param->arg_info->type_hint), 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -5089,7 +5184,7 @@ ZEND_METHOD(reflection_extension, getDependencies)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public void ReflectionExtension::info() U
|
||||
/* {{{ proto public void ReflectionExtension::info()
|
||||
Prints phpinfo block for the extension */
|
||||
ZEND_METHOD(reflection_extension, info)
|
||||
{
|
||||
@ -5617,6 +5712,13 @@ static const zend_function_entry reflection_parameter_functions[] = {
|
||||
ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, isInt, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, isDouble, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, isBool, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, getTypeHint, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, isString, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, isObject, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, isResource, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, getPosition, arginfo_reflection__void, 0)
|
||||
ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
|
||||
|
Loading…
Reference in New Issue
Block a user