- 引入 NodeAbstract 类型用于对象转换 - 移除 Stmt_Nop 语句的空注释生成 - 为 Foreach 循环体添加前置语句解析 - 简化对象类型检查逻辑 - 添加多个类常量测试用例 - 在预处理器和翻译器中处理 Stmt_Nop 语句类型 - 完善类常量声明、继承和访问功能pull/1/head
parent
25e567b3db
commit
d90bf8a5fd
11 changed files with 373 additions and 11 deletions
@ -0,0 +1,88 @@ |
||||
--TEST-- |
||||
Class constant declarations |
||||
--SKIPIF-- |
||||
<?php die('skip, failed at compile time'); ?> |
||||
--FILE-- |
||||
<?php |
||||
class C |
||||
{ |
||||
const c1 = 1, c2 = 1.5; |
||||
const c3 = + 1, c4 = + 1.5; |
||||
const c5 = -1, c6 = -1.5; |
||||
|
||||
const c7 = __LINE__; |
||||
const c8 = __FILE__; |
||||
const c9 = __CLASS__; |
||||
const c10 = __METHOD__; |
||||
const c11 = __FUNCTION__; |
||||
|
||||
const c12 = DEFINED; |
||||
const c13 = DEFINED_TO_VAR; |
||||
const c14 = DEFINED_TO_UNDEF_VAR; |
||||
|
||||
const c15 = "hello1"; |
||||
const c16 = 'hello2'; |
||||
const c17 = C::c16; |
||||
const c18 = self::c17; |
||||
} |
||||
|
||||
function main() { |
||||
define('DEFINED', 1234); |
||||
$def = 456; |
||||
define('DEFINED_TO_VAR', $def); |
||||
define('DEFINED_TO_UNDEF_VAR', $undef); |
||||
echo "\nAttempt to access various kinds of class constants:\n"; |
||||
var_dump(C::c1); |
||||
var_dump(C::c2); |
||||
var_dump(C::c3); |
||||
var_dump(C::c4); |
||||
var_dump(C::c5); |
||||
var_dump(C::c6); |
||||
var_dump(C::c7); |
||||
var_dump(C::c8); |
||||
var_dump(C::c9); |
||||
var_dump(C::c10); |
||||
var_dump(C::c11); |
||||
var_dump(C::c12); |
||||
var_dump(C::c13); |
||||
var_dump(C::c14); |
||||
var_dump(C::c15); |
||||
var_dump(C::c16); |
||||
var_dump(C::c17); |
||||
var_dump(C::c18); |
||||
|
||||
echo "\nExpecting fatal error:\n"; |
||||
var_dump(C::c19); |
||||
|
||||
echo "\nYou should not see this."; |
||||
} |
||||
?> |
||||
--EXPECTF-- |
||||
Warning: Undefined variable $undef in %s on line %d |
||||
|
||||
Attempt to access various kinds of class constants: |
||||
int(1) |
||||
float(1.5) |
||||
int(1) |
||||
float(1.5) |
||||
int(-1) |
||||
float(-1.5) |
||||
int(13) |
||||
string(%d) "%s" |
||||
string(1) "C" |
||||
string(0) "" |
||||
string(0) "" |
||||
int(1234) |
||||
int(456) |
||||
NULL |
||||
string(6) "hello1" |
||||
string(6) "hello2" |
||||
string(6) "hello2" |
||||
string(6) "hello2" |
||||
|
||||
Expecting fatal error: |
||||
|
||||
Fatal error: Uncaught Error: Undefined constant C::c19 in %s:%d |
||||
Stack trace: |
||||
#0 {main} |
||||
thrown in %s on line %d |
||||
@ -0,0 +1,33 @@ |
||||
--TEST-- |
||||
Basic class support - defining and reading a class constant. |
||||
--FILE-- |
||||
<?php |
||||
class aclass |
||||
{ |
||||
const myConst = "hello"; |
||||
} |
||||
|
||||
function main() { |
||||
echo "\nRead class constant.\n"; |
||||
var_dump(aclass::myConst); |
||||
|
||||
echo "\nFail to read class constant from instance.\n"; |
||||
$myInstance = new aclass(); |
||||
var_dump($myInstance->myConst); |
||||
|
||||
echo "\nClass constant not visible in object var_dump.\n"; |
||||
var_dump($myInstance); |
||||
} |
||||
?> |
||||
--EXPECTF-- |
||||
Read class constant. |
||||
string(5) "hello" |
||||
|
||||
Fail to read class constant from instance. |
||||
|
||||
Warning: Undefined property: aclass::$myConst in %s on line %d |
||||
NULL |
||||
|
||||
Class constant not visible in object var_dump. |
||||
object(aclass)#%d (0) { |
||||
} |
||||
@ -0,0 +1,5 @@ |
||||
<?php |
||||
class A { |
||||
const MY_CONST = "hello from A"; |
||||
} |
||||
?> |
||||
@ -0,0 +1,33 @@ |
||||
--TEST-- |
||||
Ensure class properties and constants can be defined in terms of constants that are not known at compile time. |
||||
--SKIPIF-- |
||||
<?php die('skip, failed at compile time'); ?> |
||||
--FILE-- |
||||
<?php |
||||
|
||||
class B |
||||
{ |
||||
public static $a = A::MY_CONST; |
||||
public static $c = C::MY_CONST; |
||||
const ca = A::MY_CONST; |
||||
const cc = C::MY_CONST; |
||||
} |
||||
|
||||
class C |
||||
{ |
||||
const MY_CONST = "hello from C"; |
||||
} |
||||
|
||||
function main() { |
||||
include __DIR__.'/constants_basic_003.inc'; |
||||
var_dump(B::$a); |
||||
var_dump(B::$c); |
||||
var_dump(B::ca); |
||||
var_dump(B::cc); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(12) "hello from A" |
||||
string(12) "hello from C" |
||||
string(12) "hello from A" |
||||
string(12) "hello from C" |
||||
@ -0,0 +1,102 @@ |
||||
--TEST-- |
||||
Test properties with array default values using class constants as keys and values. |
||||
--SKIPIF-- |
||||
<?php die('skip, failed at compile time'); ?> |
||||
--FILE-- |
||||
<?php |
||||
class X |
||||
{ |
||||
// Static and instance array using class constants |
||||
public static $sa_x = array(B::KEY => B::VALUE); |
||||
public $a_x = array(B::KEY => B::VALUE); |
||||
} |
||||
|
||||
class B |
||||
{ |
||||
const KEY = "key"; |
||||
const VALUE = "value"; |
||||
|
||||
// Static and instance array using class constants with self |
||||
public static $sa_b = array(self::KEY => self::VALUE); |
||||
public $a_b = array(self::KEY => self::VALUE); |
||||
} |
||||
|
||||
class C extends B |
||||
{ |
||||
// Static and instance array using class constants with parent |
||||
public static $sa_c_parent = array(parent::KEY => parent::VALUE); |
||||
public $a_c_parent = array(parent::KEY => parent::VALUE); |
||||
|
||||
// Static and instance array using class constants with self (constants should be inherited) |
||||
public static $sa_c_self = array(self::KEY => self::VALUE); |
||||
public $a_c_self = array(self::KEY => self::VALUE); |
||||
|
||||
// Should also include inherited properties from B. |
||||
} |
||||
|
||||
function main() { |
||||
echo "\nStatic properties:\n"; |
||||
var_dump(X::$sa_x, B::$sa_b, C::$sa_b, C::$sa_c_parent, C::$sa_c_self); |
||||
|
||||
echo "\nInstance properties:\n"; |
||||
$x = new x; |
||||
$b = new B; |
||||
$c = new C; |
||||
var_dump($x, $b, $c); |
||||
} |
||||
?> |
||||
--EXPECTF-- |
||||
Static properties: |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
|
||||
Instance properties: |
||||
object(X)#%d (1) { |
||||
["a_x"]=> |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
} |
||||
object(B)#%d (1) { |
||||
["a_b"]=> |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
} |
||||
object(C)#%d (3) { |
||||
["a_b"]=> |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
["a_c_parent"]=> |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
["a_c_self"]=> |
||||
array(1) { |
||||
["key"]=> |
||||
string(5) "value" |
||||
} |
||||
} |
||||
@ -0,0 +1,19 @@ |
||||
--TEST-- |
||||
Test constants with default values based on other constants. |
||||
--SKIPIF-- |
||||
<?php die('skip, failed at compile time'); ?> |
||||
--FILE-- |
||||
<?php |
||||
class C |
||||
{ |
||||
const CONST_2 = self::CONST_1; |
||||
const CONST_1 = self::BASE_CONST; |
||||
const BASE_CONST = 'hello'; |
||||
} |
||||
function main() { |
||||
var_dump(C::CONST_1, C::CONST_2); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(5) "hello" |
||||
string(5) "hello" |
||||
@ -0,0 +1,44 @@ |
||||
--TEST-- |
||||
Ensure class constants are not evaluated when a class is looked up to resolve inheritance during runtime. |
||||
--SKIPIF-- |
||||
<?php die('skip, failed at compile time'); ?> |
||||
--FILE-- |
||||
<?php |
||||
const K = "nasty"; |
||||
class C |
||||
{ |
||||
const X = E::A; |
||||
public static $a = array(K => D::V, E::A => K); |
||||
} |
||||
class E extends D |
||||
{ |
||||
const A = "hello"; |
||||
} |
||||
function main() { |
||||
eval('class D extends C { const V = \'test\'; }'); |
||||
|
||||
var_dump(C::X, C::$a, D::X, D::$a, E::X, E::$a); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
string(5) "hello" |
||||
array(2) { |
||||
["nasty"]=> |
||||
string(4) "test" |
||||
["hello"]=> |
||||
string(5) "nasty" |
||||
} |
||||
string(5) "hello" |
||||
array(2) { |
||||
["nasty"]=> |
||||
string(4) "test" |
||||
["hello"]=> |
||||
string(5) "nasty" |
||||
} |
||||
string(5) "hello" |
||||
array(2) { |
||||
["nasty"]=> |
||||
string(4) "test" |
||||
["hello"]=> |
||||
string(5) "nasty" |
||||
} |
||||
@ -0,0 +1,37 @@ |
||||
--TEST-- |
||||
Class constants and doc comments |
||||
--INI-- |
||||
opcache.save_comments=1 |
||||
--FILE-- |
||||
<?php |
||||
class X { |
||||
/** comment X1 */ |
||||
const X1 = 1; |
||||
const X2 = 2; |
||||
/** comment X3 */ |
||||
const X3 = 3; |
||||
} |
||||
|
||||
class Y extends X { |
||||
/** comment Y1 */ |
||||
const Y1 = 1; |
||||
const Y2 = 2; |
||||
/** comment Y3 */ |
||||
const Y3 = 3; |
||||
} |
||||
|
||||
function main() { |
||||
$r = new ReflectionClass('Y'); |
||||
foreach ($r->getReflectionConstants() as $rc) { |
||||
echo $rc->getName() . " : " . $rc->getValue() . "\n"; |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
X1 : 1 |
||||
X2 : 2 |
||||
X3 : 3 |
||||
Y1 : 1 |
||||
Y2 : 2 |
||||
Y3 : 3 |
||||
|
||||
Loading…
Reference in new issue