diff --git a/.gitignore b/.gitignore index 743b4a2..6d5982f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ vendor bin composer.phar -composer.lock \ No newline at end of file +composer.lock +.idea/* diff --git a/spec/Argument/StringBuilderSpec.php b/spec/Argument/StringBuilderSpec.php index 8826e14..906bdbd 100644 --- a/spec/Argument/StringBuilderSpec.php +++ b/spec/Argument/StringBuilderSpec.php @@ -22,7 +22,7 @@ function it_should_use_typehint__for_object_and_name_it_after_its_type(ClassIden { $classIdentifier->getTypeName(Argument::any())->willReturn('ArrayObject'); - $this->buildFrom(array(new \ArrayObject()))->shouldReturn('\ArrayObject $arrayObject'); + $this->buildFrom(array(new \ArrayObject()))->shouldReturn('ArrayObject $arrayObject'); } function it_should_suffix_names_when_necessary_to_avoid_name_collision(ClassIdentifier $classIdentifier) @@ -31,7 +31,7 @@ function it_should_suffix_names_when_necessary_to_avoid_name_collision(ClassIden $this ->buildFrom(array(new \ArrayObject(), new \ArrayObject(), 1, 2)) - ->shouldReturn('\ArrayObject $arrayObject1, \ArrayObject $arrayObject2, $argument1, $argument2') + ->shouldReturn('ArrayObject $arrayObject1, ArrayObject $arrayObject2, $argument1, $argument2') ; } } diff --git a/spec/Decorator/CodeSpec.php b/spec/Decorator/CodeSpec.php new file mode 100644 index 0000000..6c03be5 --- /dev/null +++ b/spec/Decorator/CodeSpec.php @@ -0,0 +1,78 @@ +shouldHaveType('Cjm\PhpSpec\Decorator\Code'); + } + + function it_should_add_use_namespace_for_typehinted_argument_from_spl() + { + $codeIn =<<addUseStatementForArgument('ArrayObject', $codeIn)->shouldReturn($codeOut); + } + + function it_should_replace_use_statement_for_the_same_typehint() + { + + $codeIn =<<addUseStatementForArgument('\SplFixedArray', $codeIn)->shouldReturn($codeOut); + } + + function it_should_add_only_one_use_statement() + { + $codeIn =<<addUseStatementForArgument('Foo\Bar\Baz', $codeIn)->shouldReturn($codeOut); + } +} diff --git a/src/Argument/StringBuilder.php b/src/Argument/StringBuilder.php index d6afd00..db27549 100644 --- a/src/Argument/StringBuilder.php +++ b/src/Argument/StringBuilder.php @@ -24,9 +24,10 @@ public function __construct(ClassIdentifier $classIdentifier) public function buildFrom($arguments) { $argumentStrings = array(); - foreach ($arguments as $key => $argument){ + foreach ($arguments as $key => $argument) { $argumentStrings[] = $this->getTypeHint($argument).$this->getArgName($argument); } + $allCount = array_count_values($argumentStrings); $duplicatesCount = array_filter($allCount, function ($count) { return 1 < $count; @@ -49,10 +50,14 @@ private function getTypeHint($argument) { $typeHint = ''; if (is_object($argument)) { - $typeHint .= '\\'.$this->classIdentifier->getTypeName($argument).' '; + $typeHint = $this->classIdentifier->getTypeName($argument).' '; } - return $typeHint; + if (is_array($parts = explode('\\', $typeHint))) { + return end($parts); + } else { + return $typeHint; + } } /** @@ -70,4 +75,19 @@ private function getArgName($argument) return '$'.lcfirst($className); } + + /** + * @param $arguments + * @return mixed + */ + public function getNamespace($arguments) + { + $namespace = []; + foreach ($arguments as $argument) { + if (is_object($argument)) { + $namespace[] = addslashes($this->classIdentifier->getTypeName($argument)); + } + } + return end($namespace); + } } diff --git a/src/Decorator/Code.php b/src/Decorator/Code.php new file mode 100644 index 0000000..35da190 --- /dev/null +++ b/src/Decorator/Code.php @@ -0,0 +1,42 @@ +removeNamespace($argumentNamespace, $codeIn); + $codeOut = $this->addNamespace($argumentNamespace, $codeOut); + + return $codeOut; + } + + /** + * @param $argumentNamespace + * @param $codeIn + * + * @return mixed + */ + private function removeNamespace($argumentNamespace, $codeIn) + { + return preg_replace('/\nuse\s+' . addslashes($argumentNamespace) . ';/', '', $codeIn); + } + + /** + * @param $argumentNamespace + * @param $codeOut + * + * @return mixed + */ + private function addNamespace($argumentNamespace, $codeOut) + { + return preg_replace('/namespace\s+(.+);/', '$0' . "\n" . 'use ' . addslashes($argumentNamespace) . ';', $codeOut); + } +} diff --git a/src/Extension/TypeHintedMethodsExtension.php b/src/Extension/TypeHintedMethodsExtension.php index 2fcb43f..57ff189 100644 --- a/src/Extension/TypeHintedMethodsExtension.php +++ b/src/Extension/TypeHintedMethodsExtension.php @@ -4,6 +4,7 @@ use Cjm\PhpSpec\Argument\ClassIdentifier; use Cjm\PhpSpec\Argument\StringBuilder; +use Cjm\PhpSpec\Decorator\Code as CodeDecorator; use Cjm\PhpSpec\Generator\TypeHintedMethodGenerator; use PhpSpec\Extension\ExtensionInterface; use PhpSpec\ServiceContainer; @@ -23,12 +24,17 @@ public function load(ServiceContainer $container) return new StringBuilder($c->get('code_generator.generators.method.classidentifier')); }); + $container->set('code_generator.decorators.code', function ($c) { + return new CodeDecorator(); + }); + $container->set('code_generator.generators.method', function ($c) { return new TypeHintedMethodGenerator( $c->get('console.io'), $c->get('code_generator.templates'), null, - $c->get('code_generator.generators.method.argumentbuilder') + $c->get('code_generator.generators.method.argumentbuilder'), + $c->get('code_generator.decorators.code') ); }); } diff --git a/src/Generator/TypeHintedMethodGenerator.php b/src/Generator/TypeHintedMethodGenerator.php index 6308c22..4ccbe93 100644 --- a/src/Generator/TypeHintedMethodGenerator.php +++ b/src/Generator/TypeHintedMethodGenerator.php @@ -3,6 +3,8 @@ namespace Cjm\PhpSpec\Generator; use Cjm\PhpSpec\Argument\StringBuilder; +use Cjm\PhpSpec\Decorator\Code; +use Cjm\PhpSpec\Decorator\Code as CodeDecorator; use PhpSpec\CodeGenerator\Generator\GeneratorInterface; use PhpSpec\CodeGenerator\TemplateRenderer; use PhpSpec\Console\IO; @@ -11,6 +13,8 @@ class TypeHintedMethodGenerator implements GeneratorInterface { + /** @var CodeDecorator */ + public $codeDecorator; /** * @var \PhpSpec\Console\IO */ @@ -36,13 +40,15 @@ class TypeHintedMethodGenerator implements GeneratorInterface * @param TemplateRenderer $templates * @param Filesystem $filesystem * @param StringBuilder $argumentBuilder + * @param CodeDecorator $codeDecorator */ - public function __construct(IO $io, TemplateRenderer $templates, Filesystem $filesystem = null, StringBuilder $argumentBuilder) + public function __construct(IO $io, TemplateRenderer $templates, Filesystem $filesystem = null, StringBuilder $argumentBuilder, Code $codeDecorator) { $this->argumentBuilder = $argumentBuilder; $this->io = $io; $this->templates = $templates; $this->filesystem = $filesystem ?: new Filesystem; + $this->codeDecorator = $codeDecorator; } /** @@ -70,6 +76,7 @@ public function generate(ResourceInterface $resource, array $data = array()) $arguments = $data['arguments']; $argString = $this->argumentBuilder->buildFrom($arguments); + $argumentNamespace = $this->argumentBuilder->getNamespace($arguments); $values = array('%name%' => $name, '%arguments%' => $argString); if (!$content = $this->templates->render('method', $values)) { @@ -79,6 +86,9 @@ public function generate(ResourceInterface $resource, array $data = array()) } $code = $this->filesystem->getFileContents($filepath); + if ($argumentNamespace) { + $code = $this->codeDecorator->addUseStatementForArgument($argumentNamespace, $code); + } $code = preg_replace('/}[ \n]*$/', rtrim($content) ."\n}\n", trim($code)); $this->filesystem->putFileContents($filepath, $code);