the whole shebang

This commit is contained in:
2014-11-25 16:42:40 +01:00
parent 7f74c0613e
commit ab1334c0cf
3686 changed files with 496409 additions and 1 deletions

View File

@@ -0,0 +1,91 @@
<?php
class PHPParser_Tests_Builder_ClassTest extends PHPUnit_Framework_TestCase
{
protected function createClassBuilder($class) {
return new PHPParser_Builder_Class($class);
}
public function testExtendsImplements() {
$node = $this->createClassBuilder('SomeLogger')
->extend('BaseLogger')
->implement('Namespaced\Logger', new PHPParser_Node_Name('SomeInterface'))
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Class('SomeLogger', array(
'extends' => new PHPParser_Node_Name('BaseLogger'),
'implements' => array(
new PHPParser_Node_Name('Namespaced\Logger'),
new PHPParser_Node_Name('SomeInterface')
),
)),
$node
);
}
public function testAbstract() {
$node = $this->createClassBuilder('Test')
->makeAbstract()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Class('Test', array(
'type' => PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT
)),
$node
);
}
public function testFinal() {
$node = $this->createClassBuilder('Test')
->makeFinal()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Class('Test', array(
'type' => PHPParser_Node_Stmt_Class::MODIFIER_FINAL
)),
$node
);
}
public function testStatementOrder() {
$method = new PHPParser_Node_Stmt_ClassMethod('testMethod');
$property = new PHPParser_Node_Stmt_Property(
PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC,
array(new PHPParser_Node_Stmt_PropertyProperty('testProperty'))
);
$const = new PHPParser_Node_Stmt_ClassConst(array(
new PHPParser_Node_Const('TEST_CONST', new PHPParser_Node_Scalar_String('ABC'))
));
$use = new PHPParser_Node_Stmt_TraitUse(array(new PHPParser_Node_Name('SomeTrait')));
$node = $this->createClassBuilder('Test')
->addStmt($method)
->addStmt($property)
->addStmts(array($const, $use))
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Class('Test', array(
'stmts' => array($use, $const, $property, $method)
)),
$node
);
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Unexpected node of type "Stmt_Echo"
*/
public function testInvalidStmtError() {
$this->createClassBuilder('Test')
->addStmt(new PHPParser_Node_Stmt_Echo(array()))
;
}
}

View File

@@ -0,0 +1,70 @@
<?php
class PHPParser_Tests_Builder_FunctionTest extends PHPUnit_Framework_TestCase
{
public function createFunctionBuilder($name) {
return new PHPParser_Builder_Function($name);
}
public function testReturnByRef() {
$node = $this->createFunctionBuilder('test')
->makeReturnByRef()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Function('test', array(
'byRef' => true
)),
$node
);
}
public function testParams() {
$param1 = new PHPParser_Node_Param('test1');
$param2 = new PHPParser_Node_Param('test2');
$param3 = new PHPParser_Node_Param('test3');
$node = $this->createFunctionBuilder('test')
->addParam($param1)
->addParams(array($param2, $param3))
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Function('test', array(
'params' => array($param1, $param2, $param3)
)),
$node
);
}
public function testStmts() {
$stmt1 = new PHPParser_Node_Expr_Print(new PHPParser_Node_Scalar_String('test1'));
$stmt2 = new PHPParser_Node_Expr_Print(new PHPParser_Node_Scalar_String('test2'));
$stmt3 = new PHPParser_Node_Expr_Print(new PHPParser_Node_Scalar_String('test3'));
$node = $this->createFunctionBuilder('test')
->addStmt($stmt1)
->addStmts(array($stmt2, $stmt3))
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Function('test', array(
'stmts' => array($stmt1, $stmt2, $stmt3)
)),
$node
);
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Expected parameter node, got "Name"
*/
public function testInvalidParamError() {
$this->createFunctionBuilder('test')
->addParam(new PHPParser_Node_Name('foo'))
;
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* This class unit-tests the interface builder
*/
class PHPParser_Tests_Builder_InterfaceTest extends PHPUnit_Framework_TestCase
{
/** @var PHPParser_Builder_Interface */
protected $builder;
protected function setUp() {
$this->builder = new PHPParser_Builder_Interface('Contract');
}
private function dump($node) {
$pp = new PHPParser_PrettyPrinter_Default();
return $pp->prettyPrint(array($node));
}
public function testEmpty() {
$contract = $this->builder->getNode();
$this->assertInstanceOf('PHPParser_Node_Stmt_Interface', $contract);
$this->assertEquals('Contract', $contract->name);
}
public function testExtending() {
$contract = $this->builder->extend('Space\Root1', 'Root2')->getNode();
$this->assertEquals(
new PHPParser_Node_Stmt_Interface('Contract', array(
'extends' => array(
new PHPParser_Node_Name('Space\Root1'),
new PHPParser_Node_Name('Root2')
),
)), $contract
);
}
public function testAddMethod() {
$method = new PHPParser_Node_Stmt_ClassMethod('doSomething');
$contract = $this->builder->addStmt($method)->getNode();
$this->assertEquals(array($method), $contract->stmts);
}
public function testAddConst() {
$const = new PHPParser_Node_Stmt_ClassConst(array(
new PHPParser_Node_Const('SPEED_OF_LIGHT', new PHPParser_Node_Scalar_DNumber(299792458))
));
$contract = $this->builder->addStmt($const)->getNode();
$this->assertEquals(299792458, $contract->stmts[0]->consts[0]->value->value);
}
public function testOrder() {
$const = new PHPParser_Node_Stmt_ClassConst(array(
new PHPParser_Node_Const('SPEED_OF_LIGHT', new PHPParser_Node_Scalar_DNumber(299792458))
));
$method = new PHPParser_Node_Stmt_ClassMethod('doSomething');
$contract = $this->builder
->addStmt($method)
->addStmt($const)
->getNode()
;
$this->assertInstanceOf('PHPParser_Node_Stmt_ClassConst', $contract->stmts[0]);
$this->assertInstanceOf('PHPParser_Node_Stmt_ClassMethod', $contract->stmts[1]);
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Unexpected node of type "Stmt_PropertyProperty"
*/
public function testInvalidStmtError() {
$this->builder->addStmt(new PHPParser_Node_Stmt_PropertyProperty('invalid'));
}
public function testFullFunctional() {
$const = new PHPParser_Node_Stmt_ClassConst(array(
new PHPParser_Node_Const('SPEED_OF_LIGHT', new PHPParser_Node_Scalar_DNumber(299792458))
));
$method = new PHPParser_Node_Stmt_ClassMethod('doSomething');
$contract = $this->builder
->addStmt($method)
->addStmt($const)
->getNode()
;
eval($this->dump($contract));
$this->assertTrue(interface_exists('Contract', false));
}
}

View File

@@ -0,0 +1,137 @@
<?php
class PHPParser_Tests_Builder_MethodTest extends PHPUnit_Framework_TestCase
{
public function createMethodBuilder($name) {
return new PHPParser_Builder_Method($name);
}
public function testModifiers() {
$node = $this->createMethodBuilder('test')
->makePublic()
->makeAbstract()
->makeStatic()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_ClassMethod('test', array(
'type' => PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC
| PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT
| PHPParser_Node_Stmt_Class::MODIFIER_STATIC,
'stmts' => null,
)),
$node
);
$node = $this->createMethodBuilder('test')
->makeProtected()
->makeFinal()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_ClassMethod('test', array(
'type' => PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED
| PHPParser_Node_Stmt_Class::MODIFIER_FINAL
)),
$node
);
$node = $this->createMethodBuilder('test')
->makePrivate()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_ClassMethod('test', array(
'type' => PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE
)),
$node
);
}
public function testReturnByRef() {
$node = $this->createMethodBuilder('test')
->makeReturnByRef()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_ClassMethod('test', array(
'byRef' => true
)),
$node
);
}
public function testParams() {
$param1 = new PHPParser_Node_Param('test1');
$param2 = new PHPParser_Node_Param('test2');
$param3 = new PHPParser_Node_Param('test3');
$node = $this->createMethodBuilder('test')
->addParam($param1)
->addParams(array($param2, $param3))
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_ClassMethod('test', array(
'params' => array($param1, $param2, $param3)
)),
$node
);
}
public function testStmts() {
$stmt1 = new PHPParser_Node_Expr_Print(new PHPParser_Node_Scalar_String('test1'));
$stmt2 = new PHPParser_Node_Expr_Print(new PHPParser_Node_Scalar_String('test2'));
$stmt3 = new PHPParser_Node_Expr_Print(new PHPParser_Node_Scalar_String('test3'));
$node = $this->createMethodBuilder('test')
->addStmt($stmt1)
->addStmts(array($stmt2, $stmt3))
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_ClassMethod('test', array(
'stmts' => array($stmt1, $stmt2, $stmt3)
)),
$node
);
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Cannot add statements to an abstract method
*/
public function testAddStmtToAbstractMethodError() {
$this->createMethodBuilder('test')
->makeAbstract()
->addStmt(new PHPParser_Node_Expr_Print(new PHPParser_Node_Scalar_String('test')))
;
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Cannot make method with statements abstract
*/
public function testMakeMethodWithStmtsAbstractError() {
$this->createMethodBuilder('test')
->addStmt(new PHPParser_Node_Expr_Print(new PHPParser_Node_Scalar_String('test')))
->makeAbstract()
;
}
/**
* @expectedException LogicException
* @expectedExceptionMessage Expected parameter node, got "Name"
*/
public function testInvalidParamError() {
$this->createMethodBuilder('test')
->addParam(new PHPParser_Node_Name('foo'))
;
}
}

View File

@@ -0,0 +1,118 @@
<?php
class PHPParser_Tests_Builder_ParamTest extends PHPUnit_Framework_TestCase
{
public function createParamBuilder($name) {
return new PHPParser_Builder_Param($name);
}
/**
* @dataProvider provideTestDefaultValues
*/
public function testDefaultValues($value, $expectedValueNode) {
$node = $this->createParamBuilder('test')
->setDefault($value)
->getNode()
;
$this->assertEquals($expectedValueNode, $node->default);
}
public function provideTestDefaultValues() {
return array(
array(
null,
new PHPParser_Node_Expr_ConstFetch(new PHPParser_Node_Name('null'))
),
array(
true,
new PHPParser_Node_Expr_ConstFetch(new PHPParser_Node_Name('true'))
),
array(
false,
new PHPParser_Node_Expr_ConstFetch(new PHPParser_Node_Name('false'))
),
array(
31415,
new PHPParser_Node_Scalar_LNumber(31415)
),
array(
3.1415,
new PHPParser_Node_Scalar_DNumber(3.1415)
),
array(
'Hallo World',
new PHPParser_Node_Scalar_String('Hallo World')
),
array(
array(1, 2, 3),
new PHPParser_Node_Expr_Array(array(
new PHPParser_Node_Expr_ArrayItem(new PHPParser_Node_Scalar_LNumber(1)),
new PHPParser_Node_Expr_ArrayItem(new PHPParser_Node_Scalar_LNumber(2)),
new PHPParser_Node_Expr_ArrayItem(new PHPParser_Node_Scalar_LNumber(3)),
))
),
array(
array('foo' => 'bar', 'bar' => 'foo'),
new PHPParser_Node_Expr_Array(array(
new PHPParser_Node_Expr_ArrayItem(
new PHPParser_Node_Scalar_String('bar'),
new PHPParser_Node_Scalar_String('foo')
),
new PHPParser_Node_Expr_ArrayItem(
new PHPParser_Node_Scalar_String('foo'),
new PHPParser_Node_Scalar_String('bar')
),
))
),
array(
new PHPParser_Node_Scalar_DirConst,
new PHPParser_Node_Scalar_DirConst
)
);
}
public function testTypeHints() {
$node = $this->createParamBuilder('test')
->setTypeHint('array')
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Param('test', null, 'array'),
$node
);
$node = $this->createParamBuilder('test')
->setTypeHint('callable')
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Param('test', null, 'callable'),
$node
);
$node = $this->createParamBuilder('test')
->setTypeHint('Some\Class')
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Param('test', null, new PHPParser_Node_Name('Some\Class')),
$node
);
}
public function testByRef() {
$node = $this->createParamBuilder('test')
->makeByRef()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Param('test', null, null, true),
$node
);
}
}

View File

@@ -0,0 +1,123 @@
<?php
class PHPParser_Tests_Builder_PropertyTest extends PHPUnit_Framework_TestCase
{
public function createPropertyBuilder($name) {
return new PHPParser_Builder_Property($name);
}
public function testModifiers() {
$node = $this->createPropertyBuilder('test')
->makePrivate()
->makeStatic()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Property(
PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE
| PHPParser_Node_Stmt_Class::MODIFIER_STATIC,
array(
new PHPParser_Node_Stmt_PropertyProperty('test')
)
),
$node
);
$node = $this->createPropertyBuilder('test')
->makeProtected()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Property(
PHPParser_Node_Stmt_Class::MODIFIER_PROTECTED,
array(
new PHPParser_Node_Stmt_PropertyProperty('test')
)
),
$node
);
$node = $this->createPropertyBuilder('test')
->makePublic()
->getNode()
;
$this->assertEquals(
new PHPParser_Node_Stmt_Property(
PHPParser_Node_Stmt_Class::MODIFIER_PUBLIC,
array(
new PHPParser_Node_Stmt_PropertyProperty('test')
)
),
$node
);
}
/**
* @dataProvider provideTestDefaultValues
*/
public function testDefaultValues($value, $expectedValueNode) {
$node = $this->createPropertyBuilder('test')
->setDefault($value)
->getNode()
;
$this->assertEquals($expectedValueNode, $node->props[0]->default);
}
public function provideTestDefaultValues() {
return array(
array(
null,
new PHPParser_Node_Expr_ConstFetch(new PHPParser_Node_Name('null'))
),
array(
true,
new PHPParser_Node_Expr_ConstFetch(new PHPParser_Node_Name('true'))
),
array(
false,
new PHPParser_Node_Expr_ConstFetch(new PHPParser_Node_Name('false'))
),
array(
31415,
new PHPParser_Node_Scalar_LNumber(31415)
),
array(
3.1415,
new PHPParser_Node_Scalar_DNumber(3.1415)
),
array(
'Hallo World',
new PHPParser_Node_Scalar_String('Hallo World')
),
array(
array(1, 2, 3),
new PHPParser_Node_Expr_Array(array(
new PHPParser_Node_Expr_ArrayItem(new PHPParser_Node_Scalar_LNumber(1)),
new PHPParser_Node_Expr_ArrayItem(new PHPParser_Node_Scalar_LNumber(2)),
new PHPParser_Node_Expr_ArrayItem(new PHPParser_Node_Scalar_LNumber(3)),
))
),
array(
array('foo' => 'bar', 'bar' => 'foo'),
new PHPParser_Node_Expr_Array(array(
new PHPParser_Node_Expr_ArrayItem(
new PHPParser_Node_Scalar_String('bar'),
new PHPParser_Node_Scalar_String('foo')
),
new PHPParser_Node_Expr_ArrayItem(
new PHPParser_Node_Scalar_String('foo'),
new PHPParser_Node_Scalar_String('bar')
),
))
),
array(
new PHPParser_Node_Scalar_DirConst,
new PHPParser_Node_Scalar_DirConst
)
);
}
}

View File

@@ -0,0 +1,23 @@
<?php
class PHPParser_Tests_BuilderFactoryTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provideTestFactory
*/
public function testFactory($methodName, $className) {
$factory = new PHPParser_BuilderFactory;
$this->assertInstanceOf($className, $factory->$methodName('test'));
}
public function provideTestFactory() {
return array(
array('class', 'PHPParser_Builder_Class'),
array('interface', 'PHPParser_Builder_Interface'),
array('method', 'PHPParser_Builder_Method'),
array('function', 'PHPParser_Builder_Function'),
array('property', 'PHPParser_Builder_Property'),
array('param', 'PHPParser_Builder_Param'),
);
}
}

View File

