Skip to content

Implemented extensions system. #95

Merged
merged 1 commit into from Jan 23, 2013
+587 −19
View
2 composer.json
@@ -17,7 +17,7 @@
"eloquent/blox": "~1",
"eloquent/cosmos": "~2",
"eloquent/enumeration": "~3",
- "eloquent/typhax": "~0.8",
+ "eloquent/typhax": "dev-master",
"icecave/isolator": "~2",
"icecave/pasta-ast": "~0.1",
"icecave/rasta": "~0.1",
View
28 composer.lock
@@ -1,5 +1,5 @@
{
- "hash": "9da65ccda6b2404847e3b69e0f803507",
+ "hash": "a456aa34fa1d0f4893a42aebd1c25530",
"packages": [
{
"name": "eloquent/asplode",
@@ -253,16 +253,16 @@
},
{
"name": "eloquent/typhax",
- "version": "0.8.2",
+ "version": "dev-master",
"source": {
"type": "git",
"url": "git://github.com/eloquent/typhax.git",
- "reference": "0.8.2"
+ "reference": "6f220ef6c4ce7a74ee474e132d24f56d332b8790"
},
"dist": {
"type": "zip",
- "url": "https://github.com/eloquent/typhax/archive/0.8.2.zip",
- "reference": "0.8.2",
+ "url": "https://github.com/eloquent/typhax/archive/6f220ef6c4ce7a74ee474e132d24f56d332b8790.zip",
+ "reference": "6f220ef6c4ce7a74ee474e132d24f56d332b8790",
"shasum": ""
},
"require": {
@@ -274,14 +274,14 @@
"require-dev": {
"icecave/testing": ">=1.0,<2.0"
},
- "time": "2013-01-19 13:51:39",
+ "time": "2013-01-23 12:02:24",
"type": "library",
"autoload": {
"psr-0": {
"Eloquent\\Typhax": "src"
}
},
- "notification-url": "https://packagist.org/downloads/",
+ "notification-url": "http://packagist.org/downloads/",
"license": [
"MIT"
],
@@ -342,7 +342,7 @@
"Icecave\\Collections\\TypeCheck": "lib-typhoon"
}
},
- "notification-url": "https://packagist.org/downloads/",
+ "notification-url": "http://packagist.org/downloads/",
"license": [
"MIT"
],
@@ -392,7 +392,7 @@
"Icecave\\Isolator": "lib"
}
},
- "notification-url": "https://packagist.org/downloads/",
+ "notification-url": "http://packagist.org/downloads/",
"license": [
"MIT"
],
@@ -490,7 +490,7 @@
"Icecave\\Rasta": "lib"
}
},
- "notification-url": "https://packagist.org/downloads/",
+ "notification-url": "http://packagist.org/downloads/",
"license": [
"MIT"
],
@@ -534,7 +534,7 @@
"Icecave\\Repr": "lib"
}
},
- "notification-url": "https://packagist.org/downloads/",
+ "notification-url": "http://packagist.org/downloads/",
"license": [
"MIT"
],
@@ -1029,7 +1029,7 @@
],
"minimum-stability": "stable",
- "stability-flags": [
-
- ]
+ "stability-flags": {
+ "eloquent/typhax": 20
+ }
}
View
32 ...eck/Validator/Eloquent/Typhoon/Extension/Exception/InvalidExtensionExceptionTypeCheck.php
@@ -0,0 +1,32 @@
+<?php
+namespace Eloquent\Typhoon\TypeCheck\Validator\Eloquent\Typhoon\Extension\Exception;
+
+class InvalidExtensionExceptionTypeCheck extends \Eloquent\Typhoon\TypeCheck\AbstractValidator
+{
+ public function validateConstruct(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('className', 0, 'string');
+ } elseif ($argumentCount > 2) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(2, $arguments[2]);
+ }
+ $value = $arguments[0];
+ if (!\is_string($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'className',
+ 0,
+ $arguments[0],
+ 'string'
+ );
+ }
+ }
+
+ public function className(array $arguments)
+ {
+ if (\count($arguments) > 0) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(0, $arguments[0]);
+ }
+ }
+
+}
View
82 ...quent/Typhoon/TypeCheck/Validator/Eloquent/Typhoon/Extension/ExtensionLoaderTypeCheck.php
@@ -0,0 +1,82 @@
+<?php
+namespace Eloquent\Typhoon\TypeCheck\Validator\Eloquent\Typhoon\Extension;
+
+class ExtensionLoaderTypeCheck extends \Eloquent\Typhoon\TypeCheck\AbstractValidator
+{
+ public function validateConstruct(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount > 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ }
+
+ public function load(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('className', 0, 'string');
+ } elseif ($argumentCount > 2) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(2, $arguments[2]);
+ }
+ $value = $arguments[0];
+ if (!\is_string($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'className',
+ 0,
+ $arguments[0],
+ 'string'
+ );
+ }
+ if ($argumentCount > 1) {
+ $value = $arguments[1];
+ if (!\is_bool($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'forceReload',
+ 1,
+ $arguments[1],
+ 'boolean'
+ );
+ }
+ }
+ }
+
+ public function unload(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('className', 0, 'string');
+ } elseif ($argumentCount > 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ $value = $arguments[0];
+ if (!\is_string($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'className',
+ 0,
+ $arguments[0],
+ 'string'
+ );
+ }
+ }
+
+ public function isLoaded(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('className', 0, 'string');
+ } elseif ($argumentCount > 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ $value = $arguments[0];
+ if (!\is_string($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'className',
+ 0,
+ $arguments[0],
+ 'string'
+ );
+ }
+ }
+
+}
View
14 ...nt/Typhoon/TypeCheck/Validator/Eloquent/Typhoon/Generator/TyphaxASTGeneratorTypeCheck.php
@@ -6,8 +6,8 @@ class TyphaxASTGeneratorTypeCheck extends \Eloquent\Typhoon\TypeCheck\AbstractVa
public function validateConstruct(array $arguments)
{
$argumentCount = \count($arguments);
- if ($argumentCount > 1) {
- throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ if ($argumentCount > 2) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(2, $arguments[2]);
}
}
@@ -51,6 +51,16 @@ public function visitCallableType(array $arguments)
}
}
+ public function visitExtensionType(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('type', 0, 'Eloquent\\Typhax\\Type\\ExtensionType');
+ } elseif ($argumentCount > 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ }
+
public function visitFloatType(array $arguments)
{
$argumentCount = \count($arguments);
View
53 src/Eloquent/Typhoon/Extension/Exception/InvalidExtensionException.php
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\Extension\Exception;
+
+use Eloquent\Typhoon\TypeCheck\TypeCheck;
+use Exception;
+use LogicException;
+
+final class InvalidExtensionException extends LogicException
+{
+ /**
+ * @param string $className
+ * @param Exception|null $previous
+ */
+ public function __construct(
+ $className,
+ Exception $previous = null
+ ) {
+ $this->typeCheck = TypeCheck::get(__CLASS__, func_get_args());
+ $this->className = $className;
+
+ parent::__construct(
+ sprintf(
+ "The extension type '%s' does not exist, or does not implement ExtensionInterface.",
+ $this->className()
+ ),
+ 0,
+ $previous
+ );
+ }
+
+ /**
+ * @return string
+ */
+ public function className()
+ {
+ $this->typeCheck->className(func_get_args());
+
+ return $this->className;
+ }
+
+ private $className;
+ private $typeCheck;
+}
View
27 src/Eloquent/Typhoon/Extension/ExtensionInterface.php
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\Extension;
+
+use Eloquent\Typhax\Type\ExtensionType;
+use Eloquent\Typhoon\Generator\TyphaxASTGenerator;
+use Icecave\Pasta\AST\Func\Closure;
+
+interface ExtensionInterface
+{
+ /**
+ * @param TyphaxASTGenerator $generator The AST generator that loaded this extension.
+ * @param ExtensionType $type Type extension type for which code should be generated.
+ *
+ * @return Closure A closure AST node that accepts a single value parameter.
+ */
+ public function generateTypeCheck(TyphaxASTGenerator $generator, ExtensionType $extensionType);
+}
View
82 src/Eloquent/Typhoon/Extension/ExtensionLoader.php
@@ -0,0 +1,82 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\Extension;
+
+use Eloquent\Typhoon\TypeCheck\TypeCheck;
+use ReflectionClass;
+use ReflectionException;
+
+class ExtensionLoader implements ExtensionLoaderInterface
+{
+ /**
+ * @param array $constructorArguments Arguments to forward to each extension's constructor.
+ */
+ public function __construct(array $constructorArguments = array())
+ {
+ $this->typeCheck = TypeCheck::get(__CLASS__, func_get_args());
+
+ $this->constructorArguments = $constructorArguments;
+ $this->extensions = array();
+ }
+
+ /**
+ * @param string $className The name of the extension class.
+ * @param boolean $forceReload
+ *
+ * @return ExtensionInterface
+ */
+ public function load($className, $forceReload = false)
+ {
+ $this->typeCheck->load(func_get_args());
+
+ // Extension is already loaded ...
+ if (!$forceReload && $this->isLoaded($className)) {
+ return $this->extensions[$className];
+ }
+
+ // Obtain a reflector ...
+ try {
+ $reflector = new ReflectionClass($className);
+ } catch (ReflectionException $e) {
+ throw new Exception\InvalidExtensionException($className, $e);
+ }
+
+ // Verify interface ...
+ if (!$reflector->implementsInterface('Eloquent\Typhoon\Extension\ExtensionInterface')) {
+ throw new Exception\InvalidExtensionException($className);
+ }
+
+ return $this->extensions[$className] = $reflector->newInstanceArgs($this->constructorArguments);
+ }
+
+ /**
+ * @param string $className The name of the extension class.
+ */
+ public function unload($className)
+ {
+ unset($this->extensions[$className]);
+ }
+
+ /**
+ * @param string $className The name of the extension class.
+ *
+ * @return boolean
+ */
+ public function isLoaded($className)
+ {
+ return array_key_exists($className, $this->extensions);
+ }
+
+ private $constructorArguments;
+ private $extensions;
+ private $typeCheck;
+}
View
35 src/Eloquent/Typhoon/Extension/ExtensionLoaderInterface.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\Extension;
+
+interface ExtensionLoaderInterface
+{
+ /**
+ * @param string $className The name of the extension class.
+ * @param boolean $forceReload
+ *
+ * @return ExtensionInterface
+ */
+ public function load($className, $forceReload = false);
+
+ /**
+ * @param string $className The name of the extension class.
+ */
+ public function unload($className);
+
+ /**
+ * @param string $className The name of the extension class.
+ *
+ * @return boolean
+ */
+ public function isLoaded($className);
+}
View
30 src/Eloquent/Typhoon/Generator/TyphaxASTGenerator.php
@@ -15,6 +15,7 @@
use Eloquent\Typhax\Type\ArrayType;
use Eloquent\Typhax\Type\BooleanType;
use Eloquent\Typhax\Type\CallableType;
+use Eloquent\Typhax\Type\ExtensionType;
use Eloquent\Typhax\Type\FloatType;
use Eloquent\Typhax\Type\IntegerType;
use Eloquent\Typhax\Type\MixedType;
@@ -29,6 +30,8 @@
use Eloquent\Typhax\Type\TraversableType;
use Eloquent\Typhax\Type\TupleType;
use Eloquent\Typhax\Type\Visitor;
+use Eloquent\Typhoon\Extension\ExtensionLoader;
+use Eloquent\Typhoon\Extension\ExtensionLoaderInterface;
use Eloquent\Typhoon\TypeCheck\TypeCheck;
use Icecave\Pasta\AST\Expr\Assign;
use Icecave\Pasta\AST\Expr\Call;
@@ -58,17 +61,23 @@ class TyphaxASTGenerator implements Visitor
{
/**
* @param Identifier|null $valueIdentifier
+ * @param ExtensionLoaderInterface|null $extensionLoader
*/
public function __construct(
- Identifier $valueIdentifier = null
+ Identifier $valueIdentifier = null,
+ ExtensionLoaderInterface $extensionLoader = null
) {
$this->typeCheck = TypeCheck::get(__CLASS__, func_get_args());
if (null === $valueIdentifier) {
$valueIdentifier = new Identifier('value');
}
+ if (null === $extensionLoader) {
+ $extensionLoader = new ExtensionLoader;
+ }
$this->valueIdentifier = $valueIdentifier;
+ $this->extensionLoader = $extensionLoader;
}
/**
@@ -193,6 +202,24 @@ public function visitCallableType(CallableType $type)
}
/**
+ * @param ExtensionType $type
+ *
+ * @return Call
+ */
+ public function visitExtensionType(ExtensionType $type)
+ {
+ $this->typeCheck->visitExtensionType(func_get_args());
+
+ $extension = $this->extensionLoader->load($type->className()->string());
+ $closure = $extension->generateTypeCheck($this, $type);
+
+ $call = new Call($closure);
+ $call->add($this->valueExpression());
+
+ return $call;
+ }
+
+ /**
* @param FloatType $type
*
* @return Call
@@ -790,5 +817,6 @@ protected function valueExpression()
private $valueIdentifier;
private $valueIndex;
+ private $extensionLoader;
private $typeCheck;
}
View
55 test/src/Eloquent/Typhoon/TestFixture/ExtensionFixtures/TestExtension.php
@@ -0,0 +1,55 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\TestFixture\ExtensionFixtures;
+
+use Eloquent\Typhax\Type\ExtensionType;
+use Eloquent\Typhoon\Extension\ExtensionInterface;
+use Eloquent\Typhoon\Generator\TyphaxASTGenerator;
+use Icecave\Pasta\AST\Expr\Equals;
+use Icecave\Pasta\AST\Expr\Literal;
+use Icecave\Pasta\AST\Expr\Variable;
+use Icecave\Pasta\AST\Func\Closure;
+use Icecave\Pasta\AST\Func\Parameter;
+use Icecave\Pasta\AST\Identifier;
+use Icecave\Pasta\AST\Stmt\ReturnStatement;
+
+class TestExtension implements ExtensionInterface
+{
+ public function __construct()
+ {
+ $this->args = func_get_args();
+ }
+
+ /**
+ * @param TyphaxASTGenerator $generator The AST generator that loaded this extension.
+ * @param ExtensionType $type Type extension type for which code should be generated.
+ *
+ * @return Closure A closure AST node that accepts a single value parameter.
+ */
+ public function generateTypeCheck(TyphaxASTGenerator $generator, ExtensionType $extensionType)
+ {
+ $closure = new Closure;
+ $closure->addParameter(new Parameter(new Identifier('value')));
+ $closure->statementBlock()->add(
+ new ReturnStatement(
+ new Equals(
+ new Variable(new Identifier('value')),
+ new Literal(12345)
+ )
+ )
+ );
+
+ return $closure;
+ }
+
+ public $args;
+}
View
8 test/src/Eloquent/Typhoon/TestFixture/SampleClasses/TypicalClass.php
@@ -11,6 +11,7 @@
namespace Eloquent\Typhoon\TestFixture\SampleClasses;
+use Eloquent\Typhoon\TestFixture\ExtensionFixtures\TestExtension;
use Iterator;
use stdClass;
@@ -189,4 +190,11 @@ private function onlyOptional($foo = 'bar')
private function variableLength($foo)
{
}
+
+ /**
+ * @param :TestExtension $foo
+ */
+ private function extensionType($foo)
+ {
+ }
}
View
21 test/src/foo/Validator/Eloquent/Typhoon/TestFixture/SampleClasses/TypicalClassTypeCheck.php
@@ -1059,4 +1059,25 @@ public function variableLength(array $arguments)
}
}
+ public function extensionType(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \foo\Exception\MissingArgumentException('foo', 0, ':Eloquent\\Typhoon\\TestFixture\\ExtensionFixtures\\TestExtension');
+ } elseif ($argumentCount > 1) {
+ throw new \foo\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ $value = $arguments[0];
+ if (!function ($value) {
+ return ($value == 12345);
+ }($value)) {
+ throw new \foo\Exception\UnexpectedArgumentValueException(
+ 'foo',
+ 0,
+ $arguments[0],
+ ':Eloquent\\Typhoon\\TestFixture\\ExtensionFixtures\\TestExtension'
+ );
+ }
+ }
+
}
View
35 test/suite/Eloquent/Typhoon/Extension/Exception/InvalidExtensionExceptionTest.php
@@ -0,0 +1,35 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\Extension\Exception;
+
+use Eloquent\Typhoon\TestCase\MultiGenerationTestCase;
+use Phake;
+
+class InvalidExtensionExceptionTest extends MultiGenerationTestCase
+{
+ public function testException()
+ {
+ $previous = Phake::mock('Exception');
+ $exception = new InvalidExtensionException(
+ 'foo',
+ $previous
+ );
+
+ $this->assertSame(
+ "The extension type 'foo' does not exist, or does not implement ExtensionInterface.",
+ $exception->getMessage()
+ );
+ $this->assertSame('foo', $exception->className());
+ $this->assertSame(0, $exception->getCode());
+ $this->assertSame($previous, $exception->getPrevious());
+ }
+}
View
68 test/suite/Eloquent/Typhoon/Extension/ExtensionLoaderTest.php
@@ -0,0 +1,68 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\Extension;
+
+use Eloquent\Typhoon\TestCase\MultiGenerationTestCase;
+use Phake;
+
+class ExtensionLoaderTest extends MultiGenerationTestCase
+{
+ public function setUp()
+ {
+ $this->_closure = Phake::mock('Icecave\Pasta\AST\Func\Closure');
+ $this->_arguments = array($this->_closure, 1, 2, 3);
+ $this->_loader = new ExtensionLoader($this->_arguments);
+ }
+
+ public function testLoad()
+ {
+ $className = 'Eloquent\Typhoon\TestFixture\ExtensionFixtures\TestExtension';
+
+ $this->assertFalse($this->_loader->isLoaded($className));
+
+ $extension = $this->_loader->load($className);
+
+ $this->assertTrue($this->_loader->isLoaded($className));
+ $this->assertInstanceOf($className, $extension);
+ $this->assertSame($this->_arguments, $extension->args);
+
+ // Repeat call gives same instance ...
+ $this->assertSame($extension, $this->_loader->load($className));
+
+ // Unless forced reload ...
+ $newExtension = $this->_loader->load($className, true);
+ $this->assertInstanceOf($className, $newExtension);
+ $this->assertNotSame($extension, $newExtension);
+ }
+
+ public function testLoadFailure()
+ {
+ $className = 'Eloquent\Typhoon\TestFixture\ExtensionFixtures\NotExistantClass';
+ $this->setExpectedException(__NAMESPACE__.'\Exception\InvalidExtensionException', "The extension type '".$className."' does not exist, or does not implement ExtensionInterface.");
+ $this->_loader->load($className);
+ }
+
+ public function testLoadFailureDoesNotImplementInterface()
+ {
+ $this->setExpectedException(__NAMESPACE__.'\Exception\InvalidExtensionException', "The extension type '".__CLASS__."' does not exist, or does not implement ExtensionInterface.");
+ $this->_loader->load(__CLASS__);
+ }
+
+ public function testUnload()
+ {
+ $className = 'Eloquent\Typhoon\TestFixture\ExtensionFixtures\TestExtension';
+ $extension = $this->_loader->load($className);
+ $this->assertTrue($this->_loader->isLoaded($className));
+ $this->_loader->unload($className);
+ $this->assertFalse($this->_loader->isLoaded($className));
+ }
+}
View
34 test/suite/Eloquent/Typhoon/Generator/TyphaxASTGeneratorTest.php
@@ -17,6 +17,7 @@
use Eloquent\Typhax\Type\ArrayType;
use Eloquent\Typhax\Type\BooleanType;
use Eloquent\Typhax\Type\CallableType;
+use Eloquent\Typhax\Type\ExtensionType;
use Eloquent\Typhax\Type\FloatType;
use Eloquent\Typhax\Type\IntegerType;
use Eloquent\Typhax\Type\MixedType;
@@ -33,6 +34,8 @@
use Eloquent\Typhax\Type\Type;
use Eloquent\Typhax\Type\Visitor;
use Eloquent\Typhoon\TestCase\MultiGenerationTestCase;
+use Icecave\Pasta\AST\Expr\Call;
+use Icecave\Pasta\AST\Expr\Variable;
use Icecave\Pasta\AST\Func\Closure;
use Icecave\Pasta\AST\Func\Parameter;
use Icecave\Pasta\AST\Identifier;
@@ -47,7 +50,8 @@ protected function setUp()
{
parent::setUp();
- $this->_generator = new TyphaxASTGenerator;
+ $this->_loader = Phake::mock('Eloquent\Typhoon\Extension\ExtensionLoaderInterface');
+ $this->_generator = new TyphaxASTGenerator(null, $this->_loader);
$this->_renderer = new Renderer;
}
@@ -187,6 +191,34 @@ public function testVisitCallableTypeLogic()
$this->assertFalse($validator(stream_context_create()));
}
+ public function testVisitExtensionType()
+ {
+ $closure = Phake::mock('Icecave\Pasta\AST\Func\Closure');
+ $extension = Phake::mock('Eloquent\Typhoon\Extension\ExtensionInterface');
+ $className = ClassName::fromString(get_class($extension));
+
+ $type = new ExtensionType(
+ $className,
+ array(),
+ array()
+ );
+
+ Phake::when($this->_loader)
+ ->load($className->string())
+ ->thenReturn($extension);
+
+ Phake::when($extension)
+ ->generateTypeCheck($this->_generator, $type)
+ ->thenReturn($closure);
+
+ $expected = new Call($closure);
+ $expected->add(new Variable(new Identifier('value')));
+
+ $result = $this->_generator->visitExtensionType($type);
+
+ $this->assertEquals($expected, $result);
+ }
+
public function testVisitFloatTypeLogic()
{
$validator = $this->validatorFixture(new FloatType);
Something went wrong with that request. Please try again.