abstracted docblock comment extraction, implemented in JmsMetadataParser to get parameter descriptions

This commit is contained in:
Evan Villemez 2012-08-31 14:57:42 -04:00
parent 65c634d32b
commit 8c3466f6ed
7 changed files with 86 additions and 49 deletions

View File

@ -18,6 +18,7 @@ use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Nelmio\ApiDocBundle\Util\DocCommentExtractor;
class ApiDocExtractor
{
@ -40,16 +41,22 @@ class ApiDocExtractor
*/
private $reader;
/**
* @var \Nelmio\ApiDocBundle\Util\DocCommentExtractor
*/
private $commentExtractor;
/**
* @var array \Nelmio\ApiDocBundle\Parser\ParserInterface
*/
private $parsers = array();
public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader)
public function __construct(ContainerInterface $container, RouterInterface $router, Reader $reader, DocCommentExtractor $commentExtractor)
{
$this->container = $container;
$this->router = $router;
$this->reader = $reader;
$this->commentExtractor = $commentExtractor;
}
/**
@ -208,7 +215,7 @@ class ApiDocExtractor
// description
if (null === $annotation->getDescription()) {
$comments = explode("\n", $this->getDocCommentText($method));
$comments = explode("\n", $this->commentExtractor->getDocCommentText($method));
// just set the first line
$comment = trim($comments[0]);
$comment = preg_replace("#\n+#", ' ', $comment);
@ -221,7 +228,7 @@ class ApiDocExtractor
}
// doc
$annotation->setDocumentation($this->getDocCommentText($method));
$annotation->setDocumentation($this->commentExtractor->getDocCommentText($method));
// input (populates 'parameters' for the formatters)
if (null !== $input = $annotation->getInput()) {
@ -271,7 +278,7 @@ class ApiDocExtractor
}
$paramDocs = array();
foreach (explode("\n", $this->getDocComment($method)) as $line) {
foreach (explode("\n", $this->commentExtractor->getDocComment($method)) as $line) {
if (preg_match('{^@param (.+)}', trim($line), $matches)) {
$paramDocs[] = $matches[1];
}
@ -308,45 +315,6 @@ class ApiDocExtractor
return $annotation;
}
/**
* @param \Reflector $reflected
* @return string
*/
protected function getDocComment(\Reflector $reflected)
{
$comment = $reflected->getDocComment();
// let's clean the doc block
$comment = str_replace('/**', '', $comment);
$comment = str_replace('*', '', $comment);
$comment = str_replace('*/', '', $comment);
$comment = str_replace("\r", '', trim($comment));
$comment = preg_replace("#^\n[ \t]+[*]?#i", "\n", trim($comment));
$comment = preg_replace("#[\t ]+#i", ' ', trim($comment));
$comment = str_replace("\"", "\\\"", $comment);
return $comment;
}
/**
* @param \Reflector $reflected
* @return string
*/
protected function getDocCommentText(\Reflector $reflected)
{
$comment = $reflected->getDocComment();
// Remove PHPDoc
$comment = preg_replace('/^\s+\* @[\w0-9]+.*/msi', '', $comment);
// let's clean the doc block
$comment = str_replace('/**', '', $comment);
$comment = str_replace('*/', '', $comment);
$comment = preg_replace('/^\s*\* ?/m', '', $comment);
return trim($comment);
}
/**
* Parses annotations for a given method, and adds new information to the given ApiDoc
* annotation. Useful to extract information from the FOSRestBundle annotations.

View File

@ -12,6 +12,7 @@
namespace Nelmio\ApiDocBundle\Parser;
use Metadata\MetadataFactoryInterface;
use Nelmio\ApiDocBundle\Util\DocCommentExtractor;
/**
* Uses the JMS metadata factory to extract input/output model information
@ -19,12 +20,23 @@ use Metadata\MetadataFactoryInterface;
class JmsMetadataParser implements ParserInterface
{
/**
* @var \Metadata\MetadataFactoryInterface
*/
private $factory;
/**
* @var \Nelmio\ApiDocBundle\Util\DocCommentExtractor
*/
private $commentExtractor;
/**
* Constructor, requires JMS Metadata factory
*/
public function __construct(MetadataFactoryInterface $factory)
public function __construct(MetadataFactoryInterface $factory, DocCommentExtractor $commentExtractor)
{
$this->factory = $factory;
$this->commentExtractor = $commentExtractor;
}
/**
@ -148,9 +160,9 @@ class JmsMetadataParser implements ParserInterface
protected function getDescription($className, $propertyName)
{
$description = "No description.";
//TODO: abstract docblock parsing utility and implement here
$ref = new \ReflectionClass($className);
$extracted = $this->commentExtractor->getDocCommentText($ref->getProperty($propertyName));
$description = !empty($extracted) ? $extracted : "No description.";
return $description;
}

View File

@ -10,6 +10,7 @@
<services>
<service id="nelmio_api_doc.parser.jms_metadata_parser" class="%nelmio_api_doc.parser.jms_metadata_parser.class%">
<argument type="service" id="jms_serializer.metadata_factory" />
<argument type="service" id="nelmio_api_doc.doc_comment_extractor" />
<tag name="nelmio_api_doc.extractor.parser" />
</service>
</services>

View File

@ -7,13 +7,17 @@
<parameter key="nelmio_api_doc.extractor.api_doc_extractor.class">Nelmio\ApiDocBundle\Extractor\ApiDocExtractor</parameter>
<parameter key="nelmio_api_doc.form.extension.description_form_type_extension.class">Nelmio\ApiDocBundle\Form\Extension\DescriptionFormTypeExtension</parameter>
<parameter key="nelmio_api_doc.twig.extension.extra_markdown.class">Nelmio\ApiDocBundle\Twig\Extension\MarkdownExtension</parameter>
<parameter key="nelmio_api_doc.doc_comment_extractor.class">Nelmio\ApiDocBundle\Util\DocCommentExtractor</parameter>
</parameters>
<services>
<service id='nelmio_api_doc.doc_comment_extractor' class='%nelmio_api_doc.doc_comment_extractor.class%' />
<service id="nelmio_api_doc.extractor.api_doc_extractor" class="%nelmio_api_doc.extractor.api_doc_extractor.class%">
<argument type="service" id="service_container"/>
<argument type="service" id="router" />
<argument type="service" id="annotation_reader" />
<argument type="service" id="nelmio_api_doc.doc_comment_extractor" />
</service>
<service id="nelmio_api_doc.form.extension.description_form_type_extension" class="%nelmio_api_doc.form.extension.description_form_type_extension.class%">

View File

@ -20,6 +20,8 @@ class JmsNested
/**
* Epic description.
*
* With multiple lines.
*
* @JMS\Type("array<integer>")
*/
public $baz;