@@ -0,0 +1,51 @@
<?php
abstract class PHPParser_Tests_CodeTestAbstract extends PHPUnit_Framework_TestCase
{
protected function getTests($directory, $fileExtension) {
$it = new RecursiveDirectoryIterator($directory);
$it = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::LEAVES_ONLY);
$it = new RegexIterator($it, '(\.' . preg_quote($fileExtension) . '$)');
$tests = array();
foreach ($it as $file) {
// read file
$fileContents = file_get_contents($file);
// evaluate @@{expr}@@ expressions
$fileContents = preg_replace_callback(
'/@@\{(.*?)\}@@/',
array($this, 'evalCallback'),
$fileContents
);
// parse sections
$parts = array_map('trim', explode('-----', $fileContents));
// first part is the name
$name = array_shift($parts);
// multiple sections possible with always two forming a pair
foreach (array_chunk($parts, 2) as $chunk) {
$tests[] = array($name, $chunk[0], $chunk[1]);
}
}
return $tests;
}
protected function evalCallback($matches) {
return eval('return ' . $matches[1] . ';');
}
protected function canonicalize($str) {
// trim from both sides
$str = trim($str);
// normalize EOL to \n
$str = str_replace(array("\r\n", "\r"), "\n", $str);
// trim right side of all lines
return implode("\n", array_map('rtrim', explode("\n", $str)));
}
}

View File

@@ -0,0 +1,69 @@
<?php
class PHPParser_Tests_CommentTest extends PHPUnit_Framework_TestCase
{
public function testGetSet() {
$comment = new PHPParser_Comment('/* Some comment */', 1);
$this->assertEquals('/* Some comment */', $comment->getText());
$this->assertEquals('/* Some comment */', (string) $comment);
$this->assertEquals(1, $comment->getLine());
$comment->setText('/* Some other comment */');
$comment->setLine(10);
$this->assertEquals('/* Some other comment */', $comment->getText());
$this->assertEquals('/* Some other comment */', (string) $comment);
$this->assertEquals(10, $comment->getLine());
}
/**
* @dataProvider provideTestReformatting
*/
public function testReformatting($commentText, $reformattedText) {
$comment = new PHPParser_Comment($commentText);
$this->assertEquals($reformattedText, $comment->getReformattedText());
}
public function provideTestReformatting() {
return array(
array('// Some text' . "\n", '// Some text'),
array('/* Some text */', '/* Some text */'),
array(
'/**
* Some text.
* Some more text.
*/',
'/**
* Some text.
* Some more text.
*/'
),
array(
'/*
Some text.
Some more text.
*/',
'/*
Some text.
Some more text.
*/'
),
array(
'/* Some text.
More text.
Even more text. */',
'/* Some text.
More text.
Even more text. */'
),
// invalid comment -> no reformatting
array(
'hallo
world',
'hallo
world',
),
);
}
}

View File

@@ -0,0 +1,33 @@
<?php
class PHPParser_Tests_ErrorTest extends PHPUnit_Framework_TestCase
{
public function testConstruct() {
$error = new PHPParser_Error('Some error', 10);
$this->assertEquals('Some error', $error->getRawMessage());
$this->assertEquals(10, $error->getRawLine());
$this->assertEquals('Some error on line 10', $error->getMessage());
return $error;
}
/**
* @depends testConstruct
*/
public function testSetMessageAndLine(PHPParser_Error $error) {
$error->setRawMessage('Some other error');
$error->setRawLine(15);
$this->assertEquals('Some other error', $error->getRawMessage());
$this->assertEquals(15, $error->getRawLine());
$this->assertEquals('Some other error on line 15', $error->getMessage());
}
public function testUnknownLine() {
$error = new PHPParser_Error('Some error');
$this->assertEquals(-1, $error->getRawLine());
$this->assertEquals('Some error on unknown line', $error->getMessage());
}
}

View File

@@ -0,0 +1,103 @@
<?php
class PHPParser_Tests_Lexer_EmulativeTest extends PHPUnit_Framework_TestCase
{
/** @var PHPParser_Lexer_Emulative */
protected $lexer;
protected function setUp() {
$this->lexer = new PHPParser_Lexer_Emulative;
}
/**
* @dataProvider provideTestReplaceKeywords
*/
public function testReplaceKeywords($keyword, $expectedToken) {
$this->lexer->startLexing('<?php ' . $keyword);
$this->assertEquals($expectedToken, $this->lexer->getNextToken());
$this->assertEquals(0, $this->lexer->getNextToken());
}
/**
* @dataProvider provideTestReplaceKeywords
*/
public function testNoReplaceKeywordsAfterObjectOperator($keyword) {
$this->lexer->startLexing('<?php ->' . $keyword);
$this->assertEquals(PHPParser_Parser::T_OBJECT_OPERATOR, $this->lexer->getNextToken());
$this->assertEquals(PHPParser_Parser::T_STRING, $this->lexer->getNextToken());
$this->assertEquals(0, $this->lexer->getNextToken());
}
public function provideTestReplaceKeywords() {
return array(
// PHP 5.5
array('finally', PHPParser_Parser::T_FINALLY),
array('yield', PHPParser_Parser::T_YIELD),
// PHP 5.4
array('callable', PHPParser_Parser::T_CALLABLE),
array('insteadof', PHPParser_Parser::T_INSTEADOF),
array('trait', PHPParser_Parser::T_TRAIT),
array('__TRAIT__', PHPParser_Parser::T_TRAIT_C),
// PHP 5.3
array('__DIR__', PHPParser_Parser::T_DIR),
array('goto', PHPParser_Parser::T_GOTO),
array('namespace', PHPParser_Parser::T_NAMESPACE),
array('__NAMESPACE__', PHPParser_Parser::T_NS_C),
);
}
/**
* @dataProvider provideTestLexNewFeatures
*/
public function testLexNewFeatures($code, array $expectedTokens) {
$this->lexer->startLexing('<?php ' . $code);
foreach ($expectedTokens as $expectedToken) {
list($expectedTokenType, $expectedTokenText) = $expectedToken;
$this->assertEquals($expectedTokenType, $this->lexer->getNextToken($text));
$this->assertEquals($expectedTokenText, $text);
}
$this->assertEquals(0, $this->lexer->getNextToken());
}
/**
* @dataProvider provideTestLexNewFeatures
*/
public function testLeaveStuffAloneInStrings($code) {
$stringifiedToken = '"' . addcslashes($code, '"\\') . '"';
$this->lexer->startLexing('<?php ' . $stringifiedToken);
$this->assertEquals(PHPParser_Parser::T_CONSTANT_ENCAPSED_STRING, $this->lexer->getNextToken($text));
$this->assertEquals($stringifiedToken, $text);
$this->assertEquals(0, $this->lexer->getNextToken());
}
public function provideTestLexNewFeatures() {
return array(
array('0b1010110', array(
array(PHPParser_Parser::T_LNUMBER, '0b1010110'),
)),
array('0b1011010101001010110101010010101011010101010101101011001110111100', array(
array(PHPParser_Parser::T_DNUMBER, '0b1011010101001010110101010010101011010101010101101011001110111100'),
)),
array('\\', array(
array(PHPParser_Parser::T_NS_SEPARATOR, '\\'),
)),
array("<<<'NOWDOC'\nNOWDOC;\n", array(
array(PHPParser_Parser::T_START_HEREDOC, "<<<'NOWDOC'\n"),
array(PHPParser_Parser::T_END_HEREDOC, 'NOWDOC'),
array(ord(';'), ';'),
)),
array("<<<'NOWDOC'\nFoobar\nNOWDOC;\n", array(
array(PHPParser_Parser::T_START_HEREDOC, "<<<'NOWDOC'\n"),
array(PHPParser_Parser::T_ENCAPSED_AND_WHITESPACE, "Foobar\n"),
array(PHPParser_Parser::T_END_HEREDOC, 'NOWDOC'),
array(ord(';'), ';'),
)),
);
}
}

View File

@@ -0,0 +1,145 @@
<?php
class PHPParser_Tests_LexerTest extends PHPUnit_Framework_TestCase
{
/** @var PHPParser_Lexer */
protected $lexer;
protected function setUp() {
$this->lexer = new PHPParser_Lexer;
}
/**
* @dataProvider provideTestError
*/
public function testError($code, $message) {
try {
$this->lexer->startLexing($code);
} catch (PHPParser_Error $e) {
$this->assertEquals($message, $e->getMessage());
return;
}
$this->fail('Expected PHPParser_Error');
}
public function provideTestError() {
return array(
array('<?php /*', 'Unterminated comment on line 1'),
array('<?php ' . "\1", 'Unexpected character "' . "\1" . '" (ASCII 1) on unknown line'),
array('<?php ' . "\0", 'Unexpected null byte on unknown line'),
);
}
/**
* @dataProvider provideTestLex
*/
public function testLex($code, $tokens) {
$this->lexer->startLexing($code);
while ($id = $this->lexer->getNextToken($value, $startAttributes, $endAttributes)) {
$token = array_shift($tokens);
$this->assertEquals($token[0], $id);
$this->assertEquals($token[1], $value);
$this->assertEquals($token[2], $startAttributes);
$this->assertEquals($token[3], $endAttributes);
}
}
public function provideTestLex() {
return array(
// tests conversion of closing PHP tag and drop of whitespace and opening tags
array(
'<?php tokens ?>plaintext',
array(
array(
PHPParser_Parser::T_STRING, 'tokens',
array('startLine' => 1), array('endLine' => 1)
),
array(
ord(';'), '?>',
array('startLine' => 1), array('endLine' => 1)
),
array(
PHPParser_Parser::T_INLINE_HTML, 'plaintext',
array('startLine' => 1), array('endLine' => 1)
),
)
),
// tests line numbers
array(
'<?php' . "\n" . '$ token /** doc' . "\n" . 'comment */ $',
array(
array(
ord('$'), '$',
array('startLine' => 2), array('endLine' => 2)
),
array(
PHPParser_Parser::T_STRING, 'token',
array('startLine' => 2), array('endLine' => 2)
),
array(
ord('$'), '$',
array(
'startLine' => 3,
'comments' => array(new PHPParser_Comment_Doc('/** doc' . "\n" . 'comment */', 2))
),
array('endLine' => 3)
),
)
),
// tests comment extraction
array(
'<?php /* comment */ // comment' . "\n" . '/** docComment 1 *//** docComment 2 */ token',
array(
array(
PHPParser_Parser::T_STRING, 'token',
array(
'startLine' => 2,
'comments' => array(
new PHPParser_Comment('/* comment */', 1),
new PHPParser_Comment('// comment' . "\n", 1),
new PHPParser_Comment_Doc('/** docComment 1 */', 2),
new PHPParser_Comment_Doc('/** docComment 2 */', 2),
),
),
array('endLine' => 2)
),
)
),
// tests differing start and end line
array(
'<?php "foo' . "\n" . 'bar"',
array(
array(
PHPParser_Parser::T_CONSTANT_ENCAPSED_STRING, '"foo' . "\n" . 'bar"',
array('startLine' => 1), array('endLine' => 2)
),
)
),
);
}
/**
* @dataProvider provideTestHaltCompiler
*/
public function testHandleHaltCompiler($code, $remaining) {
$this->lexer->startLexing($code);
while (PHPParser_Parser::T_HALT_COMPILER !== $this->lexer->getNextToken());
$this->assertEquals($this->lexer->handleHaltCompiler(), $remaining);
$this->assertEquals(0, $this->lexer->getNextToken());
}
public function provideTestHaltCompiler() {
return array(
array('<?php ... __halt_compiler();Remaining Text', 'Remaining Text'),
array('<?php ... __halt_compiler ( ) ;Remaining Text', 'Remaining Text'),
array('<?php ... __halt_compiler() ?>Remaining Text', 'Remaining Text'),
//array('<?php ... __halt_compiler();' . "\0", "\0"),
//array('<?php ... __halt_compiler /* */ ( ) ;Remaining Text', 'Remaining Text'),
);
}
}

View File

@@ -0,0 +1,130 @@
<?php
class PHPParser_Tests_Node_NameTest extends PHPUnit_Framework_TestCase
{
public function testConstruct() {
$name = new PHPParser_Node_Name(array('foo', 'bar'));
$this->assertEquals(array('foo', 'bar'), $name->parts);
$name = new PHPParser_Node_Name('foo\bar');
$this->assertEquals(array('foo', 'bar'), $name->parts);
}
public function testGet() {
$name = new PHPParser_Node_Name('foo');
$this->assertEquals('foo', $name->getFirst());
$this->assertEquals('foo', $name->getLast());
$name = new PHPParser_Node_Name('foo\bar');
$this->assertEquals('foo', $name->getFirst());
$this->assertEquals('bar', $name->getLast());
}
public function testToString() {
$name = new PHPParser_Node_Name('foo\bar');
$this->assertEquals('foo\bar', (string) $name);
$this->assertEquals('foo\bar', $name->toString());
$this->assertEquals('foo_bar', $name->toString('_'));
}
public function testSet() {
$name = new PHPParser_Node_Name('foo');
$name->set('foo\bar');
$this->assertEquals('foo\bar', $name->toString());
$name->set(array('foo', 'bar'));
$this->assertEquals('foo\bar', $name->toString());
$name->set(new PHPParser_Node_Name('foo\bar'));
$this->assertEquals('foo\bar', $name->toString());
}
public function testSetFirst() {
$name = new PHPParser_Node_Name('foo');
$name->setFirst('bar');
$this->assertEquals('bar', $name->toString());
$name->setFirst('A\B');
$this->assertEquals('A\B', $name->toString());
$name->setFirst('C');
$this->assertEquals('C\B', $name->toString());
$name->setFirst('D\E');
$this->assertEquals('D\E\B', $name->toString());
}
public function testSetLast() {
$name = new PHPParser_Node_Name('foo');
$name->setLast('bar');
$this->assertEquals('bar', $name->toString());
$name->setLast('A\B');
$this->assertEquals('A\B', $name->toString());
$name->setLast('C');
$this->assertEquals('A\C', $name->toString());
$name->setLast('D\E');
$this->assertEquals('A\D\E', $name->toString());
}
public function testAppend() {
$name = new PHPParser_Node_Name('foo');
$name->append('bar');
$this->assertEquals('foo\bar', $name->toString());
$name->append('bar\foo');
$this->assertEquals('foo\bar\bar\foo', $name->toString());
}
public function testPrepend() {
$name = new PHPParser_Node_Name('foo');
$name->prepend('bar');
$this->assertEquals('bar\foo', $name->toString());
$name->prepend('foo\bar');
$this->assertEquals('foo\bar\bar\foo', $name->toString());
}
public function testIs() {
$name = new PHPParser_Node_Name('foo');
$this->assertTrue ($name->isUnqualified());
$this->assertFalse($name->isQualified());
$this->assertFalse($name->isFullyQualified());
$this->assertFalse($name->isRelative());
$name = new PHPParser_Node_Name('foo\bar');
$this->assertFalse($name->isUnqualified());
$this->assertTrue ($name->isQualified());
$this->assertFalse($name->isFullyQualified());
$this->assertFalse($name->isRelative());
$name = new PHPParser_Node_Name_FullyQualified('foo');
$this->assertFalse($name->isUnqualified());
$this->assertFalse($name->isQualified());
$this->assertTrue ($name->isFullyQualified());
$this->assertFalse($name->isRelative());
$name = new PHPParser_Node_Name_Relative('foo');
$this->assertFalse($name->isUnqualified());
$this->assertFalse($name->isQualified());
$this->assertFalse($name->isFullyQualified());
$this->assertTrue ($name->isRelative());
}
/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage When changing a name you need to pass either a string, an array or a Name node
*/
public function testInvalidArg() {
$name = new PHPParser_Node_Name('foo');
$name->set(new stdClass);
}
}

View File

@@ -0,0 +1,59 @@
<?php
class PHPParser_Tests_Node_Scalar_StringTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provideTestParseEscapeSequences
*/
public function testParseEscapeSequences($expected, $string, $quote) {
$this->assertEquals(
$expected,
PHPParser_Node_Scalar_String::parseEscapeSequences($string, $quote)
);
}
/**
* @dataProvider provideTestParse
*/
public function testCreate($expected, $string) {
$this->assertEquals(
$expected,
PHPParser_Node_Scalar_String::parse($string)
);
}
public function provideTestParseEscapeSequences() {
return array(
array('"', '\\"', '"'),
array('\\"', '\\"', '`'),
array('\\"\\`', '\\"\\`', null),
array("\\\$\n\r\t\f\v", '\\\\\$\n\r\t\f\v', null),
array("\x1B", '\e', null),
array(chr(255), '\xFF', null),
array(chr(255), '\377', null),
array(chr(0), '\400', null),
array("\0", '\0', null),
array('\xFF', '\\\\xFF', null),
);
}
public function provideTestParse() {
$tests = array(
array('A', '\'A\''),
array('A', 'b\'A\''),
array('A', '"A"'),
array('A', 'b"A"'),
array('\\', '\'\\\\\''),
array('\'', '\'\\\'\''),
);
foreach ($this->provideTestParseEscapeSequences() as $i => $test) {
// skip second and third tests, they aren't for double quotes
if ($i != 1 && $i != 2) {
$tests[] = array($test[0], '"' . $test[1] . '"');
}
}
return $tests;
}
}

