- 引入 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