mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-18 01:57:13 +00:00
Write test for the Description object and stabilize the API
This commit is contained in:
committed by
Mike van Riel
parent
53d5adb324
commit
c24f8ead92
@@ -14,29 +14,65 @@ namespace phpDocumentor\Reflection\DocBlock;
|
|||||||
|
|
||||||
use phpDocumentor\Reflection\DocBlock\Description\Formatter;
|
use phpDocumentor\Reflection\DocBlock\Description\Formatter;
|
||||||
use phpDocumentor\Reflection\DocBlock\Description\PassthroughFormatter;
|
use phpDocumentor\Reflection\DocBlock\Description\PassthroughFormatter;
|
||||||
|
use Webmozart\Assert\Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object representing to description for a DocBlock.
|
||||||
|
*
|
||||||
|
* A Description object can consist of plain text but can also include tags. A Description Formatter can then combine
|
||||||
|
* a body template with sprintf-style placeholders together with formatted tags in order to reconstitute a complete
|
||||||
|
* description text using the format that you would prefer.
|
||||||
|
*
|
||||||
|
* Because parsing a Description text can be a verbose process this is handled by the {@see DescriptionFactory}. It is
|
||||||
|
* thus recommended to use that to create a Description object, like this:
|
||||||
|
*
|
||||||
|
* $description = $descriptionFactory->create('This is a {@see Description}', $context);
|
||||||
|
*
|
||||||
|
* The description factory will interpret the given body and create a body template and list of tags from them, and pass
|
||||||
|
* that onto the constructor if this class.
|
||||||
|
*
|
||||||
|
* > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace
|
||||||
|
* > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial
|
||||||
|
* > type names and FQSENs.
|
||||||
|
*
|
||||||
|
* If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this:
|
||||||
|
*
|
||||||
|
* $description = new Description(
|
||||||
|
* 'This is a %1$s',
|
||||||
|
* [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ]
|
||||||
|
* );
|
||||||
|
*
|
||||||
|
* It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object
|
||||||
|
* is mainly responsible for rendering.
|
||||||
|
*
|
||||||
|
* @see DescriptionFactory to create a new Description.
|
||||||
|
* @see Description\Formatter for the formatting of the body and tags.
|
||||||
|
*/
|
||||||
class Description
|
class Description
|
||||||
{
|
{
|
||||||
/** @var string */
|
/** @var string */
|
||||||
private $body;
|
private $bodyTemplate;
|
||||||
|
|
||||||
/** @var Tag[] */
|
/** @var Tag[] */
|
||||||
private $tags;
|
private $tags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes a this object with a series of tokens of which a description consists.
|
* Initializes a Description with its body (template) and a listing of the tags used in the body template.
|
||||||
*
|
*
|
||||||
* @param string $body
|
* @param string $bodyTemplate
|
||||||
* @param Tag[] $tags
|
* @param Tag[] $tags
|
||||||
*/
|
*/
|
||||||
public function __construct($body, array $tags = [])
|
public function __construct($bodyTemplate, array $tags = [])
|
||||||
{
|
{
|
||||||
$this->body = $body;
|
Assert::string($bodyTemplate);
|
||||||
|
|
||||||
|
$this->bodyTemplate = $bodyTemplate;
|
||||||
$this->tags = $tags;
|
$this->tags = $tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders this description as a string where the provided formatter will format tags for the expected output.
|
* Renders this description as a string where the provided formatter will format the tags in the expected string
|
||||||
|
* format.
|
||||||
*
|
*
|
||||||
* @param Formatter|null $formatter
|
* @param Formatter|null $formatter
|
||||||
*
|
*
|
||||||
@@ -48,6 +84,16 @@ class Description
|
|||||||
$formatter = new PassthroughFormatter();
|
$formatter = new PassthroughFormatter();
|
||||||
}
|
}
|
||||||
|
|
||||||
return vsprintf($this->body, $formatter->format($this->tags));
|
return vsprintf($this->bodyTemplate, $formatter->format($this->tags));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a plain string representation of this description.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
namespace phpDocumentor\Reflection\DocBlock;
|
namespace phpDocumentor\Reflection\DocBlock;
|
||||||
|
|
||||||
use Mockery as m;
|
use Mockery as m;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
|
use phpDocumentor\Reflection\DocBlock\Description\PassthroughFormatter;
|
||||||
use phpDocumentor\Reflection\DocBlock\Tags\Link;
|
use phpDocumentor\Reflection\DocBlock\Tags\Other;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @coversDefaultClass \phpDocumentor\Reflection\DocBlock\Description
|
* @coversDefaultClass \phpDocumentor\Reflection\DocBlock\Description
|
||||||
@@ -22,88 +22,54 @@ use phpDocumentor\Reflection\DocBlock\Tags\Link;
|
|||||||
class DescriptionTest extends \PHPUnit_Framework_TestCase
|
class DescriptionTest extends \PHPUnit_Framework_TestCase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param array $examples
|
|
||||||
* @dataProvider provideExampleDescriptions
|
|
||||||
* @covers ::__construct
|
* @covers ::__construct
|
||||||
* @covers ::render
|
* @covers ::render
|
||||||
* @covers ::parse
|
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Other
|
||||||
* @uses phpDocumentor\Reflection\DocBlock\Description\PassthroughFormatter
|
* @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
|
||||||
* @uses phpDocumentor\Reflection\DocBlock\Tag
|
* @uses \phpDocumentor\Reflection\DocBlock\Description\PassthroughFormatter
|
||||||
* @uses phpDocumentor\Reflection\DocBlock\Tags\Link
|
|
||||||
*/
|
*/
|
||||||
public function testParsesDescription($example)
|
public function testDescriptionCanRenderUsingABodyWithPlaceholdersAndTags()
|
||||||
{
|
{
|
||||||
$object = new Description($example);
|
$body = 'This is a %1$s body.';
|
||||||
|
$expected = 'This is a {@internal significant } body.';
|
||||||
|
$tags = [new Other('internal', new Description('significant '))];
|
||||||
|
|
||||||
$this->assertSame($example, $object->render());
|
$fixture = new Description($body, $tags);
|
||||||
|
|
||||||
|
// without formatter (thus the PassthroughFormatter by default)
|
||||||
|
$this->assertSame($expected, $fixture->render());
|
||||||
|
|
||||||
|
// with a custom formatter
|
||||||
|
$formatter = m::mock(PassthroughFormatter::class);
|
||||||
|
$formatter->shouldReceive('format')->with($tags)->andReturn(['{@internal significant }']);
|
||||||
|
$this->assertSame($expected, $fixture->render($formatter));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::__construct
|
* @covers ::__construct
|
||||||
* @covers ::render
|
* @covers ::render
|
||||||
* @covers ::parse
|
* @covers ::__toString
|
||||||
* @uses phpDocumentor\Reflection\DocBlock\Description\PassthroughFormatter
|
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Other
|
||||||
|
* @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
|
||||||
|
* @uses \phpDocumentor\Reflection\DocBlock\Description\PassthroughFormatter
|
||||||
*/
|
*/
|
||||||
public function testInlineTagEscapingSequence()
|
public function testDescriptionCanBeCastToString()
|
||||||
{
|
{
|
||||||
$fixture = 'This is text for a description with literal {{@}link}.';
|
$body = 'This is a %1$s body.';
|
||||||
$expected = 'This is text for a description with literal {@link}.';
|
$expected = 'This is a {@internal significant } body.';
|
||||||
$object = new Description($fixture);
|
$tags = [new Other('internal', new Description('significant '))];
|
||||||
$this->assertSame($expected, $object->render());
|
|
||||||
|
$fixture = new Description($body, $tags);
|
||||||
|
|
||||||
|
$this->assertSame($expected, (string)$fixture);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @covers ::__construct
|
* @covers ::__construct
|
||||||
* @covers ::render
|
* @expectedException \InvalidArgumentException
|
||||||
* @covers ::parse
|
|
||||||
* @uses phpDocumentor\Reflection\DocBlock\Tag
|
|
||||||
* @uses phpDocumentor\Reflection\DocBlock\Tags\Version
|
|
||||||
* @uses phpDocumentor\Reflection\DocBlock\Tags\Link
|
|
||||||
*/
|
*/
|
||||||
public function testFormatterReceivesContentsAsTokens()
|
public function testBodyTemplateMustBeAString()
|
||||||
{
|
{
|
||||||
$fixture = <<<DESCRIPTION
|
new Description([]);
|
||||||
This is a description with {a} {@link http://phpdoc.org/ link} or {@deprecated inline tag with {@link http://phpdoc.org
|
|
||||||
another link} in it}. Here is a solitary } and a { to test the regex. We can also escape at-signs like this
|
|
||||||
{@}example.com or {{@}link}.
|
|
||||||
DESCRIPTION;
|
|
||||||
|
|
||||||
$expected = [
|
|
||||||
'This is a description with {a} ',
|
|
||||||
Link::create('@link http://phpdoc.org/ link'),
|
|
||||||
' or ',
|
|
||||||
Deprecated::create("@deprecated inline tag with {@link http://phpdoc.org\nanother link} in it"),
|
|
||||||
". Here is a solitary } and a { to test the regex. We can also escape at-signs like this\n"
|
|
||||||
. "@example.com or {@link}."
|
|
||||||
];
|
|
||||||
|
|
||||||
$formatter = m::mock('phpDocumentor\Reflection\DocBlock\Description\Formatter');
|
|
||||||
$formatter->shouldReceive('format')->with($expected)->andReturn($fixture);
|
|
||||||
|
|
||||||
$object = new Description($fixture);
|
|
||||||
$this->assertSame($fixture, $object->render($formatter));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a series of example strings that the parser should correctly interpret and return.
|
|
||||||
*
|
|
||||||
* @return string[][]
|
|
||||||
*/
|
|
||||||
public function provideExampleDescriptions()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
['This is text for a description.'],
|
|
||||||
['This is text for a {@link http://phpdoc.org/ description} that uses an inline tag.'],
|
|
||||||
['{@link http://phpdoc.org/ This} is text for a description that starts with an inline tag.'],
|
|
||||||
[
|
|
||||||
'This is text for a description with {@internal inline tag with {@link http://phpdoc.org another '
|
|
||||||
. 'inline tag} in it}.'
|
|
||||||
],
|
|
||||||
['This is text for a description containing { that is literal.'],
|
|
||||||
['This is text for a description containing {@internal inline tag that has { that is literal}.'],
|
|
||||||
['This is text for a description with {} that is not a tag.'],
|
|
||||||
['This is text for a description with {@internal inline tag with {} that is not an inline tag}.'],
|
|
||||||
['This is text for a description with an {@internal inline tag with literal {{@}link{} in it}.']
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user