View File

@@ -0,0 +1,35 @@
<?php
class PHPParser_Tests_Node_Stmt_ClassMethodTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provideModifiers
*/
public function testModifiers($modifier) {
$node = new PHPParser_Node_Stmt_ClassMethod('foo', array(
'type' => constant('PHPParser_Node_Stmt_Class::MODIFIER_' . strtoupper($modifier))
));
$this->assertTrue($node->{'is' . $modifier}());
}
/**
* @dataProvider provideModifiers
*/
public function testNoModifiers($modifier) {
$node = new PHPParser_Node_Stmt_ClassMethod('foo', array('type' => 0));
$this->assertFalse($node->{'is' . $modifier}());
}
public function provideModifiers() {
return array(
array('public'),
array('protected'),
array('private'),
array('abstract'),
array('final'),
array('static'),
);
}
}

View File

@@ -0,0 +1,40 @@
<?php
class PHPParser_Tests_Node_Stmt_ClassTest extends PHPUnit_Framework_TestCase
{
public function testIsAbstract() {
$class = new PHPParser_Node_Stmt_Class('Foo', array('type' => PHPParser_Node_Stmt_Class::MODIFIER_ABSTRACT));
$this->assertTrue($class->isAbstract());
$class = new PHPParser_Node_Stmt_Class('Foo');
$this->assertFalse($class->isAbstract());
}
public function testIsFinal() {
$class = new PHPParser_Node_Stmt_Class('Foo', array('type' => PHPParser_Node_Stmt_Class::MODIFIER_FINAL));
$this->assertTrue($class->isFinal());
$class = new PHPParser_Node_Stmt_Class('Foo');
$this->assertFalse($class->isFinal());
}
public function testGetMethods() {
$methods = array(
new PHPParser_Node_Stmt_ClassMethod('foo'),
new PHPParser_Node_Stmt_ClassMethod('bar'),
new PHPParser_Node_Stmt_ClassMethod('fooBar'),
);
$class = new PHPParser_Node_Stmt_Class('Foo', array(
'stmts' => array(
new PHPParser_Node_Stmt_TraitUse(array()),
$methods[0],
new PHPParser_Node_Stmt_Const(array()),
$methods[1],
new PHPParser_Node_Stmt_Property(0, array()),
$methods[2],
)
));
$this->assertEquals($methods, $class->getMethods());
}
}

View File

@@ -0,0 +1,34 @@
<?php
class PHPParser_Tests_Node_Stmt_PropertyTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provideModifiers
*/
public function testModifiers($modifier) {
$node = new PHPParser_Node_Stmt_Property(
constant('PHPParser_Node_Stmt_Class::MODIFIER_' . strtoupper($modifier)),
array() // invalid
);
$this->assertTrue($node->{'is' . $modifier}());
}
/**
* @dataProvider provideModifiers
*/
public function testNoModifiers($modifier) {
$node = new PHPParser_Node_Stmt_Property(0, array());
$this->assertFalse($node->{'is' . $modifier}());
}
public function provideModifiers() {
return array(
array('public'),
array('protected'),
array('private'),
array('static'),
);
}
}

View File

@@ -0,0 +1,96 @@
<?php
class PHPParser_Tests_NodeAbstractTest extends PHPUnit_Framework_TestCase
{
public function testConstruct() {
$attributes = array(
'startLine' => 10,
'comments' => array(
new PHPParser_Comment('// Comment' . "\n"),
new PHPParser_Comment_Doc('/** doc comment */'),
),
);
$node = $this->getMockForAbstractClass(
'PHPParser_NodeAbstract',
array(
array(
'subNode' => 'value'
),
$attributes
),
'PHPParser_Node_Dummy'
);
$this->assertEquals('Dummy', $node->getType());
$this->assertEquals(array('subNode'), $node->getSubNodeNames());
$this->assertEquals(10, $node->getLine());
$this->assertEquals('/** doc comment */', $node->getDocComment());
$this->assertEquals('value', $node->subNode);
$this->assertTrue(isset($node->subNode));
$this->assertEquals($attributes, $node->getAttributes());
return $node;
}
/**
* @depends testConstruct
*/
public function testGetDocComment(PHPParser_Node $node) {
$this->assertEquals('/** doc comment */', $node->getDocComment());
array_pop($node->getAttribute('comments')); // remove doc comment
$this->assertNull($node->getDocComment());
array_pop($node->getAttribute('comments')); // remove comment
$this->assertNull($node->getDocComment());
}
/**
* @depends testConstruct
*/
public function testChange(PHPParser_Node $node) {
// change of line
$node->setLine(15);
$this->assertEquals(15, $node->getLine());
// direct modification
$node->subNode = 'newValue';
$this->assertEquals('newValue', $node->subNode);
// indirect modification
$subNode =& $node->subNode;
$subNode = 'newNewValue';
$this->assertEquals('newNewValue', $node->subNode);
// removal
unset($node->subNode);
$this->assertFalse(isset($node->subNode));
}
public function testAttributes() {
/** @var $node PHPParser_Node */
$node = $this->getMockForAbstractClass('PHPParser_NodeAbstract');
$this->assertEmpty($node->getAttributes());
$node->setAttribute('key', 'value');
$this->assertTrue($node->hasAttribute('key'));
$this->assertEquals('value', $node->getAttribute('key'));
$this->assertFalse($node->hasAttribute('doesNotExist'));
$this->assertNull($node->getAttribute('doesNotExist'));
$this->assertEquals('default', $node->getAttribute('doesNotExist', 'default'));
$node->setAttribute('null', null);
$this->assertTrue($node->hasAttribute('null'));
$this->assertNull($node->getAttribute('null'));
$this->assertNull($node->getAttribute('null', 'default'));
$this->assertEquals(
array(
'key' => 'value',
'null' => null,
),
$node->getAttributes()
);
}
}

View File

@@ -0,0 +1,66 @@
<?php
class PHPParser_Tests_NodeDumperTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provideTestDump
* @covers PHPParser_NodeDumper::dump
*/
public function testDump($node, $dump) {
$dumper = new PHPParser_NodeDumper;
$this->assertEquals($dump, $dumper->dump($node));
}
public function provideTestDump() {
return array(
array(
array(),
'array(
)'
),
array(
array('Foo', 'Bar', 'Key' => 'FooBar'),
'array(
0: Foo
1: Bar
Key: FooBar
)'
),
array(
new PHPParser_Node_Name(array('Hallo', 'World')),
'Name(
parts: array(
0: Hallo
1: World
)
)'
),
array(
new PHPParser_Node_Expr_Array(array(
new PHPParser_Node_Expr_ArrayItem(new PHPParser_Node_Scalar_String('Foo'))
)),
'Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_String(
value: Foo
)
byRef: false
)
)
)'
),
);
}
/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Can only dump nodes and arrays.
*/
public function testError() {
$dumper = new PHPParser_NodeDumper;
$dumper->dump(new stdClass);
}
}

View File

@@ -0,0 +1,125 @@
<?php
class PHPParser_Tests_NodeTraverserTest extends PHPUnit_Framework_TestCase
{
public function testNonModifying() {
$str1Node = new PHPParser_Node_Scalar_String('Foo');
$str2Node = new PHPParser_Node_Scalar_String('Bar');
$echoNode = new PHPParser_Node_Stmt_Echo(array($str1Node, $str2Node));
$stmts = array($echoNode);
$visitor = $this->getMock('PHPParser_NodeVisitor');
$visitor->expects($this->at(0))->method('beforeTraverse')->with($stmts);
$visitor->expects($this->at(1))->method('enterNode')->with($echoNode);
$visitor->expects($this->at(2))->method('enterNode')->with($str1Node);
$visitor->expects($this->at(3))->method('leaveNode')->with($str1Node);
$visitor->expects($this->at(4))->method('enterNode')->with($str2Node);
$visitor->expects($this->at(5))->method('leaveNode')->with($str2Node);
$visitor->expects($this->at(6))->method('leaveNode')->with($echoNode);
$visitor->expects($this->at(7))->method('afterTraverse')->with($stmts);
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals($stmts, $traverser->traverse($stmts));
}
public function testModifying() {
$str1Node = new PHPParser_Node_Scalar_String('Foo');
$str2Node = new PHPParser_Node_Scalar_String('Bar');
$printNode = new PHPParser_Node_Expr_Print($str1Node);
// first visitor changes the node, second verifies the change
$visitor1 = $this->getMock('PHPParser_NodeVisitor');
$visitor2 = $this->getMock('PHPParser_NodeVisitor');
// replace empty statements with string1 node
$visitor1->expects($this->at(0))->method('beforeTraverse')->with(array())
->will($this->returnValue(array($str1Node)));
$visitor2->expects($this->at(0))->method('beforeTraverse')->with(array($str1Node));
// replace string1 node with print node
$visitor1->expects($this->at(1))->method('enterNode')->with($str1Node)
->will($this->returnValue($printNode));
$visitor2->expects($this->at(1))->method('enterNode')->with($printNode);
// replace string1 node with string2 node
$visitor1->expects($this->at(2))->method('enterNode')->with($str1Node)
->will($this->returnValue($str2Node));
$visitor2->expects($this->at(2))->method('enterNode')->with($str2Node);
// replace string2 node with string1 node again
$visitor1->expects($this->at(3))->method('leaveNode')->with($str2Node)
->will($this->returnValue($str1Node));
$visitor2->expects($this->at(3))->method('leaveNode')->with($str1Node);
// replace print node with string1 node again
$visitor1->expects($this->at(4))->method('leaveNode')->with($printNode)
->will($this->returnValue($str1Node));
$visitor2->expects($this->at(4))->method('leaveNode')->with($str1Node);
// replace string1 node with empty statements again
$visitor1->expects($this->at(5))->method('afterTraverse')->with(array($str1Node))
->will($this->returnValue(array()));
$visitor2->expects($this->at(5))->method('afterTraverse')->with(array());
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor($visitor1);
$traverser->addVisitor($visitor2);
// as all operations are reversed we end where we start
$this->assertEquals(array(), $traverser->traverse(array()));
}
public function testRemove() {
$str1Node = new PHPParser_Node_Scalar_String('Foo');
$str2Node = new PHPParser_Node_Scalar_String('Bar');
$visitor = $this->getMock('PHPParser_NodeVisitor');
// remove the string1 node, leave the string2 node
$visitor->expects($this->at(2))->method('leaveNode')->with($str1Node)
->will($this->returnValue(false));
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals(array($str2Node), $traverser->traverse(array($str1Node, $str2Node)));
}
public function testMerge() {
$strStart = new PHPParser_Node_Scalar_String('Start');
$strMiddle = new PHPParser_Node_Scalar_String('End');
$strEnd = new PHPParser_Node_Scalar_String('Middle');
$strR1 = new PHPParser_Node_Scalar_String('Replacement 1');
$strR2 = new PHPParser_Node_Scalar_String('Replacement 2');
$visitor = $this->getMock('PHPParser_NodeVisitor');
// replace strMiddle with strR1 and strR2 by merge
$visitor->expects($this->at(4))->method('leaveNode')->with($strMiddle)
->will($this->returnValue(array($strR1, $strR2)));
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals(
array($strStart, $strR1, $strR2, $strEnd),
$traverser->traverse(array($strStart, $strMiddle, $strEnd))
);
}
public function testDeepArray() {
$strNode = new PHPParser_Node_Scalar_String('Foo');
$stmts = array(array(array($strNode)));
$visitor = $this->getMock('PHPParser_NodeVisitor');
$visitor->expects($this->at(1))->method('enterNode')->with($strNode);
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor($visitor);
$this->assertEquals($stmts, $traverser->traverse($stmts));
}
}

View File

