From d4cf0d2e44094b59341ed4f88bc896c3e3b731d7 Mon Sep 17 00:00:00 2001 From: Alexis von Glasow Date: Sun, 31 Jan 2016 15:31:12 +0100 Subject: [PATCH 1/5] Allow to define if the type is an alias or not. When a use statements is declared we should be able to use alias as type for parameters. This patch keep the current behavior and add a way to define if the parameter type is an alias or not. --- src/Generator/ParameterGenerator.php | 12 +++-- src/Generator/TypeGenerator.php | 38 ++++++++++++- test/Generator/TypeGeneratorTest.php | 81 ++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 4 deletions(-) diff --git a/src/Generator/ParameterGenerator.php b/src/Generator/ParameterGenerator.php index a5b59ed0..6a3cf647 100644 --- a/src/Generator/ParameterGenerator.php +++ b/src/Generator/ParameterGenerator.php @@ -163,14 +163,20 @@ public function __construct( } /** - * @param string $type + * @param mixed $type * @return ParameterGenerator */ public function setType($type) { - $this->type = TypeGenerator::fromTypeString($type); + if (is_array($type)) { + $this->type = TypeGenerator::fromTypeArray($type); + return $this; + } - return $this; + if (is_string($type)) { + $this->type = TypeGenerator::fromTypeString($type); + return $this; + } } /** diff --git a/src/Generator/TypeGenerator.php b/src/Generator/TypeGenerator.php index 38490e1a..e601eeb6 100644 --- a/src/Generator/TypeGenerator.php +++ b/src/Generator/TypeGenerator.php @@ -23,6 +23,11 @@ final class TypeGenerator implements GeneratorInterface */ private $type; + /** + * @var string; + */ + private $alias = false; + /** * @var string[] * @@ -73,6 +78,32 @@ public static function fromTypeString($type) return $instance; } + /** + * @param array $typeArray + * + * @return TypeGenerator + * + * @throws InvalidArgumentException + */ + public static function fromTypeArray(array $typeArray) + { + if (!isset($typeArray['name'])) { + throw new InvalidArgumentException(sprintf( + 'Provided type "%s" is invalid: must conform "%s"', + var_export($typeArray, true), + self::$validIdentifierMatcher + )); + } + + $instance = self::fromTypeString($typeArray['name']); + + if (isset($typeArray['alias']) && is_bool($typeArray['alias'])) { + $instance->alias = (boolean) $typeArray['alias']; + } + + return $instance; + } + private function __construct() { } @@ -86,7 +117,7 @@ public function generate() return strtolower($this->type); } - return '\\' . $this->type; + return ($this->isAlias()) ? $this->type : '\\' . $this->type; } /** @@ -121,4 +152,9 @@ private static function isInternalPhpType($type) { return in_array(strtolower($type), self::$internalPhpTypes, true); } + + private function isAlias() + { + return $this->alias; + } } diff --git a/test/Generator/TypeGeneratorTest.php b/test/Generator/TypeGeneratorTest.php index 80054c2a..79ae9f4d 100644 --- a/test/Generator/TypeGeneratorTest.php +++ b/test/Generator/TypeGeneratorTest.php @@ -79,6 +79,87 @@ public function testRejectsInvalidTypeString(string $typeString) TypeGenerator::fromTypeString($typeString); } + /** + * @dataProvider validTypeArrayProvider + * + * @param string $typeArray + * @param string $expectedReturnType + */ + public function testFromValidStringAlias(array $typeArray, string $expectedReturnType) + { + $generator = TypeGenerator::fromTypeArray($typeArray); + + self::assertSame($expectedReturnType, $generator->generate()); + } + + public function validTypeArrayProvider() + { + return [ + [['name' => 'foo', 'alias' => true], 'foo'], + [['name' => 'foo', 'alias' => false], '\\foo'], + [['name' => '\\foo', 'alias' => false], '\\foo'], + [['name' => '\\foo', 'alias' => true], 'foo'], + [['name' => 'a\\b\\c', 'alias' => false], '\\a\\b\\c'], + [['name' => 'a\\b\\c', 'alias' => true], 'a\\b\\c'], + [['name' => 'array', 'alias' => false], 'array'], + [['name' => 'array', 'alias' => true], 'array'], + [['name' => 'Array', 'alias' => false], 'array'], + [['name' => 'Array', 'alias' => true], 'array'], + [['name' => 'ARRAY', 'alias' => false], 'array'], + [['name' => 'ARRAY', 'alias' => true], 'array'], + [['name' => 'callable', 'alias' => false], 'callable'], + [['name' => 'callable', 'alias' => true], 'callable'], + [['name' => 'Callable', 'alias' => false], 'callable'], + [['name' => 'Callable', 'alias' => true], 'callable'], + [['name' => 'CALLABLE', 'alias' => false], 'callable'], + [['name' => 'CALLABLE', 'alias' => true], 'callable'], + [['name' => 'string', 'alias' => false], 'string'], + [['name' => 'string', 'alias' => true], 'string'], + [['name' => 'String', 'alias' => false], 'string'], + [['name' => 'String', 'alias' => true], 'string'], + [['name' => 'STRING', 'alias' => false], 'string'], + [['name' => 'STRING', 'alias' => true], 'string'], + [['name' => 'int', 'alias' => false], 'int'], + [['name' => 'int', 'alias' => true], 'int'], + [['name' => 'Int', 'alias' => false], 'int'], + [['name' => 'Int', 'alias' => true], 'int'], + [['name' => 'INT', 'alias' => false], 'int'], + [['name' => 'INT', 'alias' => true], 'int'], + [['name' => 'float', 'alias' => false], 'float'], + [['name' => 'float', 'alias' => true], 'float'], + [['name' => 'Float', 'alias' => false], 'float'], + [['name' => 'Float', 'alias' => true], 'float'], + [['name' => 'FLOAT', 'alias' => false], 'float'], + [['name' => 'FLOAT', 'alias' => true], 'float'], + [['name' => 'bool', 'alias' => false], 'bool'], + [['name' => 'bool', 'alias' => true], 'bool'], + [['name' => 'Bool', 'alias' => false], 'bool'], + [['name' => 'Bool', 'alias' => true], 'bool'], + [['name' => 'BOOL', 'alias' => false], 'bool'], + [['name' => 'BOOL', 'alias' => true], 'bool'], + [['name' => 'object', 'alias' => false], '\\object'], + [['name' => 'object', 'alias' => true], 'object'], + [['name' => 'Object', 'alias' => false], '\\Object'], + [['name' => 'Object', 'alias' => true], 'Object'], + [['name' => 'OBJECT', 'alias' => false], '\\OBJECT'], + [['name' => 'OBJECT', 'alias' => true], 'OBJECT'], + [['name' => 'mixed', 'alias' => false], '\\mixed'], + [['name' => 'mixed', 'alias' => true], 'mixed'], + [['name' => 'Mixed', 'alias' => false], '\\Mixed'], + [['name' => 'Mixed', 'alias' => true], 'Mixed'], + [['name' => 'MIXED', 'alias' => false], '\\MIXED'], + [['name' => 'MIXED', 'alias' => true], 'MIXED'], + [['name' => 'resource', 'alias' => false], '\\resource'], + [['name' => 'resource', 'alias' => true], 'resource'], + [['name' => 'Resource', 'alias' => false], '\\Resource'], + [['name' => 'Resource', 'alias' => true], 'Resource'], + [['name' => 'RESOURCE', 'alias' => false], '\\RESOURCE'], + [['name' => 'RESOURCE', 'alias' => true], 'RESOURCE'], + [['name' => 'foo_bar', 'alias' => false], '\\foo_bar'], + [['name' => 'foo_bar', 'alias' => true], 'foo_bar'], + ]; + } + /** * @return string[][] */ From c0f092e88fe0fb708e17a4cde3b2f3e620a99df2 Mon Sep 17 00:00:00 2001 From: Alexis von Glasow Date: Tue, 2 Feb 2016 13:46:17 +0100 Subject: [PATCH 2/5] Remove unneeded method and rename property --- src/Generator/TypeGenerator.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Generator/TypeGenerator.php b/src/Generator/TypeGenerator.php index e601eeb6..0c9437e3 100644 --- a/src/Generator/TypeGenerator.php +++ b/src/Generator/TypeGenerator.php @@ -26,7 +26,7 @@ final class TypeGenerator implements GeneratorInterface /** * @var string; */ - private $alias = false; + private $aliased = false; /** * @var string[] @@ -98,7 +98,7 @@ public static function fromTypeArray(array $typeArray) $instance = self::fromTypeString($typeArray['name']); if (isset($typeArray['alias']) && is_bool($typeArray['alias'])) { - $instance->alias = (boolean) $typeArray['alias']; + $instance->aliased = (boolean) $typeArray['alias']; } return $instance; @@ -117,7 +117,7 @@ public function generate() return strtolower($this->type); } - return ($this->isAlias()) ? $this->type : '\\' . $this->type; + return ($this->aliased) ? $this->type : '\\' . $this->type; } /** @@ -152,9 +152,4 @@ private static function isInternalPhpType($type) { return in_array(strtolower($type), self::$internalPhpTypes, true); } - - private function isAlias() - { - return $this->alias; - } } From ae26be21658d9646428fcfbdbdb52656604eb775 Mon Sep 17 00:00:00 2001 From: Alexis von Glasow Date: Mon, 15 Feb 2016 13:57:53 +0100 Subject: [PATCH 3/5] Remove method unneeded and refactor code. Remove create type from array and add arguments to allow to use the type as alias. Fix Typo. --- src/Generator/ParameterGenerator.php | 15 ++++++++++++-- src/Generator/TypeGenerator.php | 29 ++-------------------------- test/Generator/TypeGeneratorTest.php | 2 +- 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/src/Generator/ParameterGenerator.php b/src/Generator/ParameterGenerator.php index 6a3cf647..a7439f89 100644 --- a/src/Generator/ParameterGenerator.php +++ b/src/Generator/ParameterGenerator.php @@ -96,7 +96,7 @@ public static function fromArray(array $array) { if (!isset($array['name'])) { throw new Exception\InvalidArgumentException( - 'Paramerer generator requires that a name is provided for this object' + 'Parameter generator requires that a name is provided for this object' ); } @@ -164,12 +164,19 @@ public function __construct( /** * @param mixed $type + * @throws Exception\InvalidArgumentException * @return ParameterGenerator */ public function setType($type) { + if (is_array($type) && !isset($type['name'])) { + throw new Exception\InvalidArgumentException( + 'Type generator requires that a name is provided for this object' + ); + } + if (is_array($type)) { - $this->type = TypeGenerator::fromTypeArray($type); + $this->type = TypeGenerator::fromTypeString($type['name'], true); return $this; } @@ -177,6 +184,10 @@ public function setType($type) $this->type = TypeGenerator::fromTypeString($type); return $this; } + + throw new Exception\InvalidArgumentException( + 'Unknown parameter type passed in' + ); } /** diff --git a/src/Generator/TypeGenerator.php b/src/Generator/TypeGenerator.php index 0c9437e3..b1ac02f7 100644 --- a/src/Generator/TypeGenerator.php +++ b/src/Generator/TypeGenerator.php @@ -49,7 +49,7 @@ final class TypeGenerator implements GeneratorInterface * * @throws InvalidArgumentException */ - public static function fromTypeString($type) + public static function fromTypeString($type, $aliased = false) { list($wasTrimmed, $trimmedType) = self::trimType($type); @@ -74,32 +74,7 @@ public static function fromTypeString($type) $instance->type = $trimmedType; $instance->isInternalPhpType = self::isInternalPhpType($trimmedType); - - return $instance; - } - - /** - * @param array $typeArray - * - * @return TypeGenerator - * - * @throws InvalidArgumentException - */ - public static function fromTypeArray(array $typeArray) - { - if (!isset($typeArray['name'])) { - throw new InvalidArgumentException(sprintf( - 'Provided type "%s" is invalid: must conform "%s"', - var_export($typeArray, true), - self::$validIdentifierMatcher - )); - } - - $instance = self::fromTypeString($typeArray['name']); - - if (isset($typeArray['alias']) && is_bool($typeArray['alias'])) { - $instance->aliased = (boolean) $typeArray['alias']; - } + $instance->aliased = (boolean) $aliased; return $instance; } diff --git a/test/Generator/TypeGeneratorTest.php b/test/Generator/TypeGeneratorTest.php index 79ae9f4d..a1e7d5fb 100644 --- a/test/Generator/TypeGeneratorTest.php +++ b/test/Generator/TypeGeneratorTest.php @@ -87,7 +87,7 @@ public function testRejectsInvalidTypeString(string $typeString) */ public function testFromValidStringAlias(array $typeArray, string $expectedReturnType) { - $generator = TypeGenerator::fromTypeArray($typeArray); + $generator = TypeGenerator::fromTypeString($typeArray['name'], $typeArray['alias']); self::assertSame($expectedReturnType, $generator->generate()); } From 24c2b49cd51751f04dc2b6fc65a8b40e29fbe835 Mon Sep 17 00:00:00 2001 From: Alexis von Glasow Date: Tue, 22 Mar 2016 13:38:46 +0100 Subject: [PATCH 4/5] Use TypeGenerator instead of array to set Type. --- src/Generator/ParameterGenerator.php | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/Generator/ParameterGenerator.php b/src/Generator/ParameterGenerator.php index a7439f89..849acb0e 100644 --- a/src/Generator/ParameterGenerator.php +++ b/src/Generator/ParameterGenerator.php @@ -163,25 +163,19 @@ public function __construct( } /** - * @param mixed $type + * @param string|TypeGenerator $type * @throws Exception\InvalidArgumentException * @return ParameterGenerator */ public function setType($type) { - if (is_array($type) && !isset($type['name'])) { - throw new Exception\InvalidArgumentException( - 'Type generator requires that a name is provided for this object' - ); - } - - if (is_array($type)) { - $this->type = TypeGenerator::fromTypeString($type['name'], true); + if (is_string($type)) { + $this->type = TypeGenerator::fromTypeString($type); return $this; } - if (is_string($type)) { - $this->type = TypeGenerator::fromTypeString($type); + if ($type instanceof TypeGenerator) { + $this->type = $type; return $this; } From 538ea0ed242be512130a9e9bb777ccf7f76dd870 Mon Sep 17 00:00:00 2001 From: Alexis von Glasow Date: Thu, 28 Apr 2016 14:05:40 +0200 Subject: [PATCH 5/5] Add tests for setType in ParameterGenerator --- test/Generator/ParameterGeneratorTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/Generator/ParameterGeneratorTest.php b/test/Generator/ParameterGeneratorTest.php index 5c1ad4b3..145baf0f 100644 --- a/test/Generator/ParameterGeneratorTest.php +++ b/test/Generator/ParameterGeneratorTest.php @@ -9,8 +9,10 @@ namespace ZendTest\Code\Generator; +use Zend\Code\Exception\InvalidArgumentException; use Zend\Code\Generator\ParameterGenerator; use Zend\Code\Generator\ValueGenerator; +use Zend\Code\Generator\TypeGenerator; use Zend\Code\Reflection\ParameterReflection; use ZendTest\Code\TestAsset\ClassTypeHintedClass; use ZendTest\Code\TestAsset\DocBlockOnlyHintsClass; @@ -30,6 +32,21 @@ public function testTypeGetterAndSetterPersistValue() $this->assertEquals('Foo', $parameterGenerator->getType()); } + public function testTypeSetterWithTypeGenerator() + { + $parameterGenerator = new ParameterGenerator(); + $parameterGenerator->setType(TypeGenerator::fromTypeString('Foo')); + $this->assertEquals('Foo', $parameterGenerator->getType()); + } + + public function testTypeSetterRejectInvalidType() + { + $this->setExpectedException(InvalidArgumentException::class); + + $parameterGenerator = new ParameterGenerator(); + $parameterGenerator->setType(new \stdclass); + } + public function testNameGetterAndSetterPersistValue() { $parameterGenerator = new ParameterGenerator();