Add interface builder

This commit is contained in:
Florent 2013-05-23 10:31:59 +02:00 committed by nikic
parent c0da1b88b2
commit 12faad529e
4 changed files with 216 additions and 29 deletions

View File

@ -0,0 +1,92 @@
<?php
class PHPParser_Builder_Interface extends PHPParser_BuilderAbstract
{
protected $name;
protected $extends;
protected $constants;
protected $methods;
/**
* Creates an interface builder.
*
* @param string $name Name of the interface
*/
public function __construct($name) {
$this->name = $name;
$this->extends = array();
$this->constants = $this->methods = array();
}
/**
* Extends one or more interfaces.
*
* @param PHPParser_Node_Name|string $interface Name of interface to extend
* @param PHPParser_Node_Name|string $... More interfaces to extend
*
* @return PHPParser_Builder_Interface The builder instance (for fluid interface)
*/
public function extend() {
foreach (func_get_args() as $interface) {
$this->extends[] = $this->normalizeName($interface);
}
return $this;
}
/**
* Adds a statement.
*
* @param PHPParser_Node_Stmt|PHPParser_Builder $stmt The statement to add
*
* @return PHPParser_Builder_Interface The builder instance (for fluid interface)
*/
public function addStmt($stmt) {
$stmt = $this->normalizeNode($stmt);
$type = $stmt->getType();
switch ($type) {
case 'Stmt_ClassConst':
$this->constants[] = $stmt;
break;
case 'Stmt_ClassMethod':
// we erase all statements in the body of an interface method
$stmt->stmts = null;
$this->methods[] = $stmt;
break;
default:
throw new LogicException(sprintf('Unexpected node of type "%s"', $type));
}
return $this;
}
/**
* Adds multiple statements.
*
* @param array $stmts The statements to add
*
* @return PHPParser_Builder_Class The builder instance (for fluid interface)
*/
public function addStmts(array $stmts) {
foreach ($stmts as $stmt) {
$this->addStmt($stmt);
}
return $this;
}
/**
* Returns the built class node.
*
* @return PHPParser_Node_Stmt_Interface The built interface node
*/
public function getNode() {
return new PHPParser_Node_Stmt_Interface($this->name, array(
'extends' => $this->extends,
'stmts' => array_merge($this->constants, $this->methods),
));
}
}

View File

@ -1,12 +1,13 @@
<?php
/**
* "class" and "function" are reserved keywords, so the methods are defined as _class()
* and _function() in the class and are made available as class() and function() through
* __call() magic.
* "class", "interface" and "function" are reserved keywords, so the methods are defined as _class(),
* _interface() and _function() in the class and are made available as class(), interface() and function()
* through __call() magic.
*
* @method PHPParser_Builder_Class class(string $name) Creates a class builder.
* @method PHPParser_Builder_Function function(string $name) Creates a function builder
* @method PHPParser_Builder_Class class(string $name) Creates a class builder.
* @method PHPParser_Builder_Function function(string $name) Creates a function builder
* @method PHPParser_Builder_Interface interface(string $name) Creates an interface builder.
*/
class PHPParser_BuilderFactory
{
@ -21,6 +22,17 @@ class PHPParser_BuilderFactory
return new PHPParser_Builder_Class($name);
}
/**
* Creates a interface builder.
*
* @param string $name Name of the interface
*
* @return PHPParser_Builder_Class The created interface builder
*/
protected function _interface($name) {
return new PHPParser_Builder_Interface($name);
}
/**
* Creates a method builder.
*
@ -66,10 +78,8 @@ class PHPParser_BuilderFactory
}
public function __call($name, array $args) {
if ('class' === $name) {
return call_user_func_array(array($this, '_class'), $args);
} elseif ('function' === $name) {
return call_user_func_array(array($this, '_function'), $args);
if (method_exists($this, '_' . $name)) {
return call_user_func_array(array($this, '_' . $name), $args);
}
throw new LogicException(sprintf('Method "%s" does not exist', $name));

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

@ -2,28 +2,22 @@
class PHPParser_Tests_BuilderFactoryTest extends PHPUnit_Framework_TestCase
{
public function testCreateClassBuilder() {
/**
* @dataProvider provideTestFactory
*/
public function testFactory($methodName, $className) {
$factory = new PHPParser_BuilderFactory;
$this->assertInstanceOf('PHPParser_Builder_Class', $factory->class('Test'));
$this->assertInstanceOf($className, $factory->$methodName('test'));
}
public function testCreateMethodBuilder() {
$factory = new PHPParser_BuilderFactory;
$this->assertInstanceOf('PHPParser_Builder_Method', $factory->method('test'));
}
public function testCreateParamBuilder() {
$factory = new PHPParser_BuilderFactory;
$this->assertInstanceOf('PHPParser_Builder_Param', $factory->param('test'));
}
public function testCreatePropertyBuilder() {
$factory = new PHPParser_BuilderFactory;
$this->assertInstanceOf('PHPParser_Builder_Property', $factory->property('test'));
}
public function testCreateFunctionBuilder() {
$factory = new PHPParser_BuilderFactory;
$this->assertInstanceOf('PHPParser_Builder_Function', $factory->function('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'),
);
}
}