@@ -0,0 +1,225 @@
<?php
class PHPParser_Tests_NodeVisitor_NameResolverTest extends PHPUnit_Framework_TestCase
{
/**
* @covers PHPParser_NodeVisitor_NameResolver
*/
public function testResolveNames() {
$code = <<<EOC
<?php
namespace Foo {
use Hallo as Hi;
new Bar();
new Hi();
new Hi\\Bar();
new \\Bar();
new namespace\\Bar();
bar();
hi();
Hi\\bar();
foo\\bar();
\\bar();
namespace\\bar();
}
namespace {
use Hallo as Hi;
new Bar();
new Hi();
new Hi\\Bar();
new \\Bar();
new namespace\\Bar();
bar();
hi();
Hi\\bar();
foo\\bar();
\\bar();
namespace\\bar();
}
EOC;
$expectedCode = <<<EOC
namespace Foo {
use Hallo as Hi;
new \\Foo\\Bar();
new \\Hallo();
new \\Hallo\\Bar();
new \\Bar();
new \\Foo\\Bar();
bar();
hi();
\\Hallo\\bar();
\\Foo\\foo\\bar();
\\bar();
\\Foo\\bar();
}
namespace {
use Hallo as Hi;
new \\Bar();
new \\Hallo();
new \\Hallo\\Bar();
new \\Bar();
new \\Bar();
bar();
hi();
\\Hallo\\bar();
\\foo\\bar();
\\bar();
\\bar();
}
EOC;
$parser = new PHPParser_Parser(new PHPParser_Lexer_Emulative);
$prettyPrinter = new PHPParser_PrettyPrinter_Default;
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
$stmts = $parser->parse($code);
$stmts = $traverser->traverse($stmts);
$this->assertEquals($expectedCode, $prettyPrinter->prettyPrint($stmts));
}
/**
* @covers PHPParser_NodeVisitor_NameResolver
*/
public function testResolveLocations() {
$code = <<<EOC
<?php
namespace NS;
class A extends B implements C {
use A;
}
interface A extends C {
public function a(A \$a);
}
A::b();
A::\$b;
A::B;
new A;
\$a instanceof A;
namespace\a();
namespace\A;
try {
\$someThing;
} catch (A \$a) {
\$someThingElse;
}
EOC;
$expectedCode = <<<EOC
namespace NS;
class A extends \\NS\\B implements \\NS\\C
{
use \\NS\\A;
}
interface A extends \\NS\\C
{
public function a(\\NS\\A \$a);
}
\\NS\\A::b();
\\NS\\A::\$b;
\\NS\\A::B;
new \\NS\\A();
\$a instanceof \\NS\\A;
\\NS\\a();
\\NS\\A;
try {
\$someThing;
} catch (\\NS\\A \$a) {
\$someThingElse;
}
EOC;
$parser = new PHPParser_Parser(new PHPParser_Lexer_Emulative);
$prettyPrinter = new PHPParser_PrettyPrinter_Default;
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
$stmts = $parser->parse($code);
$stmts = $traverser->traverse($stmts);
$this->assertEquals($expectedCode, $prettyPrinter->prettyPrint($stmts));
}
public function testNoResolveSpecialName() {
$stmts = array(new PHPParser_Node_Expr_New(new PHPParser_Node_Name('self')));
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
$this->assertEquals($stmts, $traverser->traverse($stmts));
}
protected function createNamespacedAndNonNamespaced(array $stmts) {
return array(
new PHPParser_Node_Stmt_Namespace(new PHPParser_Node_Name('NS'), $stmts),
new PHPParser_Node_Stmt_Namespace(null, $stmts),
);
}
public function testAddNamespacedName() {
$stmts = $this->createNamespacedAndNonNamespaced(array(
new PHPParser_Node_Stmt_Class('A'),
new PHPParser_Node_Stmt_Interface('B'),
new PHPParser_Node_Stmt_Function('C'),
new PHPParser_Node_Stmt_Const(array(
new PHPParser_Node_Const('D', new PHPParser_Node_Scalar_String('E'))
)),
));
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
$stmts = $traverser->traverse($stmts);
$this->assertEquals('NS\\A', (string) $stmts[0]->stmts[0]->namespacedName);
$this->assertEquals('NS\\B', (string) $stmts[0]->stmts[1]->namespacedName);
$this->assertEquals('NS\\C', (string) $stmts[0]->stmts[2]->namespacedName);
$this->assertEquals('NS\\D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName);
$this->assertEquals('A', (string) $stmts[1]->stmts[0]->namespacedName);
$this->assertEquals('B', (string) $stmts[1]->stmts[1]->namespacedName);
$this->assertEquals('C', (string) $stmts[1]->stmts[2]->namespacedName);
$this->assertEquals('D', (string) $stmts[1]->stmts[3]->consts[0]->namespacedName);
}
public function testAddTraitNamespacedName() {
$stmts = $this->createNamespacedAndNonNamespaced(array(
new PHPParser_Node_Stmt_Trait('A')
));
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
$stmts = $traverser->traverse($stmts);
$this->assertEquals('NS\\A', (string) $stmts[0]->stmts[0]->namespacedName);
$this->assertEquals('A', (string) $stmts[1]->stmts[0]->namespacedName);
}
/**
* @expectedException PHPParser_Error
* @expectedExceptionMessage Cannot use "C" as "B" because the name is already in use on line 2
*/
public function testAlreadyInUseError() {
$stmts = array(
new PHPParser_Node_Stmt_Use(array(
new PHPParser_Node_Stmt_UseUse(new PHPParser_Node_Name('A\B'), 'B', array('startLine' => 1)),
new PHPParser_Node_Stmt_UseUse(new PHPParser_Node_Name('C'), 'B', array('startLine' => 2)),
))
);
$traverser = new PHPParser_NodeTraverser;
$traverser->addVisitor(new PHPParser_NodeVisitor_NameResolver);
$traverser->traverse($stmts);
}
}

View File

@@ -0,0 +1,44 @@
<?php
require_once dirname(__FILE__) . '/CodeTestAbstract.php';
class PHPParser_Tests_ParserTest extends PHPParser_Tests_CodeTestAbstract
{
/**
* @dataProvider provideTestParse
*/
public function testParse($name, $code, $dump) {
$parser = new PHPParser_Parser(new PHPParser_Lexer_Emulative);
$dumper = new PHPParser_NodeDumper;
$stmts = $parser->parse($code);
$this->assertEquals(
$this->canonicalize($dump),
$this->canonicalize($dumper->dump($stmts)),
$name
);
}
public function provideTestParse() {
return $this->getTests(dirname(__FILE__) . '/../../code/parser', 'test');
}
/**
* @dataProvider provideTestParseFail
*/
public function testParseFail($name, $code, $msg) {
$parser = new PHPParser_Parser(new PHPParser_Lexer_Emulative);
try {
$parser->parse($code);
$this->fail(sprintf('"%s": Expected PHPParser_Error', $name));
} catch (PHPParser_Error $e) {
$this->assertEquals($msg, $e->getMessage(), $name);
}
}
public function provideTestParseFail() {
return $this->getTests(dirname(__FILE__) . '/../../code/parser', 'test-fail');
}
}

View File

@@ -0,0 +1,42 @@
<?php
require_once dirname(__FILE__) . '/CodeTestAbstract.php';
class PHPParser_Tests_PrettyPrinterTest extends PHPParser_Tests_CodeTestAbstract
{
protected function doTestPrettyPrintMethod($method, $name, $code, $dump) {
$parser = new PHPParser_Parser(new PHPParser_Lexer_Emulative);
$prettyPrinter = new PHPParser_PrettyPrinter_Default;
$stmts = $parser->parse($code);
$this->assertEquals(
$this->canonicalize($dump),
$this->canonicalize($prettyPrinter->$method($stmts)),
$name
);
}
/**
* @dataProvider provideTestPrettyPrint
* @covers PHPParser_PrettyPrinter_Default<extended>
*/
public function testPrettyPrint($name, $code, $dump) {
$this->doTestPrettyPrintMethod('prettyPrint', $name, $code, $dump);
}
/**
* @dataProvider provideTestPrettyPrintFile
* @covers PHPParser_PrettyPrinter_Default<extended>
*/
public function testPrettyPrintFile($name, $code, $dump) {
$this->doTestPrettyPrintMethod('prettyPrintFile', $name, $code, $dump);
}
public function provideTestPrettyPrint() {
return $this->getTests(dirname(__FILE__) . '/../../code/prettyPrinter', 'test');
}
public function provideTestPrettyPrintFile() {
return $this->getTests(dirname(__FILE__) . '/../../code/prettyPrinter', 'file-test');
}
}

View File

@@ -0,0 +1,152 @@
<?php
class PHPParser_Tests_Serializer_XMLTest extends PHPUnit_Framework_TestCase
{
/**
* @covers PHPParser_Serializer_XML<extended>
*/
public function testSerialize() {
$code = <<<CODE
<?php
// comment
/** doc comment */
function functionName(&\$a = 0, \$b = 1.0) {
echo 'Foo';
}
CODE;
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<AST xmlns:node="http://nikic.github.com/PHPParser/XML/node" xmlns:subNode="http://nikic.github.com/PHPParser/XML/subNode" xmlns:attribute="http://nikic.github.com/PHPParser/XML/attribute" xmlns:scalar="http://nikic.github.com/PHPParser/XML/scalar">
<scalar:array>
<node:Stmt_Function>
<attribute:comments>
<scalar:array>
<comment isDocComment="false" line="2">// comment
</comment>
<comment isDocComment="true" line="3">/** doc comment */</comment>
</scalar:array>
</attribute:comments>
<attribute:startLine>
<scalar:int>4</scalar:int>
</attribute:startLine>
<attribute:endLine>
<scalar:int>6</scalar:int>
</attribute:endLine>
<subNode:byRef>
<scalar:false/>
</subNode:byRef>
<subNode:params>
<scalar:array>
<node:Param>
<attribute:startLine>
<scalar:int>4</scalar:int>
</attribute:startLine>
<attribute:endLine>
<scalar:int>4</scalar:int>
</attribute:endLine>
<subNode:name>
<scalar:string>a</scalar:string>
</subNode:name>
<subNode:default>
<node:Scalar_LNumber>
<attribute:startLine>
<scalar:int>4</scalar:int>
</attribute:startLine>
<attribute:endLine>
<scalar:int>4</scalar:int>
</attribute:endLine>
<subNode:value>
<scalar:int>0</scalar:int>
</subNode:value>
</node:Scalar_LNumber>
</subNode:default>
<subNode:type>
<scalar:null/>
</subNode:type>
<subNode:byRef>
<scalar:true/>
</subNode:byRef>
</node:Param>
<node:Param>
<attribute:startLine>
<scalar:int>4</scalar:int>
</attribute:startLine>
<attribute:endLine>
<scalar:int>4</scalar:int>
</attribute:endLine>
<subNode:name>
<scalar:string>b</scalar:string>
</subNode:name>
<subNode:default>
<node:Scalar_DNumber>
<attribute:startLine>
<scalar:int>4</scalar:int>
</attribute:startLine>
<attribute:endLine>
<scalar:int>4</scalar:int>
</attribute:endLine>
<subNode:value>
<scalar:float>1</scalar:float>
</subNode:value>
</node:Scalar_DNumber>
</subNode:default>
<subNode:type>
<scalar:null/>
</subNode:type>
<subNode:byRef>
<scalar:false/>
</subNode:byRef>
</node:Param>
</scalar:array>
</subNode:params>
<subNode:stmts>
<scalar:array>
<node:Stmt_Echo>
<attribute:startLine>
<scalar:int>5</scalar:int>
</attribute:startLine>
<attribute:endLine>
<scalar:int>5</scalar:int>
</attribute:endLine>
<subNode:exprs>
<scalar:array>
<node:Scalar_String>
<attribute:startLine>
<scalar:int>5</scalar:int>
</attribute:startLine>
<attribute:endLine>
<scalar:int>5</scalar:int>
</attribute:endLine>
<subNode:value>
<scalar:string>Foo</scalar:string>
</subNode:value>
</node:Scalar_String>
</scalar:array>
</subNode:exprs>
</node:Stmt_Echo>
</scalar:array>
</subNode:stmts>
<subNode:name>
<scalar:string>functionName</scalar:string>
</subNode:name>
</node:Stmt_Function>
</scalar:array>
</AST>
XML;
$parser = new PHPParser_Parser(new PHPParser_Lexer);
$serializer = new PHPParser_Serializer_XML;
$stmts = $parser->parse($code);
$this->assertXmlStringEqualsXmlString($xml, $serializer->serialize($stmts));
}
/**
* @expectedException InvalidArgumentException
* @expectedExceptionMessage Unexpected node type
*/
public function testError() {
$serializer = new PHPParser_Serializer_XML;
$serializer->serialize(array(new stdClass));
}
}

View File

@@ -0,0 +1,48 @@
<?php
class PHPParser_Tests_TemplateLoaderTest extends PHPUnit_Framework_TestCase
{
public function testLoadWithoutSuffix() {
$templateLoader = new PHPParser_TemplateLoader(
new PHPParser_Parser(new PHPParser_Lexer),
dirname(__FILE__)
);
// load this file as a template, as we don't really care about the contents
$template = $templateLoader->load('TemplateLoaderTest.php');
$this->assertInstanceOf('PHPParser_Template', $template);
}
public function testLoadWithSuffix() {
$templateLoader = new PHPParser_TemplateLoader(
new PHPParser_Parser(new PHPParser_Lexer),
dirname(__FILE__), '.php'
);
// load this file as a template, as we don't really care about the contents
$template = $templateLoader->load('TemplateLoaderTest');
$this->assertInstanceOf('PHPParser_Template', $template);
}
/**
* @expectedException InvalidArgumentException
*/
public function testNonexistentBaseDirectoryError() {
new PHPParser_TemplateLoader(
new PHPParser_Parser(new PHPParser_Lexer),
dirname(__FILE__) . '/someDirectoryThatDoesNotExist'
);
}
/**
* @expectedException InvalidArgumentException
*/
public function testNonexistentFileError() {
$templateLoader = new PHPParser_TemplateLoader(
new PHPParser_Parser(new PHPParser_Lexer),
dirname(__FILE__)
);
$templateLoader->load('SomeTemplateThatDoesNotExist');
}
}

View File

@@ -0,0 +1,59 @@
<?php
class PHPParser_Tests_TemplateTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provideTestPlaceholderReplacement
* @covers PHPParser_Template
*/
public function testPlaceholderReplacement($templateCode, $placeholders, $expectedPrettyPrint) {
$parser = new PHPParser_Parser(new PHPParser_Lexer);
$prettyPrinter = new PHPParser_PrettyPrinter_Default;
$template = new PHPParser_Template($parser, $templateCode);
$this->assertEquals(
$expectedPrettyPrint,
$prettyPrinter->prettyPrint($template->getStmts($placeholders))
);
}
public function provideTestPlaceholderReplacement() {
return array(
array(
'<?php $__name__ + $__Name__;',
array('name' => 'foo'),
'$foo + $Foo;'
),
array(
'<?php $__name__ + $__Name__;',
array('Name' => 'Foo'),
'$foo + $Foo;'
),
array(
'<?php $__name__ + $__Name__;',
array('name' => 'foo', 'Name' => 'Bar'),
'$foo + $Bar;'
),
array(
'<?php $__name__ + $__Name__;',
array('Name' => 'Bar', 'name' => 'foo'),
'$foo + $Bar;'
),
array(
'<?php $prefix__Name__Suffix;',
array('name' => 'infix'),
'$prefixInfixSuffix;'
),
array(
'<?php $___name___;',
array('name' => 'foo'),
'$_foo_;'
),
array(
'<?php $foobar;',
array(),
'$foobar;'
),
);
}
}

View File

@@ -0,0 +1,141 @@
<?php
class PHPParser_Tests_Unserializer_XMLTest extends PHPUnit_Framework_TestCase
{
public function testNode() {
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<AST xmlns:node="http://nikic.github.com/PHPParser/XML/node" xmlns:subNode="http://nikic.github.com/PHPParser/XML/subNode" xmlns:attribute="http://nikic.github.com/PHPParser/XML/attribute" xmlns:scalar="http://nikic.github.com/PHPParser/XML/scalar">
<node:Scalar_String line="1" docComment="/** doc comment */">
<attribute:startLine>
<scalar:int>1</scalar:int>
</attribute:startLine>
<attribute:comments>
<scalar:array>
<comment isDocComment="false" line="2">// comment
</comment>
<comment isDocComment="true" line="3">/** doc comment */</comment>
</scalar:array>
</attribute:comments>
<subNode:value>
<scalar:string>Test</scalar:string>
</subNode:value>
</node:Scalar_String>
</AST>
XML;
$unserializer = new PHPParser_Unserializer_XML;
$this->assertEquals(
new PHPParser_Node_Scalar_String('Test', array(
'startLine' => 1,
'comments' => array(
new PHPParser_Comment('// comment' . "\n", 2),
new PHPParser_Comment_Doc('/** doc comment */', 3),
),
)),
$unserializer->unserialize($xml)
);
}
public function testEmptyNode() {
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<AST xmlns:node="http://nikic.github.com/PHPParser/XML/node">
<node:Scalar_ClassConst />
</AST>
XML;
$unserializer = new PHPParser_Unserializer_XML;
$this->assertEquals(
new PHPParser_Node_Scalar_ClassConst,
$unserializer->unserialize($xml)
);
}
public function testScalars() {
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<AST xmlns:scalar="http://nikic.github.com/PHPParser/XML/scalar">
<scalar:array>
<scalar:array></scalar:array>
<scalar:array/>
<scalar:string>test</scalar:string>
<scalar:string></scalar:string>
<scalar:string/>
<scalar:int>1</scalar:int>
<scalar:float>1</scalar:float>
<scalar:float>1.5</scalar:float>
<scalar:true/>
<scalar:false/>
<scalar:null/>
</scalar:array>
</AST>
XML;
$result = array(
array(), array(),
'test', '', '',
1,
1, 1.5,
true, false, null
);
$unserializer = new PHPParser_Unserializer_XML;
$this->assertEquals($result, $unserializer->unserialize($xml));
}
/**
* @expectedException DomainException
* @expectedExceptionMessage AST root element not found
*/
public function testWrongRootElementError() {
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<notAST/>
XML;
$unserializer = new PHPParser_Unserializer_XML;
$unserializer->unserialize($xml);
}
/**
* @dataProvider provideTestErrors
*/
public function testErrors($xml, $errorMsg) {
$this->setExpectedException('DomainException', $errorMsg);
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<AST xmlns:scalar="http://nikic.github.com/PHPParser/XML/scalar"
xmlns:node="http://nikic.github.com/PHPParser/XML/node"
xmlns:subNode="http://nikic.github.com/PHPParser/XML/subNode"
xmlns:foo="http://nikic.github.com/PHPParser/XML/foo">
$xml
</AST>
XML;
$unserializer = new PHPParser_Unserializer_XML;
$unserializer->unserialize($xml);
}
public function provideTestErrors() {
return array(
array('<scalar:true>test</scalar:true>', '"true" scalar must be empty'),
array('<scalar:false>test</scalar:false>', '"false" scalar must be empty'),
array('<scalar:null>test</scalar:null>', '"null" scalar must be empty'),
array('<scalar:foo>bar</scalar:foo>', 'Unknown scalar type "foo"'),
array('<scalar:int>x</scalar:int>', '"x" is not a valid int'),
array('<scalar:float>x</scalar:float>', '"x" is not a valid float'),
array('', 'Expected node or scalar'),
array('<foo:bar>test</foo:bar>', 'Unexpected node of type "foo:bar"'),
array(
'<node:Scalar_String><foo:bar>test</foo:bar></node:Scalar_String>',
'Expected sub node or attribute, got node of type "foo:bar"'
),
array(
'<node:Scalar_String><subNode:value/></node:Scalar_String>',
'Expected node or scalar'
),
);
}
}

View File

@@ -0,0 +1,139 @@
Array definitions
-----
<?php
array();
array('a');
array('a', );
array('a', 'b');
array('a', &$b, 'c' => 'd', 'e' => &$f);
// short array syntax
[];
[1, 2, 3];
['a' => 'b'];
-----
array(
0: Expr_Array(
items: array(
)
)
1: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_String(
value: a
)
byRef: false
)
)
)
2: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_String(
value: a
)
byRef: false
)
)
)
3: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_String(
value: a
)
byRef: false
)
1: Expr_ArrayItem(
key: null
value: Scalar_String(
value: b
)
byRef: false
)
)
)
4: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_String(
value: a
)
byRef: false
)
1: Expr_ArrayItem(
key: null
value: Expr_Variable(
name: b
)
byRef: true
)
2: Expr_ArrayItem(
key: Scalar_String(
value: c
)
value: Scalar_String(
value: d
)
byRef: false
)
3: Expr_ArrayItem(
key: Scalar_String(
value: e
)
value: Expr_Variable(
name: f
)
byRef: true
)
)
)
5: Expr_Array(
items: array(
)
)
6: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 1
)
byRef: false
)
1: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 2
)
byRef: false
)
2: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 3
)
byRef: false
)
)
)
7: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: Scalar_String(
value: a
)
value: Scalar_String(
value: b
)
byRef: false
)
)
)
)

