From 12faad529e32d5052298e16b9e36b88757e2540f Mon Sep 17 00:00:00 2001 From: Florent Date: Thu, 23 May 2013 10:31:59 +0200 Subject: [PATCH] Add interface builder --- lib/PHPParser/Builder/Interface.php | 92 +++++++++++++++++++ lib/PHPParser/BuilderFactory.php | 28 ++++-- .../PHPParser/Tests/Builder/InterfaceTest.php | 91 ++++++++++++++++++ test/PHPParser/Tests/BuilderFactoryTest.php | 34 +++---- 4 files changed, 216 insertions(+), 29 deletions(-) create mode 100644 lib/PHPParser/Builder/Interface.php create mode 100644 test/PHPParser/Tests/Builder/InterfaceTest.php diff --git a/lib/PHPParser/Builder/Interface.php b/lib/PHPParser/Builder/Interface.php new file mode 100644 index 0000000..8c76dc9 --- /dev/null +++ b/lib/PHPParser/Builder/Interface.php @@ -0,0 +1,92 @@ +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), + )); + } +} \ No newline at end of file diff --git a/lib/PHPParser/BuilderFactory.php b/lib/PHPParser/BuilderFactory.php index 2212dd8..48941dc 100644 --- a/lib/PHPParser/BuilderFactory.php +++ b/lib/PHPParser/BuilderFactory.php @@ -1,12 +1,13 @@ 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)); + } +} + diff --git a/test/PHPParser/Tests/BuilderFactoryTest.php b/test/PHPParser/Tests/BuilderFactoryTest.php index c0d5501..0eaf8a9 100644 --- a/test/PHPParser/Tests/BuilderFactoryTest.php +++ b/test/PHPParser/Tests/BuilderFactoryTest.php @@ -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'), + ); } } \ No newline at end of file