tolerant-php-parser/php-langspec/tests/traits/traits.phpt

350 строки
6.3 KiB
PHP

--TEST--
PHP Spec test generated from ./traits/traits.php
--FILE--
<?php
/*
+-------------------------------------------------------------+
| Copyright (c) 2014 Facebook, Inc. (http://www.facebook.com) |
+-------------------------------------------------------------+
*/
error_reporting(-1);
echo "Inside >" . __TRAIT__ . "<\n";
echo "Inside >" . __CLASS__ . "<\n";
echo "Inside >" . __METHOD__ . "<\n";
echo "Inside >" . __FUNCTION__ . "<\n";
echo "===================== Test an Empty Trait =========================\n";
trait T1 {} // allowed to be empty
class C1 { use T1; }
echo "========== Test Overriding and Collisions Between Traits =====\n";
trait T2a
{
function f()
{
echo "Inside " . __TRAIT__ . "\n";
echo "Inside " . __CLASS__ . "\n";
echo "Inside " . __METHOD__ . "\n";
}
}
trait T2b
{
// function f($p1, $p2) // signatures not factored in when looking for name clashes
function f()
{
echo "Inside " . __TRAIT__ . "\n";
echo "Inside " . __CLASS__ . "\n";
echo "Inside " . __METHOD__ . "\n";
}
}
class C2Base
{
public function f() { echo "Inside " . __METHOD__ . "\n"; }
}
class C2Derived extends C2Base
{
// use T2a; use T2b; // equivalent to use T2a, T2b;
// use T2a, T2b; // clash between two names f REGARDLESS of argument lists
use T2a, T2b
{ // with both below excepted, went to base, bypassing both traits!!
T2a::f insteadof T2b;
// T2b::f insteadof T2a;
T2b::f as g; // allow otherwise hidden T2B::f to be seen through alias g
T2a::f as h; // allow T2a::f to also be seen through alias h
// don't need qualifier prefix if f is unambiguous
}
// public function f() { echo "Inside " . __METHOD__ . "\n"; }
}
$c2 = new C2Derived;
echo "-------\n";
$c2->f(); // call T2a::f
echo "-------\n";
$c2->g(); // call T2b::f via its alias g
echo "-------\n";
$c2->h(); // call T2a::f via its alias h
// confirmed that lookup starts with current class, then trait(s), then base classes
echo "===================== Changing Visibility =========================\n";
trait T3
{
public function m1() { echo "Inside " . __METHOD__ . "\n"; }
protected function m2() { echo "Inside " . __METHOD__ . "\n"; }
private function m3() { echo "Inside " . __METHOD__ . "\n"; }
function m4() { echo "Inside " . __METHOD__ . "\n"; } // implicitly public
}
class C3
{
use T3
{
m1 as protected; // reduce visibility to future, derived classes
m2 as private;
m3 as public;
m3 as protected z3;
}
}
$c3 = new C3;
//$c3->m1(); // accessible, by default, but not once protected
//$c3->m2(); // inaccessible, by default
$c3->m3(); // inaccessible, by default
$c3->m4(); // accessible, by default
echo "===================== Traits using other Traits =========================\n";
trait Tx1
{
function k()
{
echo "Inside " . __TRAIT__ . "\n";
echo "Inside " . __CLASS__ . "\n";
echo "Inside " . __METHOD__ . "\n";
}
}
trait Tx2
{
function m()
{
echo "Inside " . __TRAIT__ . "\n";
echo "Inside " . __CLASS__ . "\n";
echo "Inside " . __METHOD__ . "\n";
}
}
trait T4
{
use Tx1, Tx2;
use T2a, T2b, T3
{
Tx1::k as kk;
T2a::f insteadof T2b;
}
}
class C4
{
use T4;
}
$c4 = new C4;
echo "-------\n";
$c4->f();
echo "-------\n";
$c4->m1();
echo "-------\n";
$c4->k();
echo "-------\n";
$c4->m();
echo "===================== static properties =========================\n";
trait T5
{
public static $prop;
}
class C5a
{
use T5;
}
class C5b
{
use T5;
}
C5a::$prop = 123;
C5b::$prop = "red";
echo C5a::$prop . "\n"; // ==> 123
echo C5b::$prop . "\n"; // ==> red
echo "===================== function statics =========================\n";
trait T6
{
public function f()
{
echo "Inside " . __METHOD__ . "\n";
static $v = 0; // static is class-specific
echo "\$v = " . $v++ . "\n";
}
}
class C6a
{
use T6;
}
class C6b
{
use T6;
}
$v1 = new C6a;
$v1->f(); // method run twice with same $v
$v1->f();
echo "-------\n";
$v2 = new C6b;
$v2->f(); // method run three times with a different $v
$v2->f();
$v2->f();
echo "===================== Using a Trait without a Class =========================\n";
trait T7
{
public static $pubs = 123;
function f() // implicitly public
{
echo "Inside " . __TRAIT__ . "\n";
echo "Inside " . __CLASS__ . "\n";
echo "Inside " . __METHOD__ . "\n";
var_dump($this);
}
public static function g()
{
echo "Inside " . __TRAIT__ . "\n";
echo "Inside " . __CLASS__ . "\n";
echo "Inside " . __METHOD__ . "\n";
}
}
T7::f(); // calls f like a static function with class name being the trait name
echo "-------\n";
T7::g();
/*
echo "-------\n";
var_dump(T7::pubs); // doesn't work for static properties
*/
echo "===================== examples for spec =========================\n";
trait T9a
{
public function compute(/* ... */) { /* ... */ }
}
trait T9b
{
public function compute(/* ... */) { /* ... */ }
}
trait T9c
{
public function sort(/* ... */) { /* ... */ }
}
trait T9d
{
use T9c;
use T9a, T9b
{
T9a::compute insteadof T9b;
T9c::sort as private sorter;
}
}
trait T10
{
private $prop1 = 1000;
protected static $prop2;
var $prop3;
public function compute() {}
public static function getData() {}
}
--EXPECTF--
Inside ><
Inside ><
Inside ><
Inside ><
===================== Test an Empty Trait =========================
========== Test Overriding and Collisions Between Traits =====
-------
Inside T2a
Inside C2Derived
Inside T2a::f
-------
Inside T2b
Inside C2Derived
Inside T2b::f
-------
Inside T2a
Inside C2Derived
Inside T2a::f
===================== Changing Visibility =========================
Inside T3::m3
Inside T3::m4
===================== Traits using other Traits =========================
-------
Inside T2a
Inside C4
Inside T2a::f
-------
Inside T3::m1
-------
Inside Tx1
Inside C4
Inside Tx1::k
-------
Inside Tx2
Inside C4
Inside Tx2::m
===================== static properties =========================
123
red
===================== function statics =========================
Inside T6::f
$v = 0
Inside T6::f
$v = 1
-------
Inside T6::f
$v = 0
Inside T6::f
$v = 1
Inside T6::f
$v = 2
===================== Using a Trait without a Class =========================
%AInside T7
Inside T7
Inside T7::f
Notice: Undefined variable: this in %s/traits/traits.php on line 227
NULL
-------
Inside T7
Inside T7
Inside T7::g
===================== examples for spec =========================