View File

@@ -0,0 +1,225 @@
Assignments
-----
<?php
// simple assign
$a = $b;
// combined assign
$a &= $b;
$a |= $b;
$a ^= $b;
$a .= $b;
$a /= $b;
$a -= $b;
$a %= $b;
$a *= $b;
$a += $b;
$a <<= $b;
$a >>= $b;
// by ref assign
$a =& $b;
$a =& new B;
// list() assign
list($a) = $b;
list($a, , $b) = $c;
list($a, list(, $c), $d) = $e;
// inc/dec
++$a;
$a++;
--$a;
$a--;
-----
array(
0: Expr_Assign(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
1: Expr_AssignBitwiseAnd(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
2: Expr_AssignBitwiseOr(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
3: Expr_AssignBitwiseXor(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
4: Expr_AssignConcat(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
5: Expr_AssignDiv(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
6: Expr_AssignMinus(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
7: Expr_AssignMod(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
8: Expr_AssignMul(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
9: Expr_AssignPlus(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
10: Expr_AssignShiftLeft(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
11: Expr_AssignShiftRight(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
12: Expr_AssignRef(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
13: Expr_AssignRef(
var: Expr_Variable(
name: a
)
expr: Expr_New(
class: Name(
parts: array(
0: B
)
)
args: array(
)
)
)
14: Expr_Assign(
var: Expr_List(
vars: array(
0: Expr_Variable(
name: a
)
)
)
expr: Expr_Variable(
name: b
)
)
15: Expr_Assign(
var: Expr_List(
vars: array(
0: Expr_Variable(
name: a
)
1: null
2: Expr_Variable(
name: b
)
)
)
expr: Expr_Variable(
name: c
)
)
16: Expr_Assign(
var: Expr_List(
vars: array(
0: Expr_Variable(
name: a
)
1: Expr_List(
vars: array(
0: null
1: Expr_Variable(
name: c
)
)
)
2: Expr_Variable(
name: d
)
)
)
expr: Expr_Variable(
name: e
)
)
17: Expr_PreInc(
var: Expr_Variable(
name: a
)
)
18: Expr_PostInc(
var: Expr_Variable(
name: a
)
)
19: Expr_PreDec(
var: Expr_Variable(
name: a
)
)
20: Expr_PostDec(
var: Expr_Variable(
name: a
)
)
)

View File

@@ -0,0 +1,72 @@
Casts
-----
<?php
(array) $a;
(bool) $a;
(boolean) $a;
(real) $a;
(double) $a;
(float) $a;
(int) $a;
(integer) $a;
(object) $a;
(string) $a;
(unset) $a;
-----
array(
0: Expr_Cast_Array(
expr: Expr_Variable(
name: a
)
)
1: Expr_Cast_Bool(
expr: Expr_Variable(
name: a
)
)
2: Expr_Cast_Bool(
expr: Expr_Variable(
name: a
)
)
3: Expr_Cast_Double(
expr: Expr_Variable(
name: a
)
)
4: Expr_Cast_Double(
expr: Expr_Variable(
name: a
)
)
5: Expr_Cast_Double(
expr: Expr_Variable(
name: a
)
)
6: Expr_Cast_Int(
expr: Expr_Variable(
name: a
)
)
7: Expr_Cast_Int(
expr: Expr_Variable(
name: a
)
)
8: Expr_Cast_Object(
expr: Expr_Variable(
name: a
)
)
9: Expr_Cast_String(
expr: Expr_Variable(
name: a
)
)
10: Expr_Cast_Unset(
expr: Expr_Variable(
name: a
)
)
)

View File

@@ -0,0 +1,13 @@
Clone
-----
<?php
clone $a;
-----
array(
0: Expr_Clone(
expr: Expr_Variable(
name: a
)
)
)

View File

@@ -0,0 +1,94 @@
Closures
-----
<?php
function($a) { $a; };
function($a) use($b) {};
function() use($a, &$b) {};
function &($a) {};
static function() {};
-----
array(
0: Expr_Closure(
static: false
byRef: false
params: array(
0: Param(
name: a
default: null
type: null
byRef: false
)
)
uses: array(
)
stmts: array(
0: Expr_Variable(
name: a
)
)
)
1: Expr_Closure(
static: false
byRef: false
params: array(
0: Param(
name: a
default: null
type: null
byRef: false
)
)
uses: array(
0: Expr_ClosureUse(
var: b
byRef: false
)
)
stmts: array(
)
)
2: Expr_Closure(
static: false
byRef: false
params: array(
)
uses: array(
0: Expr_ClosureUse(
var: a
byRef: false
)
1: Expr_ClosureUse(
var: b
byRef: true
)
)
stmts: array(
)
)
3: Expr_Closure(
static: false
byRef: true
params: array(
0: Param(
name: a
default: null
type: null
byRef: false
)
)
uses: array(
)
stmts: array(
)
)
4: Expr_Closure(
static: true
byRef: false
params: array(
)
uses: array(
)
stmts: array(
)
)
)

View File

@@ -0,0 +1,98 @@
Comparison operators
-----
<?php
$a < $b;
$a <= $b;
$a > $b;
$a >= $b;
$a == $b;
$a === $b;
$a != $b;
$a !== $b;
$a instanceof B;
$a instanceof $b;
-----
array(
0: Expr_Smaller(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
1: Expr_SmallerOrEqual(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
2: Expr_Greater(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
3: Expr_GreaterOrEqual(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
4: Expr_Equal(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
5: Expr_Identical(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
6: Expr_NotEqual(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
7: Expr_NotIdentical(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
8: Expr_Instanceof(
expr: Expr_Variable(
name: a
)
class: Name(
parts: array(
0: B
)
)
)
9: Expr_Instanceof(
expr: Expr_Variable(
name: a
)
class: Expr_Variable(
name: b
)
)
)

View File

@@ -0,0 +1,12 @@
Error suppression
-----
<?php
@$a;
-----
array(
0: Expr_ErrorSuppress(
expr: Expr_Variable(
name: a
)
)
)

View File

@@ -0,0 +1,34 @@
Exit
-----
<?php
exit;
exit();
exit('Die!');
die;
die();
die('Exit!');
-----
array(
0: Expr_Exit(
expr: null
)
1: Expr_Exit(
expr: null
)
2: Expr_Exit(
expr: Scalar_String(
value: Die!
)
)
3: Expr_Exit(
expr: null
)
4: Expr_Exit(
expr: null
)
5: Expr_Exit(
expr: Scalar_String(
value: Exit!
)
)
)

View File

@@ -0,0 +1,71 @@
Arguments
-----
<?php
f();
f($a);
f($a, $b);
f(&$a);
-----
array(
0: Expr_FuncCall(
name: Name(
parts: array(
0: f
)
)
args: array(
)
)
1: Expr_FuncCall(
name: Name(
parts: array(
0: f
)
)
args: array(
0: Arg(
value: Expr_Variable(
name: a
)
byRef: false
)
)
)
2: Expr_FuncCall(
name: Name(
parts: array(
0: f
)
)
args: array(
0: Arg(
value: Expr_Variable(
name: a
)
byRef: false
)
1: Arg(
value: Expr_Variable(
name: b
)
byRef: false
)
)
)
3: Expr_FuncCall(
name: Name(
parts: array(
0: f
)
)
args: array(
0: Arg(
value: Expr_Variable(
name: a
)
byRef: true
)
)
)
)

View File

@@ -0,0 +1,33 @@
Constant fetches
-----
<?php
A;
A::B;
A::class;
-----
array(
0: Expr_ConstFetch(
name: Name(
parts: array(
0: A
)
)
)
1: Expr_ClassConstFetch(
class: Name(
parts: array(
0: A
)
)
name: B
)
2: Expr_ClassConstFetch(
class: Name(
parts: array(
0: A
)
)
name: class
)
)

View File

@@ -0,0 +1,181 @@
Array/string dereferencing
-----
<?php
"abc"[2];
"abc"[2][0][0];
[1, 2, 3][2];
[1, 2, 3][2][0][0];
array(1, 2, 3)[2];
array(1, 2, 3)[2][0][0];
-----
array(
0: Expr_ArrayDimFetch(
var: Scalar_String(
value: abc
)
dim: Scalar_LNumber(
value: 2
)
)
1: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Scalar_String(
value: abc
)
dim: Scalar_LNumber(
value: 2
)
)
dim: Scalar_LNumber(
value: 0
)
)
dim: Scalar_LNumber(
value: 0
)
)
2: Expr_ArrayDimFetch(
var: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 1
)
byRef: false
)
1: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 2
)
byRef: false
)
2: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 3
)
byRef: false
)
)
)
dim: Scalar_LNumber(
value: 2
)
)
3: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 1
)
byRef: false
)
1: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 2
)
byRef: false
)
2: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 3
)
byRef: false
)
)
)
dim: Scalar_LNumber(
value: 2
)
)
dim: Scalar_LNumber(
value: 0
)
)
dim: Scalar_LNumber(
value: 0
)
)
4: Expr_ArrayDimFetch(
var: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 1
)
byRef: false
)
1: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 2
)
byRef: false
)
2: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 3
)
byRef: false
)
)
)
dim: Scalar_LNumber(
value: 2
)
)
5: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 1
)
byRef: false
)
1: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 2
)
byRef: false
)
2: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 3
)
byRef: false
)
)
)
dim: Scalar_LNumber(
value: 2
)
)
dim: Scalar_LNumber(
value: 0
)
)
dim: Scalar_LNumber(
value: 0
)
)
)

View File

@@ -0,0 +1,117 @@
Function calls
-----
<?php
// function name variations
a();
$a();
${'a'}();
$$a();
$$$a();
$a['b']();
$a{'b'}();
$a->b['c']();
// array dereferencing
a()['b'];
-----
array(
0: Expr_FuncCall(
name: Name(
parts: array(
0: a
)
)
args: array(
)
)
1: Expr_FuncCall(
name: Expr_Variable(
name: a
)
args: array(
)
)
2: Expr_FuncCall(
name: Expr_Variable(
name: Scalar_String(
value: a
)
)
args: array(
)
)
3: Expr_FuncCall(
name: Expr_Variable(
name: Expr_Variable(
name: a
)
)
args: array(
)
)
4: Expr_FuncCall(
name: Expr_Variable(
name: Expr_Variable(
name: Expr_Variable(
name: a
)
)
)
args: array(
)
)
5: Expr_FuncCall(
name: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: b
)
)
args: array(
)
)
6: Expr_FuncCall(
name: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: b
)
)
args: array(
)
)
7: Expr_FuncCall(
name: Expr_ArrayDimFetch(
var: Expr_PropertyFetch(
var: Expr_Variable(
name: a
)
name: b
)
dim: Scalar_String(
value: c
)
)
args: array(
)
)
8: Expr_ArrayDimFetch(
var: Expr_FuncCall(
name: Name(
parts: array(
0: a
)
)
args: array(
)
)
dim: Scalar_String(
value: b
)
)
)

View File

@@ -0,0 +1,70 @@
New expression dereferencing
-----
<?php
(new A)->b;
(new A)->b();
(new A)['b'];
(new A)['b']['c'];
-----
array(
0: Expr_PropertyFetch(
var: Expr_New(
class: Name(
parts: array(
0: A
)
)
args: array(
)
)
name: b
)
1: Expr_MethodCall(
var: Expr_New(
class: Name(
parts: array(
0: A
)
)
args: array(
)
)
name: b
args: array(
)
)
2: Expr_ArrayDimFetch(
var: Expr_New(
class: Name(
parts: array(
0: A
)
)
args: array(
)
)
dim: Scalar_String(
value: b
)
)
3: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Expr_New(
class: Name(
parts: array(
0: A
)
)
args: array(
)
)
dim: Scalar_String(
value: b
)
)
dim: Scalar_String(
value: c
)
)
)

View File

@@ -0,0 +1,118 @@
Object access
-----
<?php
// property fetch variations
$a->b;
$a->b['c'];
$a->b{'c'};
// method call variations
$a->b();
$a->{'b'}();
$a->$b();
$a->$b['c']();
// array dereferencing
$a->b()['c'];
$a->b(){'c'}; // invalid PHP: drop Support?
-----
array(
0: Expr_PropertyFetch(
var: Expr_Variable(
name: a
)
name: b
)
1: Expr_ArrayDimFetch(
var: Expr_PropertyFetch(
var: Expr_Variable(
name: a
)
name: b
)
dim: Scalar_String(
value: c
)
)
2: Expr_ArrayDimFetch(
var: Expr_PropertyFetch(
var: Expr_Variable(
name: a
)
name: b
)
dim: Scalar_String(
value: c
)
)
3: Expr_MethodCall(
var: Expr_Variable(
name: a
)
name: b
args: array(
)
)
4: Expr_MethodCall(
var: Expr_Variable(
name: a
)
name: Scalar_String(
value: b
)
args: array(
)
)
5: Expr_MethodCall(
var: Expr_Variable(
name: a
)
name: Expr_Variable(
name: b
)
args: array(
)
)
6: Expr_MethodCall(
var: Expr_Variable(
name: a
)
name: Expr_ArrayDimFetch(
var: Expr_Variable(
name: b
)
dim: Scalar_String(
value: c
)
)
args: array(
)
)
7: Expr_ArrayDimFetch(
var: Expr_MethodCall(
var: Expr_Variable(
name: a
)
name: b
args: array(
)
)
dim: Scalar_String(
value: c
)
)
8: Expr_ArrayDimFetch(
var: Expr_MethodCall(
var: Expr_Variable(
name: a
)
name: b
args: array(
)
)
dim: Scalar_String(
value: c
)
)
)

View File

@@ -0,0 +1,62 @@
Simple array access
-----
<?php
$a['b'];
$a['b']['c'];
$a[] = $b;
$a{'b'};
${$a}['b'];
-----
array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: b
)
)
1: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: b
)
)
dim: Scalar_String(
value: c
)
)
2: Expr_Assign(
var: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: null
)
expr: Expr_Variable(
name: b
)
)
3: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: b
)
)
4: Expr_ArrayDimFetch(
var: Expr_Variable(
name: Expr_Variable(
name: a
)
)
dim: Scalar_String(
value: b
)
)
)

View File

@@ -0,0 +1,151 @@
Static calls
-----
<?php
// method name variations
A::b();
A::{'b'}();
A::$b();
A::$b['c']();
A::$b['c']['d']();
// array dereferencing
A::b()['c'];
// class name variations
static::b();
$a::b();
${'a'}::b();
$a['b']::c();
-----
array(
0: Expr_StaticCall(
class: Name(
parts: array(
0: A
)
)
name: b
args: array(
)
)
1: Expr_StaticCall(
class: Name(
parts: array(
0: A
)
)
name: Scalar_String(
value: b
)
args: array(
)
)
2: Expr_StaticCall(
class: Name(
parts: array(
0: A
)
)
name: Expr_Variable(
name: b
)
args: array(
)
)
3: Expr_StaticCall(
class: Name(
parts: array(
0: A
)
)
name: Expr_ArrayDimFetch(
var: Expr_Variable(
name: b
)
dim: Scalar_String(
value: c
)
)
args: array(
)
)
4: Expr_StaticCall(
class: Name(
parts: array(
0: A
)
)
name: Expr_ArrayDimFetch(
var: Expr_ArrayDimFetch(
var: Expr_Variable(
name: b
)
dim: Scalar_String(
value: c
)
)
dim: Scalar_String(
value: d
)
)
args: array(
)
)
5: Expr_ArrayDimFetch(
var: Expr_StaticCall(
class: Name(
parts: array(
0: A
)
)
name: b
args: array(
)
)
dim: Scalar_String(
value: c
)
)
6: Expr_StaticCall(
class: Name(
parts: array(
0: static
)
)
name: b
args: array(
)
)
7: Expr_StaticCall(
class: Expr_Variable(
name: a
)
name: b
args: array(
)
)
8: Expr_StaticCall(
class: Expr_Variable(
name: Scalar_String(
value: a
)
)
name: b
args: array(
)
)
9: Expr_StaticCall(
class: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: b
)
)
name: c
args: array(
)
)
)

View File

