mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Refactored method tag and added test
This commit is contained in:
+112
-111
@@ -1,62 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* phpDocumentor
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* PHP Version 5.3
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @author Mike van Riel <mike[email protected]>
|
||||
* @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com)
|
||||
* @copyright 2010-2015 Mike van Riel<mike@phpdoc.org>
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\Void;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/**
|
||||
* Reflection class for a @method in a Docblock.
|
||||
*
|
||||
* @author Mike van Riel <[email protected]>
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||
* @link http://phpdoc.org
|
||||
* Reflection class for an {@}method in a Docblock.
|
||||
*/
|
||||
class Method extends Return_
|
||||
final class Method extends BaseTag
|
||||
{
|
||||
protected $name = 'method';
|
||||
|
||||
/** @var string */
|
||||
protected $method_name = '';
|
||||
private $methodName = '';
|
||||
|
||||
/** @var string */
|
||||
protected $arguments = '';
|
||||
/** @var string[] */
|
||||
private $arguments = [];
|
||||
|
||||
/** @var bool */
|
||||
protected $isStatic = false;
|
||||
private $isStatic = false;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
if (null === $this->description) {
|
||||
$this->description = '';
|
||||
if ($this->isStatic) {
|
||||
$this->description .= 'static ';
|
||||
}
|
||||
$this->description .= $this->type .
|
||||
" {$this->method_name}({$this->arguments}) " .
|
||||
$this->description;
|
||||
/** @var Type */
|
||||
private $returnType;
|
||||
|
||||
public function __construct(
|
||||
$methodName,
|
||||
array $arguments = [],
|
||||
Type $returnType = null,
|
||||
$static = false,
|
||||
Description $description = null
|
||||
) {
|
||||
Assert::stringNotEmpty($methodName);
|
||||
Assert::boolean($static);
|
||||
|
||||
if ($returnType === null) {
|
||||
$returnType = new Void();
|
||||
}
|
||||
|
||||
return $this->description;
|
||||
$this->methodName = $methodName;
|
||||
$this->arguments = $this->filterArguments($arguments);
|
||||
$this->returnType = $returnType;
|
||||
$this->isStatic = $static;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setContent($content)
|
||||
{
|
||||
Tag::setContent($content);
|
||||
public static function create(
|
||||
$body,
|
||||
TypeResolver $typeResolver = null,
|
||||
DescriptionFactory $descriptionFactory = null,
|
||||
Context $context = null
|
||||
) {
|
||||
Assert::stringNotEmpty($body);
|
||||
Assert::allNotNull([ $typeResolver, $descriptionFactory ]);
|
||||
|
||||
// 1. none or more whitespace
|
||||
// 2. optionally the keyword "static" followed by whitespace
|
||||
// 3. optionally a word with underscores followed by whitespace : as
|
||||
@@ -66,10 +81,10 @@ class Method extends Return_
|
||||
// 5. then a word with underscores, followed by ( and any character
|
||||
// until a ) and whitespace : as method name with signature
|
||||
// 6. any remaining text : as description
|
||||
if (preg_match(
|
||||
if (!preg_match(
|
||||
'/^
|
||||
# Static keyword
|
||||
# Declates a static method ONLY if type is also present
|
||||
# Declares a static method ONLY if type is also present
|
||||
(?:
|
||||
(static)
|
||||
\s+
|
||||
@@ -91,47 +106,36 @@ class Method extends Return_
|
||||
# Description
|
||||
(.*)
|
||||
$/sux',
|
||||
$this->description,
|
||||
$body,
|
||||
$matches
|
||||
)) {
|
||||
list(
|
||||
,
|
||||
$static,
|
||||
$this->type,
|
||||
$this->method_name,
|
||||
$this->arguments,
|
||||
$this->description
|
||||
) = $matches;
|
||||
if ($static) {
|
||||
if (!$this->type) {
|
||||
$this->type = 'static';
|
||||
} else {
|
||||
$this->isStatic = true;
|
||||
}
|
||||
} else {
|
||||
if (!$this->type) {
|
||||
$this->type = 'void';
|
||||
}
|
||||
}
|
||||
$this->parsedDescription = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
list(, $static, $returnType, $methodName, $arguments, $description) = $matches;
|
||||
|
||||
/**
|
||||
* Sets the name of this method.
|
||||
*
|
||||
* @param string $method_name The name of the method.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setMethodName($method_name)
|
||||
{
|
||||
$this->method_name = $method_name;
|
||||
$static = $static === 'static';
|
||||
$returnType = $typeResolver->resolve($returnType, $context);
|
||||
$description = $descriptionFactory->create($description, $context);
|
||||
|
||||
$this->description = null;
|
||||
return $this;
|
||||
$arguments = explode(',', $arguments);
|
||||
foreach($arguments as &$argument) {
|
||||
$argument = explode(' ', trim($argument));
|
||||
if ($argument[0][0] === '$') {
|
||||
$argumentName = substr($argument[0], 1);
|
||||
$argumentType = new Void();
|
||||
} else {
|
||||
$argumentType = $typeResolver->resolve($argument[0], $context);
|
||||
$argumentName = '';
|
||||
if (isset($argument[1])) {
|
||||
$argumentName = substr($argument[1], 1);
|
||||
}
|
||||
}
|
||||
|
||||
$argument = [ 'name' => $argumentName, 'type' => $argumentType];
|
||||
}
|
||||
|
||||
return new static($methodName, $arguments, $returnType, $static, $description);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,51 +145,21 @@ class Method extends Return_
|
||||
*/
|
||||
public function getMethodName()
|
||||
{
|
||||
return $this->method_name;
|
||||
return $this->methodName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the arguments for this method.
|
||||
*
|
||||
* @param string $arguments A comma-separated arguments line.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setArguments($arguments)
|
||||
{
|
||||
$this->arguments = $arguments;
|
||||
|
||||
$this->description = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing each argument as array of type and name.
|
||||
*
|
||||
* Please note that the argument sub-array may only contain 1 element if no
|
||||
* type was specified.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
if (empty($this->arguments)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$arguments = explode(',', $this->arguments);
|
||||
foreach ($arguments as $key => $value) {
|
||||
$arguments[$key] = explode(' ', trim($value));
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the method tag describes a static method or not.
|
||||
*
|
||||
* @return bool TRUE if the method declaration is for a static method, FALSE
|
||||
* otherwise.
|
||||
* @return bool TRUE if the method declaration is for a static method, FALSE otherwise.
|
||||
*/
|
||||
public function isStatic()
|
||||
{
|
||||
@@ -193,17 +167,44 @@ class Method extends Return_
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new value for whether the method is static or not.
|
||||
*
|
||||
* @param bool $isStatic The new value to set.
|
||||
*
|
||||
* @return $this
|
||||
* @return Type
|
||||
*/
|
||||
public function setIsStatic($isStatic)
|
||||
public function getReturnType()
|
||||
{
|
||||
$this->isStatic = $isStatic;
|
||||
return $this->returnType;
|
||||
}
|
||||
|
||||
$this->description = null;
|
||||
return $this;
|
||||
public function __toString()
|
||||
{
|
||||
$arguments = [];
|
||||
foreach ($this->arguments as $argument) {
|
||||
$arguments[] = $argument['type'] . ' $' . $argument['name'];
|
||||
}
|
||||
|
||||
return ($this->isStatic() ? 'static ' : '')
|
||||
. (string)$this->returnType . ' '
|
||||
. $this->methodName
|
||||
. '(' . implode(', ', $arguments) . ')'
|
||||
. ($this->description ? ' ' . $this->description->render() : '');
|
||||
}
|
||||
|
||||
private function filterArguments($arguments)
|
||||
{
|
||||
foreach ($arguments as &$argument) {
|
||||
if (is_string($argument)) {
|
||||
$argument = [ 'name' => $argument ];
|
||||
}
|
||||
if (! isset($argument['type'])) {
|
||||
$argument['type'] = new Void();
|
||||
}
|
||||
$keys = array_keys($argument);
|
||||
if ($keys !== [ 'name', 'type' ]) {
|
||||
throw new \InvalidArgumentException(
|
||||
'Arguments can only have the "name" and "type" fields, found: ' . var_export($keys, true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @copyright 2010-2015 Mike van Riel<[email protected]>
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags;
|
||||
|
||||
use Mockery as m;
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\Object_;
|
||||
use phpDocumentor\Reflection\Types\String_;
|
||||
use phpDocumentor\Reflection\Types\Void;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \phpDocumentor\Reflection\DocBlock\Tags\Method
|
||||
* @covers ::<private>
|
||||
*/
|
||||
class MethodTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getName
|
||||
*/
|
||||
public function testIfCorrectTagNameIsReturned()
|
||||
{
|
||||
$fixture = new Method('myMethod');
|
||||
|
||||
$this->assertSame('method', $fixture->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::__construct
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::isStatic
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::__toString
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Description
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render
|
||||
*/
|
||||
public function testIfTagCanBeRenderedUsingDefaultFormatter()
|
||||
{
|
||||
$arguments = [
|
||||
['name' => 'argument1', 'type' => new String_()],
|
||||
['name' => 'argument2', 'type' => new Object_()]
|
||||
];
|
||||
$fixture = new Method('myMethod', $arguments, new Void(), true, new Description('My Description'));
|
||||
|
||||
$this->assertSame(
|
||||
'static void myMethod(string $argument1, object $argument2) My Description',
|
||||
$fixture->render()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::__construct
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Description
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::render
|
||||
*/
|
||||
public function testIfTagCanBeRenderedUsingSpecificFormatter()
|
||||
{
|
||||
$fixture = new Method('myMethod');
|
||||
|
||||
$formatter = m::mock(Formatter::class);
|
||||
$formatter->shouldReceive('format')->with($fixture)->andReturn('Rendered output');
|
||||
|
||||
$this->assertSame('Rendered output', $fixture->render($formatter));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getMethodName
|
||||
*/
|
||||
public function testHasMethodName()
|
||||
{
|
||||
$expected = 'myMethod';
|
||||
|
||||
$fixture = new Method($expected);
|
||||
|
||||
$this->assertSame($expected, $fixture->getMethodName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getArguments
|
||||
*/
|
||||
public function testHasArguments()
|
||||
{
|
||||
$arguments = [
|
||||
[ 'name' => 'argument1', 'type' => new String_() ]
|
||||
];
|
||||
|
||||
$fixture = new Method('myMethod', $arguments);
|
||||
|
||||
$this->assertSame($arguments, $fixture->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getArguments
|
||||
*/
|
||||
public function testArgumentsMayBePassedAsString()
|
||||
{
|
||||
$arguments = ['argument1'];
|
||||
$expected = [
|
||||
[ 'name' => $arguments[0], 'type' => new Void() ]
|
||||
];
|
||||
|
||||
$fixture = new Method('myMethod', $arguments);
|
||||
|
||||
$this->assertEquals($expected, $fixture->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getArguments
|
||||
*/
|
||||
public function testArgumentTypeCanBeInferredAsVoid()
|
||||
{
|
||||
$arguments = [ [ 'name' => 'argument1' ] ];
|
||||
$expected = [
|
||||
[ 'name' => $arguments[0]['name'], 'type' => new Void() ]
|
||||
];
|
||||
|
||||
$fixture = new Method('myMethod', $arguments);
|
||||
|
||||
$this->assertEquals($expected, $fixture->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getReturnType
|
||||
*/
|
||||
public function testHasReturnType()
|
||||
{
|
||||
$expected = new String_();
|
||||
|
||||
$fixture = new Method('myMethod', [], $expected);
|
||||
|
||||
$this->assertSame($expected, $fixture->getReturnType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getReturnType
|
||||
*/
|
||||
public function testReturnTypeCanBeInferredAsVoid()
|
||||
{
|
||||
$fixture = new Method('myMethod', []);
|
||||
|
||||
$this->assertEquals(new Void(), $fixture->getReturnType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::isStatic
|
||||
*/
|
||||
public function testMethodCanBeStatic()
|
||||
{
|
||||
$expected = false;
|
||||
$fixture = new Method('myMethod', [], null, $expected);
|
||||
$this->assertSame($expected, $fixture->isStatic());
|
||||
|
||||
$expected = true;
|
||||
$fixture = new Method('myMethod', [], null, $expected);
|
||||
$this->assertSame($expected, $fixture->isStatic());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\BaseTag::getDescription
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Description
|
||||
*/
|
||||
public function testHasDescription()
|
||||
{
|
||||
$expected = new Description('Description');
|
||||
|
||||
$fixture = new Method('myMethod', [], null, false, $expected);
|
||||
|
||||
$this->assertSame($expected, $fixture->getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::__toString
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Description
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::isStatic
|
||||
*/
|
||||
public function testStringRepresentationIsReturned()
|
||||
{
|
||||
$arguments = [
|
||||
['name' => 'argument1', 'type' => new String_()],
|
||||
['name' => 'argument2', 'type' => new Object_()]
|
||||
];
|
||||
$fixture = new Method('myMethod', $arguments, new Void(), true, new Description('My Description'));
|
||||
|
||||
$this->assertSame(
|
||||
'static void myMethod(string $argument1, object $argument2) My Description',
|
||||
(string)$fixture
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Method::<public>
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory
|
||||
* @uses \phpDocumentor\Reflection\TypeResolver
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Description
|
||||
* @uses \phpDocumentor\Reflection\Fqsen
|
||||
* @uses \phpDocumentor\Reflection\Types\Context
|
||||
*/
|
||||
public function testFactoryMethod()
|
||||
{
|
||||
$descriptionFactory = m::mock(DescriptionFactory::class);
|
||||
$resolver = new TypeResolver();
|
||||
$context = new Context('');
|
||||
|
||||
$description = new Description('My Description');
|
||||
$expectedArguments = [
|
||||
[ 'name' => 'argument1', 'type' => new String_() ],
|
||||
[ 'name' => 'argument2', 'type' => new Void() ]
|
||||
];
|
||||
|
||||
$descriptionFactory->shouldReceive('create')->with('My Description', $context)->andReturn($description);
|
||||
|
||||
$fixture = Method::create(
|
||||
'static void myMethod(string $argument1, $argument2) My Description',
|
||||
$resolver,
|
||||
$descriptionFactory,
|
||||
$context
|
||||
);
|
||||
|
||||
$this->assertSame('static void myMethod(string $argument1, void $argument2) My Description', (string)$fixture);
|
||||
$this->assertSame('myMethod', $fixture->getMethodName());
|
||||
$this->assertEquals($expectedArguments, $fixture->getArguments());
|
||||
$this->assertInstanceOf(Void::class, $fixture->getReturnType());
|
||||
$this->assertSame($description, $fixture->getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testFactoryMethodFailsIfBodyIsNotString()
|
||||
{
|
||||
Method::create([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testFactoryMethodFailsIfBodyIsEmpty()
|
||||
{
|
||||
Method::create('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testFactoryMethodReturnsNullIfBodyIsIncorrect()
|
||||
{
|
||||
$this->assertNull(Method::create('body('));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testFactoryMethodFailsIfResolverIsNull()
|
||||
{
|
||||
Method::create('body');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testFactoryMethodFailsIfDescriptionFactoryIsNull()
|
||||
{
|
||||
Method::create('body', new TypeResolver());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testCreationFailsIfBodyIsNotString()
|
||||
{
|
||||
new Method([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testCreationFailsIfBodyIsEmpty()
|
||||
{
|
||||
new Method('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testCreationFailsIfStaticIsNotBoolean()
|
||||
{
|
||||
new Method('body', [], null, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testCreationFailsIfArgumentRecordContainsInvalidEntry()
|
||||
{
|
||||
new Method('body', [ [ 'name' => 'myName', 'unknown' => 'nah' ] ]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user