View File

@ -232,7 +232,9 @@ class SimpleFormatterTest extends WebTestCase
'baz' => array(
'dataType' => 'array of integers',
'required' => false,
'description' => 'No description.',
'description' => 'Epic description.
With multiple lines.',
'readonly' => false,
)
)
@ -258,7 +260,9 @@ class SimpleFormatterTest extends WebTestCase
'baz' => array(
'dataType' => 'array of integers',
'required' => false,
'description' => 'No description.',
'description' => 'Epic description.
With multiple lines.',
'readonly' => false,
)
)

View File

@ -0,0 +1,46 @@
<?php
namespace Nelmio\ApiDocBundle\Util;
class DocCommentExtractor
{
/**
* @param \Reflector $reflected
* @return string
*/
public function getDocComment(\Reflector $reflected)
{
$comment = $reflected->getDocComment();
// let's clean the doc block
$comment = str_replace('/**', '', $comment);
$comment = str_replace('*', '', $comment);
$comment = str_replace('*/', '', $comment);
$comment = str_replace("\r", '', trim($comment));
$comment = preg_replace("#^\n[ \t]+[*]?#i", "\n", trim($comment));
$comment = preg_replace("#[\t ]+#i", ' ', trim($comment));
$comment = str_replace("\"", "\\\"", $comment);
return $comment;
}
/**
* @param \Reflector $reflected
* @return string
*/
public function getDocCommentText(\Reflector $reflected)
{
$comment = $reflected->getDocComment();
// Remove PHPDoc
$comment = preg_replace('/^\s+\* @[\w0-9]+.*/msi', '', $comment);
// let's clean the doc block
$comment = str_replace('/**', '', $comment);
$comment = str_replace('*/', '', $comment);
$comment = preg_replace('/^\s*\* ?/m', '', $comment);
return trim($comment);
}
}