@@ -0,0 +1,71 @@
Static property fetches
-----
<?php
// property name variations
A::$b;
A::$$b;
A::${'b'};
// array access
A::$b['c'];
A::$b{'c'};
// class name variations can be found in staticCall.test
-----
array(
0: Expr_StaticPropertyFetch(
class: Name(
parts: array(
0: A
)
)
name: b
)
1: Expr_StaticPropertyFetch(
class: Name(
parts: array(
0: A
)
)
name: Expr_Variable(
name: b
)
)
2: Expr_StaticPropertyFetch(
class: Name(
parts: array(
0: A
)
)
name: Scalar_String(
value: b
)
)
3: Expr_ArrayDimFetch(
var: Expr_StaticPropertyFetch(
class: Name(
parts: array(
0: A
)
)
name: b
)
dim: Scalar_String(
value: c
)
)
4: Expr_ArrayDimFetch(
var: Expr_StaticPropertyFetch(
class: Name(
parts: array(
0: A
)
)
name: b
)
dim: Scalar_String(
value: c
)
)
)

View File

@@ -0,0 +1,40 @@
Include and eval
-----
<?php
include 'A.php';
include_once 'A.php';
require 'A.php';
require_once 'A.php';
eval('A');
-----
array(
0: Expr_Include(
expr: Scalar_String(
value: A.php
)
type: 1
)
1: Expr_Include(
expr: Scalar_String(
value: A.php
)
type: 2
)
2: Expr_Include(
expr: Scalar_String(
value: A.php
)
type: 3
)
3: Expr_Include(
expr: Scalar_String(
value: A.php
)
type: 4
)
4: Expr_Eval(
expr: Scalar_String(
value: A
)
)
)

View File

@@ -0,0 +1,75 @@
isset() and empty()
-----
<?php
isset($a);
isset($a, $b, $c);
empty($a);
empty(foo());
empty(array(1, 2, 3));
-----
array(
0: Expr_Isset(
vars: array(
0: Expr_Variable(
name: a
)
)
)
1: Expr_Isset(
vars: array(
0: Expr_Variable(
name: a
)
1: Expr_Variable(
name: b
)
2: Expr_Variable(
name: c
)
)
)
2: Expr_Empty(
expr: Expr_Variable(
name: a
)
)
3: Expr_Empty(
expr: Expr_FuncCall(
name: Name(
parts: array(
0: foo
)
)
args: array(
)
)
)
4: Expr_Empty(
expr: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 1
)
byRef: false
)
1: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 2
)
byRef: false
)
2: Expr_ArrayItem(
key: null
value: Scalar_LNumber(
value: 3
)
byRef: false
)
)
)
)
)

View File

@@ -0,0 +1,138 @@
Logical operators
-----
<?php
// boolean ops
$a && $b;
$a || $b;
!$a;
!!$a;
// logical ops
$a and $b;
$a or $b;
$a xor $b;
// precedence
$a && $b || $c && $d;
$a && ($b || $c) && $d;
$a = $b || $c;
$a = $b or $c;
-----
array(
0: Expr_BooleanAnd(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
1: Expr_BooleanOr(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
2: Expr_BooleanNot(
expr: Expr_Variable(
name: a
)
)
3: Expr_BooleanNot(
expr: Expr_BooleanNot(
expr: Expr_Variable(
name: a
)
)
)
4: Expr_LogicalAnd(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
5: Expr_LogicalOr(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
6: Expr_LogicalXor(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
7: Expr_BooleanOr(
left: Expr_BooleanAnd(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
right: Expr_BooleanAnd(
left: Expr_Variable(
name: c
)
right: Expr_Variable(
name: d
)
)
)
8: Expr_BooleanAnd(
left: Expr_BooleanAnd(
left: Expr_Variable(
name: a
)
right: Expr_BooleanOr(
left: Expr_Variable(
name: b
)
right: Expr_Variable(
name: c
)
)
)
right: Expr_Variable(
name: d
)
)
9: Expr_Assign(
var: Expr_Variable(
name: a
)
expr: Expr_BooleanOr(
left: Expr_Variable(
name: b
)
right: Expr_Variable(
name: c
)
)
)
10: Expr_LogicalOr(
left: Expr_Assign(
var: Expr_Variable(
name: a
)
expr: Expr_Variable(
name: b
)
)
right: Expr_Variable(
name: c
)
)
)

View File

@@ -0,0 +1,187 @@
Mathematical operators
-----
<?php
// unary ops
~$a;
+$a;
-$a;
// binary ops
$a & $b;
$a | $b;
$a ^ $b;
$a . $b;
$a / $b;
$a - $b;
$a % $b;
$a * $b;
$a + $b;
$a << $b;
$a >> $b;
// associativity
$a * $b * $c;
$a * ($b * $c);
// precedence
$a + $b * $c;
($a + $b) * $c;
-----
array(
0: Expr_BitwiseNot(
expr: Expr_Variable(
name: a
)
)
1: Expr_UnaryPlus(
expr: Expr_Variable(
name: a
)
)
2: Expr_UnaryMinus(
expr: Expr_Variable(
name: a
)
)
3: Expr_BitwiseAnd(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
4: Expr_BitwiseOr(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
5: Expr_BitwiseXor(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
6: Expr_Concat(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
7: Expr_Div(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
8: Expr_Minus(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
9: Expr_Mod(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
10: Expr_Mul(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
11: Expr_Plus(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
12: Expr_ShiftLeft(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
13: Expr_ShiftRight(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
14: Expr_Mul(
left: Expr_Mul(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
right: Expr_Variable(
name: c
)
)
15: Expr_Mul(
left: Expr_Variable(
name: a
)
right: Expr_Mul(
left: Expr_Variable(
name: b
)
right: Expr_Variable(
name: c
)
)
)
16: Expr_Plus(
left: Expr_Variable(
name: a
)
right: Expr_Mul(
left: Expr_Variable(
name: b
)
right: Expr_Variable(
name: c
)
)
)
17: Expr_Mul(
left: Expr_Plus(
left: Expr_Variable(
name: a
)
right: Expr_Variable(
name: b
)
)
right: Expr_Variable(
name: c
)
)
)

View File

@@ -0,0 +1,139 @@
New
-----
<?php
new A;
new A($b);
// class name variations
new $a();
new $a['b']();
new A::$b();
// DNCR object access
new $a->b();
new $a->b->c();
new $a->b['c']();
new $a->b{'c'}();
// test regression introduces by new dereferencing syntax
(new A);
-----
array(
0: Expr_New(
class: Name(
parts: array(
0: A
)
)
args: array(
)
)
1: Expr_New(
class: Name(
parts: array(
0: A
)
)
args: array(
0: Arg(
value: Expr_Variable(
name: b
)
byRef: false
)
)
)
2: Expr_New(
class: Expr_Variable(
name: a
)
args: array(
)
)
3: Expr_New(
class: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: b
)
)
args: array(
)
)
4: Expr_New(
class: Expr_StaticPropertyFetch(
class: Name(
parts: array(
0: A
)
)
name: b
)
args: array(
)
)
5: Expr_New(
class: Expr_PropertyFetch(
var: Expr_Variable(
name: a
)
name: b
)
args: array(
)
)
6: Expr_New(
class: Expr_PropertyFetch(
var: Expr_PropertyFetch(
var: Expr_Variable(
name: a
)
name: b
)
name: c
)
args: array(
)
)
7: Expr_New(
class: Expr_ArrayDimFetch(
var: Expr_PropertyFetch(
var: Expr_Variable(
name: a
)
name: b
)
dim: Scalar_String(
value: c
)
)
args: array(
)
)
8: Expr_New(
class: Expr_ArrayDimFetch(
var: Expr_PropertyFetch(
var: Expr_Variable(
name: a
)
name: b
)
dim: Scalar_String(
value: c
)
)
args: array(
)
)
9: Expr_New(
class: Name(
parts: array(
0: A
)
)
args: array(
)
)
)

View File

@@ -0,0 +1,12 @@
Print
-----
<?php
print $a;
-----
array(
0: Expr_Print(
expr: Expr_Variable(
name: a
)
)
)

View File

@@ -0,0 +1,38 @@
Shell execution
-----
<?php
``;
`test`;
`test $A`;
`test \``;
`test \"`;
-----
array(
0: Expr_ShellExec(
parts: array(
)
)
1: Expr_ShellExec(
parts: array(
0: test
)
)
2: Expr_ShellExec(
parts: array(
0: test
1: Expr_Variable(
name: A
)
)
)
3: Expr_ShellExec(
parts: array(
0: test `
)
)
4: Expr_ShellExec(
parts: array(
0: test \"
)
)
)

View File

@@ -0,0 +1,72 @@
Ternary operator
-----
<?php
// ternary
$a ? $b : $c;
$a ?: $c;
// precedence
$a ? $b : $c ? $d : $e;
$a ? $b : ($c ? $d : $e);
-----
array(
0: Expr_Ternary(
cond: Expr_Variable(
name: a
)
if: Expr_Variable(
name: b
)
else: Expr_Variable(
name: c
)
)
1: Expr_Ternary(
cond: Expr_Variable(
name: a
)
if: null
else: Expr_Variable(
name: c
)
)
2: Expr_Ternary(
cond: Expr_Ternary(
cond: Expr_Variable(
name: a
)
if: Expr_Variable(
name: b
)
else: Expr_Variable(
name: c
)
)
if: Expr_Variable(
name: d
)
else: Expr_Variable(
name: e
)
)
3: Expr_Ternary(
cond: Expr_Variable(
name: a
)
if: Expr_Variable(
name: b
)
else: Expr_Ternary(
cond: Expr_Variable(
name: c
)
if: Expr_Variable(
name: d
)
else: Expr_Variable(
name: e
)
)
)
)

View File

@@ -0,0 +1,54 @@
Variable syntaxes
-----
<?php
$a;
${'a'};
${foo()};
$$a;
$$$a;
$$a['b'];
-----
array(
0: Expr_Variable(
name: a
)
1: Expr_Variable(
name: Scalar_String(
value: a
)
)
2: Expr_Variable(
name: Expr_FuncCall(
name: Name(
parts: array(
0: foo
)
)
args: array(
)
)
)
3: Expr_Variable(
name: Expr_Variable(
name: a
)
)
4: Expr_Variable(
name: Expr_Variable(
name: Expr_Variable(
name: a
)
)
)
5: Expr_Variable(
name: Expr_ArrayDimFetch(
var: Expr_Variable(
name: a
)
dim: Scalar_String(
value: b
)
)
)
)

View File

@@ -0,0 +1,53 @@
Constant string syntaxes
-----
<?php
'';
"";
b'';
b"";
'Hi';
b'Hi';
"Hi";
b"Hi";
'!\'!\\!\a!';
"!\"!\\!\$!\n!\r!\t!\f!\v!\e!\a";
"!\xFF!\377!\400!\0!";
-----
array(
0: Scalar_String(
value:
)
1: Scalar_String(
value:
)
2: Scalar_String(
value:
)
3: Scalar_String(
value:
)
4: Scalar_String(
value: Hi
)
5: Scalar_String(
value: Hi
)
6: Scalar_String(
value: Hi
)
7: Scalar_String(
value: Hi
)
8: Scalar_String(
value: !'!\!\a!
)
9: Scalar_String(
value: !"!\!$!
!
!@@{ "\t" }@@!@@{ "\f" }@@!@@{ "\v" }@@!@@{ chr(27) /* "\e" */ }@@!\a
)
10: Scalar_String(
value: !@@{ chr(255) }@@!@@{ chr(255) }@@!@@{ chr(0) }@@!@@{ chr(0) }@@!
)
)

View File

@@ -0,0 +1,67 @@
Nowdoc and heredoc strings
-----
<?php
// empty strings
<<<'EOS'
EOS;
<<<EOS
EOS;
// constant encapsed strings
<<<'EOS'
Test '" $a \n
EOS;
<<<EOS
Test '" \$a \n
EOS;
// encapsed strings
<<<EOS
Test $a
EOS;
<<<EOS
Test $a and $b->c test
EOS;
// comment to force line break before EOF
-----
array(
0: Scalar_String(
value:
)
1: Scalar_String(
value:
)
2: Scalar_String(
value: Test '" $a \n
)
3: Scalar_String(
value: Test '" $a
)
4: Scalar_Encapsed(
parts: array(
0: Test
1: Expr_Variable(
name: a
)
)
)
5: Scalar_Encapsed(
parts: array(
0: Test
1: Expr_Variable(
name: a
)
2: and
3: Expr_PropertyFetch(
var: Expr_Variable(
name: b
)
name: c
)
4: test
)
)
)

View File

@@ -0,0 +1,148 @@
Encapsed strings
-----
<?php
"$A";
"$A->B";
"$A[B]";
"$A[0]";
"$A[0x0]";
"$A[$B]";
"{$A}";
"{$A['B']}";
"${A}";
"${A['B']}";
"${$A}";
"A $B C";
b"$A";
-----
array(
0: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
1: Scalar_Encapsed(
parts: array(
0: Expr_PropertyFetch(
var: Expr_Variable(
name: A
)
name: B
)
)
)
2: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: B
)
)
)
)
3: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: 0
)
)
)
)
4: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: 0x0
)
)
)
)
5: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Expr_Variable(
name: B
)
)
)
)
6: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
7: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: B
)
)
)
)
8: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
9: Scalar_Encapsed(
parts: array(
0: Expr_ArrayDimFetch(
var: Expr_Variable(
name: A
)
dim: Scalar_String(
value: B
)
)
)
)
10: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: Expr_Variable(
name: A
)
)
)
)
11: Scalar_Encapsed(
parts: array(
0: A
1: Expr_Variable(
name: B
)
2: C
)
)
12: Scalar_Encapsed(
parts: array(
0: Expr_Variable(
name: A
)
)
)
)

View File

@@ -0,0 +1,70 @@
Different float syntaxes
-----
<?php
0.0;
0.;
.0;
0e0;
0E0;
0e+0;
0e-0;
30.20e10;
300.200e100;
1e10000;
// various integer -> float overflows
// (all are actually the same number, just in different representations)
18446744073709551615;
0xFFFFFFFFFFFFFFFF;
01777777777777777777777;
0177777777777777777777787;
0b1111111111111111111111111111111111111111111111111111111111111111;
-----
array(
0: Scalar_DNumber(
value: 0
)
1: Scalar_DNumber(
value: 0
)
2: Scalar_DNumber(
value: 0
)
3: Scalar_DNumber(
value: 0
)
4: Scalar_DNumber(
value: 0
)
5: Scalar_DNumber(
value: 0
)
6: Scalar_DNumber(
value: 0
)
7: Scalar_DNumber(
value: 302000000000
)
8: Scalar_DNumber(
value: 3.002E+102
)
9: Scalar_DNumber(
value: INF
)
10: Scalar_DNumber(
value: @@{ 0xFFFFFFFFFFFFFFFF }@@
)
11: Scalar_DNumber(
value: @@{ 0xFFFFFFFFFFFFFFFF }@@
)
12: Scalar_DNumber(
value: @@{ 0xFFFFFFFFFFFFFFFF }@@
)
13: Scalar_DNumber(
value: @@{ 0xFFFFFFFFFFFFFFFF }@@
)
14: Scalar_DNumber(
value: @@{ 0xFFFFFFFFFFFFFFFF }@@
)
)

View File

@@ -0,0 +1,47 @@
Different integer syntaxes
-----
<?php
0;
1;
@@{ PHP_INT_MAX }@@;
@@{ PHP_INT_MAX + 1 }@@;
0xFFF;
0xfff;
0XfFf;
0777;
0787;
0b111000111000;
-----
array(
0: Scalar_LNumber(
value: 0
)
1: Scalar_LNumber(
value: 1
)
2: Scalar_LNumber(
value: @@{ PHP_INT_MAX }@@
)
3: Scalar_DNumber(
value: @@{ PHP_INT_MAX + 1 }@@
)
4: Scalar_LNumber(
value: 4095
)
5: Scalar_LNumber(
value: 4095
)
6: Scalar_LNumber(
value: 4095
)
7: Scalar_LNumber(
value: 511
)
8: Scalar_LNumber(
value: 7
)
9: Scalar_LNumber(
value: 3640
)
)

View File

@@ -0,0 +1,31 @@
Magic constants
-----
<?php
__CLASS__;
__DIR__;
__FILE__;
__FUNCTION__;
__LINE__;
__METHOD__;
__NAMESPACE__;
__TRAIT__;
-----
array(
0: Scalar_ClassConst(
)
1: Scalar_DirConst(
)
2: Scalar_FileConst(
)
3: Scalar_FuncConst(
)
4: Scalar_LineConst(
)
5: Scalar_MethodConst(
)
6: Scalar_NSConst(
)
7: Scalar_TraitConst(
)
)

View File

@@ -0,0 +1,112 @@
Blockless statements for if/for/etc
-----
<?php
if ($a) $A;
elseif ($b) $B;
else $C;
for (;;) $foo;
foreach ($a as $b) $AB;
while ($a) $A;
do $A; while ($a);
declare (a='b') $C;
-----
array(
0: Stmt_If(
stmts: array(
0: Expr_Variable(
name: A
)
)
elseifs: array(
0: Stmt_ElseIf(
cond: Expr_Variable(
name: b
)
stmts: array(
0: Expr_Variable(
name: B
)
)
)
)
else: Stmt_Else(
stmts: array(
0: Expr_Variable(
name: C
)
)
)
cond: Expr_Variable(
name: a
)
)
1: Stmt_For(
init: array(
)
cond: array(
)
loop: array(
)
stmts: array(
0: Expr_Variable(
name: foo
)
)
)
2: Stmt_Foreach(
keyVar: null
byRef: false
stmts: array(
0: Expr_Variable(
name: AB
)
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_Variable(
name: b
)
)
3: Stmt_While(
cond: Expr_Variable(
name: a
)
stmts: array(
0: Expr_Variable(
name: A
)
)
)
4: Stmt_Do(
cond: Expr_Variable(
name: a
)
stmts: array(
0: Expr_Variable(
name: A
)
)
)
5: Stmt_Declare(
declares: array(
0: Stmt_DeclareDeclare(
key: a
value: Scalar_String(
value: b
)
)
)
stmts: array(
0: Expr_Variable(
name: C
)
)
)
)

View File

@@ -0,0 +1,37 @@
Abstract class
-----
<?php
abstract class A {
public function a() {}
abstract public function b();
}
-----
array(
0: Stmt_Class(
type: 16
extends: null
implements: array(
)
stmts: array(
0: Stmt_ClassMethod(
type: 1
byRef: false
params: array(
)
stmts: array(
)
name: a
)
1: Stmt_ClassMethod(
type: 17
byRef: false
params: array(
)
stmts: null
name: b
)
)
name: A
)
)

View File

@@ -0,0 +1,33 @@
Conditional class definition
-----
<?php
if (true) {
class A {}
}
-----
array(
0: Stmt_If(
stmts: array(
0: Stmt_Class(
type: 0
extends: null
implements: array(
)
stmts: array(
)
name: A
)
)
elseifs: array(
)
else: null
cond: Expr_ConstFetch(
name: Name(
parts: array(
0: true
)
)
)
)
)

View File

@@ -0,0 +1,17 @@
Final class
-----
<?php
final class A {}
-----
array(
0: Stmt_Class(
type: 32
extends: null
implements: array(
)
stmts: array(
)
name: A
)
)

View File

@@ -0,0 +1,35 @@
Interface
-----
<?php
interface A extends C, D {
public function a();
}
-----
array(
0: Stmt_Interface(
extends: array(
0: Name(
parts: array(
0: C
)
)
1: Name(
parts: array(
0: D
)
)
)
stmts: array(
0: Stmt_ClassMethod(
type: 1
byRef: false
params: array(
)
stmts: null
name: a
)
)
name: A
)
)

View File

@@ -0,0 +1,29 @@
Invalid modifier combination
-----
<?php class A { public public $a; }
-----
Multiple access type modifiers are not allowed on line 1
-----
<?php class A { public protected $a; }
-----
Multiple access type modifiers are not allowed on line 1
-----
<?php class A { abstract abstract a(); }
-----
Multiple abstract modifiers are not allowed on line 1
-----
<?php class A { static static $a; }
-----
Multiple static modifiers are not allowed on line 1
-----
<?php class A { final final a() {} }
-----
Multiple final modifiers are not allowed on line 1
-----
<?php class A { abstract final a(); }
-----
Cannot use the final and abstract modifier at the same time on line 1
-----
<?php abstract final class A { }
-----
Syntax error, unexpected T_FINAL, expecting T_CLASS on line 1

View File

@@ -0,0 +1,61 @@
Invalid class name
-----
<?php class self {}
-----
Cannot use "self" as class name as it is reserved on line 1
-----
<?php class parent {}
-----
Cannot use "parent" as class name as it is reserved on line 1
-----
<?php class static {}
-----
Syntax error, unexpected T_STATIC, expecting T_STRING on line 1
-----
<?php class A extends self {}
-----
Cannot use "self" as class name as it is reserved on line 1
-----
<?php class A extends parent {}
-----
Cannot use "parent" as class name as it is reserved on line 1
-----
<?php class A extends static {}
-----
Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR on line 1
-----
<?php class A implements self {}
-----
Cannot use "self" as interface name as it is reserved on line 1
-----
<?php class A implements parent {}
-----
Cannot use "parent" as interface name as it is reserved on line 1
-----
<?php class A implements static {}
-----
Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR on line 1
-----
<?php interface self {}
-----
Cannot use "self" as interface name as it is reserved on line 1
-----
<?php interface parent {}
-----
Cannot use "parent" as interface name as it is reserved on line 1
-----
<?php interface static {}
-----
Syntax error, unexpected T_STATIC, expecting T_STRING on line 1
-----
<?php interface A extends self {}
-----
Cannot use "self" as interface name as it is reserved on line 1
-----
<?php interface A extends parent {}
-----
Cannot use "parent" as interface name as it is reserved on line 1
-----
<?php interface A extends static {}
-----
Syntax error, unexpected T_STATIC, expecting T_STRING or T_NAMESPACE or T_NS_SEPARATOR on line 1

View File

@@ -0,0 +1,38 @@
PHP 4 style declarations
-----
<?php
class A {
var $foo;
function bar() {}
}
-----
array(
0: Stmt_Class(
type: 0
extends: null
implements: array(
)
stmts: array(
0: Stmt_Property(
type: 1
props: array(
0: Stmt_PropertyProperty(
name: foo
default: null
)
)
)
1: Stmt_ClassMethod(
type: 1
byRef: false
params: array(
)
stmts: array(
)
name: bar
)
)
name: A
)
)

View File

@@ -0,0 +1,139 @@
Class declaration
-----
<?php
class A extends B implements C, D {
const A = 'B', C = 'D';
public $a = 'b', $c = 'd';
protected $e;
private $f;
public function a() {}
public static function b() {}
public final function c() {}
protected function d() {}
private function e() {}
}
-----
array(
0: Stmt_Class(
type: 0
extends: Name(
parts: array(
0: B
)
)
implements: array(
0: Name(
parts: array(
0: C
)
)
1: Name(
parts: array(
0: D
)
)
)
stmts: array(
0: Stmt_ClassConst(
consts: array(
0: Const(
name: A
value: Scalar_String(
value: B
)
)
1: Const(
name: C
value: Scalar_String(
value: D
)
)
)
)
1: Stmt_Property(
type: 1
props: array(
0: Stmt_PropertyProperty(
name: a
default: Scalar_String(
value: b
)
)
1: Stmt_PropertyProperty(
name: c
default: Scalar_String(
value: d
)
)
)
)
2: Stmt_Property(
type: 2
props: array(
0: Stmt_PropertyProperty(
name: e
default: null
)
)
)
3: Stmt_Property(
type: 4
props: array(
0: Stmt_PropertyProperty(
name: f
default: null
)
)
)
4: Stmt_ClassMethod(
type: 1
byRef: false
params: array(
)
stmts: array(
)
name: a
)
5: Stmt_ClassMethod(
type: 9
byRef: false
params: array(
)
stmts: array(
)
name: b
)
6: Stmt_ClassMethod(
type: 33
byRef: false
params: array(
)
stmts: array(
)
name: c
)
7: Stmt_ClassMethod(
type: 2
byRef: false
params: array(
)
stmts: array(
)
name: d
)
8: Stmt_ClassMethod(
type: 4
byRef: false
params: array(
)
stmts: array(
)
name: e
)
)
name: A
)
)

View File

@@ -0,0 +1,13 @@
Some special methods cannot be static
-----
<?php class A { static function __construct() {} }
-----
"__construct" method cannot be static on line 1
-----
<?php class A { static function __destruct() {} }
-----
"__destruct" method cannot be static on line 1
-----
<?php class A { static function __clone() {} }
-----
"__clone" method cannot be static on line 1

View File

@@ -0,0 +1,159 @@
Traits
-----
<?php
trait A {
public function a() {}
}
class B {
use C;
use D {
a as protected b;
c as d;
e as private;
}
use E, F, G {
E::a insteadof F, G;
E::b as protected c;
E::d as e;
E::f as private;
}
}
-----
array(
0: Stmt_Trait(
name: A
stmts: array(
0: Stmt_ClassMethod(
type: 1
byRef: false
params: array(
)
stmts: array(
)
name: a
)
)
)
1: Stmt_Class(
type: 0
extends: null
implements: array(
)
stmts: array(
0: Stmt_TraitUse(
traits: array(
0: Name(
parts: array(
0: C
)
)
)
adaptations: array(
)
)
1: Stmt_TraitUse(
traits: array(
0: Name(
parts: array(
0: D
)
)
)
adaptations: array(
0: Stmt_TraitUseAdaptation_Alias(
trait: null
method: a
newModifier: 2
newName: b
)
1: Stmt_TraitUseAdaptation_Alias(
trait: null
method: c
newModifier: null
newName: d
)
2: Stmt_TraitUseAdaptation_Alias(
trait: null
method: e
newModifier: 4
newName: null
)
)
)
2: Stmt_TraitUse(
traits: array(
0: Name(
parts: array(
0: E
)
)
1: Name(
parts: array(
0: F
)
)
2: Name(
parts: array(
0: G
)
)
)
adaptations: array(
0: Stmt_TraitUseAdaptation_Precedence(
trait: Name(
parts: array(
0: E
)
)
method: a
insteadof: array(
0: Name(
parts: array(
0: F
)
)
1: Name(
parts: array(
0: G
)
)
)
)
1: Stmt_TraitUseAdaptation_Alias(
trait: Name(
parts: array(
0: E
)
)
method: b
newModifier: 2
newName: c
)
2: Stmt_TraitUseAdaptation_Alias(
trait: Name(
parts: array(
0: E
)
)
method: d
newModifier: null
newName: e
)
3: Stmt_TraitUseAdaptation_Alias(
trait: Name(
parts: array(
0: E
)
)
method: f
newModifier: 4
newName: null
)
)
)
)
name: B
)
)

View File

@@ -0,0 +1,40 @@
Global constants
-----
<?php
const A = 0, B = 1.0, C = 'A', D = E;
-----
array(
0: Stmt_Const(
consts: array(
0: Const(
name: A
value: Scalar_LNumber(
value: 0
)
)
1: Const(
name: B
value: Scalar_DNumber(
value: 1
)
)
2: Const(
name: C
value: Scalar_String(
value: A
)
)
3: Const(
name: D
value: Expr_ConstFetch(
name: Name(
parts: array(
0: E
)
)
)
)
)
)
)

View File

@@ -0,0 +1,55 @@
Control flow statements
-----
<?php
break;
break 2;
continue;
continue 2;
return;
return $a;
throw $e;
label:
goto label;
-----
array(
0: Stmt_Break(
num: null
)
1: Stmt_Break(
num: Scalar_LNumber(
value: 2
)
)
2: Stmt_Continue(
num: null
)
3: Stmt_Continue(
num: Scalar_LNumber(
value: 2
)
)
4: Stmt_Return(
expr: null
)
5: Stmt_Return(
expr: Expr_Variable(
name: a
)
)
6: Stmt_Throw(
expr: Expr_Variable(
name: e
)
)
7: Stmt_Label(
name: label
)
8: Stmt_Goto(
name: label
)
)

View File

@@ -0,0 +1,47 @@
Declare
-----
<?php
declare (A='B', C='D') {}
declare (A='B', C='D'):
enddeclare;
-----
array(
0: Stmt_Declare(
declares: array(
0: Stmt_DeclareDeclare(
key: A
value: Scalar_String(
value: B
)
)
1: Stmt_DeclareDeclare(
key: C
value: Scalar_String(
value: D
)
)
)
stmts: array(
)
)
1: Stmt_Declare(
declares: array(
0: Stmt_DeclareDeclare(
key: A
value: Scalar_String(
value: B
)
)
1: Stmt_DeclareDeclare(
key: C
value: Scalar_String(
value: D
)
)
)
stmts: array(
)
)
)

View File

@@ -0,0 +1,32 @@
Echo
-----
<?php
echo 'Hallo World!';
echo 'Hallo', ' ', 'World', '!';
-----
array(
0: Stmt_Echo(
exprs: array(
0: Scalar_String(
value: Hallo World!
)
)
)
1: Stmt_Echo(
exprs: array(
0: Scalar_String(
value: Hallo
)
1: Scalar_String(
value:
)
2: Scalar_String(
value: World
)
3: Scalar_String(
value: !
)
)
)
)

View File

@@ -0,0 +1,37 @@
Return and pass by ref
-----
<?php
function a(&$b) {}
function &a($b) {}
-----
array(
0: Stmt_Function(
byRef: false
params: array(
0: Param(
name: b
default: null
type: null
byRef: true
)
)
stmts: array(
)
name: a
)
1: Stmt_Function(
byRef: true
params: array(
0: Param(
name: b
default: null
type: null
byRef: false
)
)
stmts: array(
)
name: a
)
)

View File

@@ -0,0 +1,32 @@
Conditional function definition
-----
<?php
if (true) {
function A() {}
}
-----
array(
0: Stmt_If(
stmts: array(
0: Stmt_Function(
byRef: false
params: array(
)
stmts: array(
)
name: A
)
)
elseifs: array(
)
else: null
cond: Expr_ConstFetch(
name: Name(
parts: array(
0: true
)
)
)
)
)

View File

@@ -0,0 +1,138 @@
Default values (static scalar tests)
-----
<?php
function a(
$b = null,
$c = 'foo',
$d = A::B,
$f = +1,
$g = -1.0,
$h = array(),
$i = [],
$j = ['foo'],
$k = ['foo', 'bar' => 'baz']
) {}
-----
array(
0: Stmt_Function(
byRef: false
params: array(
0: Param(
name: b
default: Expr_ConstFetch(
name: Name(
parts: array(
0: null
)
)
)
type: null
byRef: false
)
1: Param(
name: c
default: Scalar_String(
value: foo
)
type: null
byRef: false
)
2: Param(
name: d
default: Expr_ClassConstFetch(
class: Name(
parts: array(
0: A
)
)
name: B
)
type: null
byRef: false
)
3: Param(
name: f
default: Expr_UnaryPlus(
expr: Scalar_LNumber(
value: 1
)
)
type: null
byRef: false
)
4: Param(
name: g
default: Expr_UnaryMinus(
expr: Scalar_DNumber(
value: 1
)
)
type: null
byRef: false
)
5: Param(
name: h
default: Expr_Array(
items: array(
)
)
type: null
byRef: false
)
6: Param(
name: i
default: Expr_Array(
items: array(
)
)
type: null
byRef: false
)
7: Param(
name: j
default: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_String(
value: foo
)
byRef: false
)
)
)
type: null
byRef: false
)
8: Param(
name: k
default: Expr_Array(
items: array(
0: Expr_ArrayItem(
key: null
value: Scalar_String(
value: foo
)
byRef: false
)
1: Expr_ArrayItem(
key: Scalar_String(
value: bar
)
value: Scalar_String(
value: baz
)
byRef: false
)
)
)
type: null
byRef: false
)
)
stmts: array(
)
name: a
)
)

View File

@@ -0,0 +1,227 @@
Generators (yield expression
-----
<?php
function gen() {
// statements
yield;
yield $value;
yield $key => $value;
// expressions
$data = yield;
$data = (yield $value);
$data = (yield $key => $value);
// yield in language constructs with their own parentheses
if (yield $foo); elseif (yield $foo);
if (yield $foo): elseif (yield $foo): endif;
while (yield $foo);
do {} while (yield $foo);
switch (yield $foo) {}
die(yield $foo);
// yield in function calls
func(yield $foo);
$foo->func(yield $foo);
new Foo(yield $foo);
}
-----
array(
0: Stmt_Function(
byRef: false
params: array(
)
stmts: array(
0: Expr_Yield(
key: null
value: null
)
1: Expr_Yield(
key: null
value: Expr_Variable(
name: value
)
)
2: Expr_Yield(
key: Expr_Variable(
name: key
)
value: Expr_Variable(
name: value
)
)
3: Expr_Assign(
var: Expr_Variable(
name: data
)
expr: Expr_Yield(
key: null
value: null
)
)
4: Expr_Assign(
var: Expr_Variable(
name: data
)
expr: Expr_Yield(
key: null
value: Expr_Variable(
name: value
)
)
)
5: Expr_Assign(
var: Expr_Variable(
name: data
)
expr: Expr_Yield(
key: Expr_Variable(
name: key
)
value: Expr_Variable(
name: value
)
)
)
6: Stmt_If(
stmts: array(
)
elseifs: array(
0: Stmt_ElseIf(
cond: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
stmts: array(
)
)
)
else: null
cond: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
)
7: Stmt_If(
stmts: array(
)
elseifs: array(
0: Stmt_ElseIf(
cond: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
stmts: array(
)
)
)
else: null
cond: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
)
8: Stmt_While(
cond: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
stmts: array(
)
)
9: Stmt_Do(
cond: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
stmts: array(
)
)
10: Stmt_Switch(
cond: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
cases: array(
)
)
11: Expr_Exit(
expr: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
)
12: Expr_FuncCall(
name: Name(
parts: array(
0: func
)
)
args: array(
0: Arg(
value: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
byRef: false
)
)
)
13: Expr_MethodCall(
var: Expr_Variable(
name: foo
)
name: func
args: array(
0: Arg(
value: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
byRef: false
)
)
)
14: Expr_New(
class: Name(
parts: array(
0: Foo
)
)
args: array(
0: Arg(
value: Expr_Yield(
key: null
value: Expr_Variable(
name: foo
)
)
byRef: false
)
)
)
)
name: gen
)
)

View File

@@ -0,0 +1,50 @@
Special function variables
-----
<?php
function a() {
global $a, ${'b'}, $$c;
static $c, $d = 'e';
}
-----
array(
0: Stmt_Function(
byRef: false
params: array(
)
stmts: array(
0: Stmt_Global(
vars: array(
0: Expr_Variable(
name: a
)
1: Expr_Variable(
name: Scalar_String(
value: b
)
)
2: Expr_Variable(
name: Expr_Variable(
name: c
)
)
)
)
1: Stmt_Static(
vars: array(
0: Stmt_StaticVar(
name: c
default: null
)
1: Stmt_StaticVar(
name: d
default: Scalar_String(
value: e
)
)
)
)
)
name: a
)
)

View File

@@ -0,0 +1,44 @@
Type hints
-----
<?php
function a($b, array $c, callable $d, E $f) {}
-----
array(
0: Stmt_Function(
byRef: false
params: array(
0: Param(
name: b
default: null
type: null
byRef: false
)
1: Param(
name: c
default: null
type: array
byRef: false
)
2: Param(
name: d
default: null
type: callable
byRef: false
)
3: Param(
name: f
default: null
type: Name(
parts: array(
0: E
)
)
byRef: false
)
)
stmts: array(
)
name: a
)
)

View File

@@ -0,0 +1,55 @@
__halt_compiler
-----
<?php
$a;
__halt_compiler()
?>
Hallo World!
-----
array(
0: Expr_Variable(
name: a
)
1: Stmt_HaltCompiler(
remaining: Hallo World!
)
)
-----
<?php
$a;
__halt_compiler();Hallo World!
-----
array(
0: Expr_Variable(
name: a
)
1: Stmt_HaltCompiler(
remaining: Hallo World!
)
)
-----
<?php
namespace A;
$a;
__halt_compiler();
-----
array(
0: Stmt_Namespace(
name: Name(
parts: array(
0: A
)
)
stmts: array(
0: Expr_Variable(
name: a
)
)
)
1: Stmt_HaltCompiler(
remaining:
)
)

View File

@@ -0,0 +1,6 @@
Invalid __halt_compiler() syntax
-----
<?php
__halt_compiler()
-----
__halt_compiler must be followed by "();" on line 2

View File

@@ -0,0 +1,8 @@
__halt_compiler can only be used from outermost scope
-----
<?php
if (true) {
__halt_compiler();
}
-----
__halt_compiler() can only be used from the outermost scope on line 3

View File

@@ -0,0 +1,95 @@
If/Elseif/Else
-----
<?php
if ($a) {}
elseif ($b) {}
elseif ($c) {}
else {}
if ($a) {} // without else
if ($a):
elseif ($b):
elseif ($c):
else :
endif;
if ($a): endif; // without else
-----
array(
0: Stmt_If(
stmts: array(
)
elseifs: array(
0: Stmt_ElseIf(
cond: Expr_Variable(
name: b
)
stmts: array(
)
)
1: Stmt_ElseIf(
cond: Expr_Variable(
name: c
)
stmts: array(
)
)
)
else: Stmt_Else(
stmts: array(
)
)
cond: Expr_Variable(
name: a
)
)
1: Stmt_If(
stmts: array(
)
elseifs: array(
)
else: null
cond: Expr_Variable(
name: a
)
)
2: Stmt_If(
stmts: array(
)
elseifs: array(
0: Stmt_ElseIf(
cond: Expr_Variable(
name: b
)
stmts: array(
)
)
1: Stmt_ElseIf(
cond: Expr_Variable(
name: c
)
stmts: array(
)
)
)
else: Stmt_Else(
stmts: array(
)
)
cond: Expr_Variable(
name: a
)
)
3: Stmt_If(
stmts: array(
)
elseifs: array(
)
else: null
cond: Expr_Variable(
name: a
)
)
)

View File

@@ -0,0 +1,27 @@
Inline HTML
-----
<?php
$a;
?>
B
<?php
$c;
?>
<?php
$d;
-----
array(
0: Expr_Variable(
name: a
)
1: Stmt_InlineHTML(
value: B
)
2: Expr_Variable(
name: c
)
3: Expr_Variable(
name: d
)
)

View File

@@ -0,0 +1,17 @@
Do loop
-----
<?php
do {
} while ($a);
-----
array(
0: Stmt_Do(
cond: Expr_Variable(
name: a
)
stmts: array(
)
)
)

View File

@@ -0,0 +1,86 @@
For loop
-----
<?php
// "classical" loop
for ($i = 0; $i < $c; ++$i) {}
// multiple expressions
for (;$a,$b;) {}
// infinite loop
for (;;) {}
// alternative syntax
for (;;):
endfor;
-----
array(
0: Stmt_For(
init: array(
0: Expr_Assign(
var: Expr_Variable(
name: i
)
expr: Scalar_LNumber(
value: 0
)
)
)
cond: array(
0: Expr_Smaller(
left: Expr_Variable(
name: i
)
right: Expr_Variable(
name: c
)
)
)
loop: array(
0: Expr_PreInc(
var: Expr_Variable(
name: i
)
)
)
stmts: array(
)
)
1: Stmt_For(
init: array(
)
cond: array(
0: Expr_Variable(
name: a
)
1: Expr_Variable(
name: b
)
)
loop: array(
)
stmts: array(
)
)
2: Stmt_For(
init: array(
)
cond: array(
)
loop: array(
)
stmts: array(
)
)
3: Stmt_For(
init: array(
)
cond: array(
)
loop: array(
)
stmts: array(
)
)
)

View File

@@ -0,0 +1,139 @@
Foreach loop
-----
<?php
// foreach on variable
foreach ($a as $b) {}
foreach ($a as &$b) {}
foreach ($a as $b => $c) {}
foreach ($a as $b => &$c) {}
foreach ($a as list($a, $b)) {}
foreach ($a as $a => list($b, , $c)) {}
// foreach on expression
foreach (array() as $b) {}
// alternative syntax
foreach ($a as $b):
endforeach;
-----
array(
0: Stmt_Foreach(
keyVar: null
byRef: false
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_Variable(
name: b
)
)
1: Stmt_Foreach(
keyVar: null
byRef: true
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_Variable(
name: b
)
)
2: Stmt_Foreach(
keyVar: Expr_Variable(
name: b
)
byRef: false
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_Variable(
name: c
)
)
3: Stmt_Foreach(
keyVar: Expr_Variable(
name: b
)
byRef: true
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_Variable(
name: c
)
)
4: Stmt_Foreach(
keyVar: null
byRef: false
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_List(
vars: array(
0: Expr_Variable(
name: a
)
1: Expr_Variable(
name: b
)
)
)
)
5: Stmt_Foreach(
keyVar: Expr_Variable(
name: a
)
byRef: false
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_List(
vars: array(
0: Expr_Variable(
name: b
)
1: null
2: Expr_Variable(
name: c
)
)
)
)
6: Stmt_Foreach(
keyVar: null
byRef: false
stmts: array(
)
expr: Expr_Array(
items: array(
)
)
valueVar: Expr_Variable(
name: b
)
)
7: Stmt_Foreach(
keyVar: null
byRef: false
stmts: array(
)
expr: Expr_Variable(
name: a
)
valueVar: Expr_Variable(
name: b
)
)
)

View File

@@ -0,0 +1,25 @@
While loop
-----
<?php
while ($a) {}
while ($a):
endwhile;
-----
array(
0: Stmt_While(
cond: Expr_Variable(
name: a
)
stmts: array(
)
)
1: Stmt_While(
cond: Expr_Variable(
name: a
)
stmts: array(
)
)
)

View File

@@ -0,0 +1,85 @@
Aliases (use)
-----
<?php
use A\B;
use C\D as E;
use F\G as H, J;
// evil alias notation - Do Not Use!
use \A;
use \A as B;
-----
array(
0: Stmt_Use(
uses: array(
0: Stmt_UseUse(
name: Name(
parts: array(
0: A
1: B
)
)
alias: B
)
)
)
1: Stmt_Use(
uses: array(
0: Stmt_UseUse(
name: Name(
parts: array(
0: C
1: D
)
)
alias: E
)
)
)
2: Stmt_Use(
uses: array(
0: Stmt_UseUse(
name: Name(
parts: array(
0: F
1: G
)
)
alias: H
)
1: Stmt_UseUse(
name: Name(
parts: array(
0: J
)
)
alias: J
)
)
)
3: Stmt_Use(
uses: array(
0: Stmt_UseUse(
name: Name(
parts: array(
0: A
)
)
alias: A
)
)
)
4: Stmt_Use(
uses: array(
0: Stmt_UseUse(
name: Name(
parts: array(
0: A
)
)
alias: B
)
)
)
)

View File

@@ -0,0 +1,42 @@
Braced namespaces
-----
<?php
namespace Foo\Bar {
foo;
}
namespace {
bar;
}
-----
array(
0: Stmt_Namespace(
name: Name(
parts: array(
0: Foo
1: Bar
)
)
stmts: array(
0: Expr_ConstFetch(
name: Name(
parts: array(
0: foo
)
)
)
)
)
1: Stmt_Namespace(
name: null
stmts: array(
0: Expr_ConstFetch(
name: Name(
parts: array(
0: bar
)
)
)
)
)
)

View File

@@ -0,0 +1,13 @@
Namespace types cannot be mixed
-----
<?php
namespace A;
namespace B {}
-----
Cannot mix bracketed namespace declarations with unbracketed namespace declarations on line 3
-----
<?php
namespace A {}
namespace B;
-----
Cannot mix bracketed namespace declarations with unbracketed namespace declarations on line 3

View File

@@ -0,0 +1,42 @@
Different name types
-----
<?php
A;
A\B;
\A\B;
namespace\A\B;
-----
array(
0: Expr_ConstFetch(
name: Name(
parts: array(
0: A
)
)
)
1: Expr_ConstFetch(
name: Name(
parts: array(
0: A
1: B
)
)
)
2: Expr_ConstFetch(
name: Name_FullyQualified(
parts: array(
0: A
1: B
)
)
)
3: Expr_ConstFetch(
name: Name_Relative(
parts: array(
0: A
1: B
)
)
)
)

View File

@@ -0,0 +1,25 @@
Invalid namespace names
-----
<?php namespace self;
-----
Cannot use "self" as namespace name as it is reserved on line 1
-----
<?php namespace parent;
-----
Cannot use "parent" as namespace name as it is reserved on line 1
-----
<?php namespace static;
-----
Syntax error, unexpected T_STATIC, expecting T_STRING or T_NS_SEPARATOR or '{' on line 1
-----
<?php use A as self;
-----
Cannot use "A" as "self" because "self" is a special class name on line 1
-----
<?php use B as parent;
-----
Cannot use "B" as "parent" because "parent" is a special class name on line 1
-----
<?php use C as static;
-----
Syntax error, unexpected T_STATIC, expecting T_STRING on line 1

View File

@@ -0,0 +1,10 @@
Nested namespaces are not allowed
-----
<?php
namespace A {
namespace B {
}
}
-----
Namespace declarations cannot be nested on line 3

View File

@@ -0,0 +1,45 @@
Semicolon style namespaces
-----
<?php
namespace Foo\Bar;
foo;
namespace Bar;
bar;
-----
array(
0: Stmt_Namespace(
name: Name(
parts: array(
0: Foo
1: Bar
)
)
stmts: array(
0: Expr_ConstFetch(
name: Name(
parts: array(
0: foo
)
)
)
)
)
1: Stmt_Namespace(
name: Name(
parts: array(
0: Bar
)
)
stmts: array(
0: Expr_ConstFetch(
name: Name(
parts: array(
0: bar
)
)
)
)
)
)

View File

@@ -0,0 +1,37 @@
Some statements may occur outside of namespaces
-----
<?php
declare(A='B');
namespace B {
}
__halt_compiler()
?>
Hi!
-----
array(
0: Stmt_Declare(
declares: array(
0: Stmt_DeclareDeclare(
key: A
value: Scalar_String(
value: B
)
)
)
stmts: array(
)
)
1: Stmt_Namespace(
name: Name(
parts: array(
0: B
)
)
stmts: array(
)
)
2: Stmt_HaltCompiler(
remaining: Hi!
)
)

View File

@@ -0,0 +1,13 @@
There (mostly) can't be statements outside of namespaces
-----
<?php
echo 1;
namespace A;
-----
Namespace declaration statement has to be the very first statement in the script on line 3
-----
<?php
namespace A {}
echo 1;
-----
No code may exist outside of namespace {} on line 3

View File

@@ -0,0 +1,67 @@
Switch
-----
<?php
switch ($a) {
case 0:
case 1;
default:
}
// alternative syntax
switch ($a):
endswitch;
// leading semicolon
switch ($a) { ; }
switch ($a): ; endswitch;
-----
array(
0: Stmt_Switch(
cond: Expr_Variable(
name: a
)
cases: array(
0: Stmt_Case(
cond: Scalar_LNumber(
value: 0
)
stmts: array(
)
)
1: Stmt_Case(
cond: Scalar_LNumber(
value: 1
)
stmts: array(
)
)
2: Stmt_Case(
cond: null
stmts: array(
)
)
)
)
1: Stmt_Switch(
cond: Expr_Variable(
name: a
)
cases: array(
)
)
2: Stmt_Switch(
cond: Expr_Variable(
name: a
)
cases: array(
)
)
3: Stmt_Switch(
cond: Expr_Variable(
name: a
)
cases: array(
)
)
)

View File

@@ -0,0 +1,114 @@
Try/catch
-----
<?php
try {
doTry();
} catch (A $b) {
doCatchA();
} catch (B $c) {
doCatchB();
} finally {
doFinally();
}
// no finally
try { }
catch (A $b) { }
// no catch
try { }
finally { }
-----
array(
0: Stmt_TryCatch(
stmts: array(
0: Expr_FuncCall(
name: Name(
parts: array(
0: doTry
)
)
args: array(
)
)
)
catches: array(
0: Stmt_Catch(
type: Name(
parts: array(
0: A
)
)
var: b
stmts: array(
0: Expr_FuncCall(
name: Name(
parts: array(
0: doCatchA
)
)
args: array(
)
)
)
)
1: Stmt_Catch(
type: Name(
parts: array(
0: B
)
)
var: c
stmts: array(
0: Expr_FuncCall(
name: Name(
parts: array(
0: doCatchB
)
)
args: array(
)
)
)
)
)
finallyStmts: array(
0: Expr_FuncCall(
name: Name(
parts: array(
0: doFinally
)
)
args: array(
)
)
)
)
1: Stmt_TryCatch(
stmts: array(
)
catches: array(
0: Stmt_Catch(
type: Name(
parts: array(
0: A
)
)
var: b
stmts: array(
)
)
)
finallyStmts: null
)
2: Stmt_TryCatch(
stmts: array(
)
catches: array(
)
finallyStmts: array(
)
)
)

Some files were not shown because too many files have changed in this diff Show More