Разбор комментариев PHP Doc в структуру данных
Я использую Reflection API в PHP, чтобы получить строку DocComment (PHPDoc) из метода
$r = new ReflectionMethod($object);
$comment = $r->getDocComment();
Это вернет строку, которая выглядит примерно так (в зависимости от того, насколько хорошо метод был задокументирован)
/**
* Does this great things
*
* @param string $thing
* @return Some_Great_Thing
*/
Существуют ли какие-либо встроенные методы или функции, которые могут анализировать строку комментариев Doc PHP в структуру данных?
$object = some_magic_function_or_method($comment_string);
echo 'Returns a: ', $object->return;
Не имея этого, какую часть исходного кода PHPDoc мне следует рассмотреть, сделайте это сами.
Отсутствие и / или в дополнение к этому, есть ли сторонний код, который считается "лучше" в этом, чем код PHPDoc?
Я понимаю, что синтаксический анализ этих строк не является ракетостроением или даже компьютерными науками, но я бы предпочел хорошо протестированную библиотеку / рутину / метод, который был создан для работы с большим количеством непонятного, полу-неправильного кода PHP Doc, который может существовать в дикой природе.
14 ответов
Я удивлен, что это еще не было упомянуто: как насчет использования Zend_Reflection Zend Framework? Это может пригодиться, особенно если вы работаете с программным обеспечением, основанным на Zend Framework, таким как Magento.
См. Руководство по Zend Framework для некоторых примеров кода и Документацию API для доступных методов.
Есть разные способы сделать это:
- Передайте имя файла Zend_Reflection_File.
- Передайте объект в Zend_Reflection_Class.
- Передайте объект и имя метода в Zend_Reflection_Method.
- Если у вас действительно есть только строка комментария, вы даже можете собрать код для небольшого фиктивного класса, сохранить его во временном файле и передать этот файл в Zend_Reflection_File.
Давайте рассмотрим простой случай и предположим, что у вас есть существующий класс, который вы хотите проверить.
Код будет таким (непроверенный, пожалуйста, прости меня):
$method = new Zend_Reflection_Method($class, 'yourMethod');
$docblock = $method->getDocBlock();
if ($docBlock->hasTag('return')) {
$tagReturn = $docBlock->getTag('return'); // $tagReturn is an instance of Zend_Reflection_Docblock_Tag_Return
echo "Returns a: " . $tagReturn->getType() . "<br>";
echo "Comment for return type: " . $tagReturn->getDescription();
}
Вы можете использовать класс "DocBlockParser" из проекта с открытым исходным кодом http://fabien.potencier.org/ Sami ("Another Another PHP API Generator Generator").
Прежде всего, получите саами из GitHub.
Это пример того, как его использовать:
<?php
require_once 'Sami/Parser/DocBlockParser.php';
require_once 'Sami/Parser/Node/DocBlockNode.php';
class TestClass {
/**
* This is the short description.
*
* This is the 1st line of the long description
* This is the 2nd line of the long description
* This is the 3rd line of the long description
*
* @param bool|string $foo sometimes a boolean, sometimes a string (or, could have just used "mixed")
* @param bool|int $bar sometimes a boolean, sometimes an int (again, could have just used "mixed")
* @return string de-html_entitied string (no entities at all)
*/
public function another_test($foo, $bar) {
return strtr($foo,array_flip(get_html_translation_table(HTML_ENTITIES)));
}
}
use Sami\Parser\DocBlockParser;
use Sami\Parser\Node\DocBlockNode;
try {
$method = new ReflectionMethod('TestClass', 'another_test');
$comment = $method->getDocComment();
if ($comment !== FALSE) {
$dbp = new DocBlockParser();
$doc = $dbp->parse($comment);
echo "\n** getDesc:\n";
print_r($doc->getDesc());
echo "\n** getTags:\n";
print_r($doc->getTags());
echo "\n** getTag('param'):\n";
print_r($doc->getTag('param'));
echo "\n** getErrors:\n";
print_r($doc->getErrors());
echo "\n** getOtherTags:\n";
print_r($doc->getOtherTags());
echo "\n** getShortDesc:\n";
print_r($doc->getShortDesc());
echo "\n** getLongDesc:\n";
print_r($doc->getLongDesc());
}
} catch (Exception $e) {
print_r($e);
}
?>
А вот и вывод тестовой страницы:
** getDesc:
This is the short description.
This is the 1st line of the long description
This is the 2nd line of the long description
This is the 3rd line of the long description
** getTags:
Array
(
[param] => Array
(
[0] => Array
(
[0] => Array
(
[0] => Array
(
[0] => bool
[1] =>
)
[1] => Array
(
[0] => string
[1] =>
)
)
[1] => foo
[2] => sometimes a boolean, sometimes a string (or, could have just used "mixed")
)
[1] => Array
(
[0] => Array
(
[0] => Array
(
[0] => bool
[1] =>
)
[1] => Array
(
[0] => int
[1] =>
)
)
[1] => bar
[2] => sometimes a boolean, sometimes an int (again, could have just used "mixed")
)
)
[return] => Array
(
[0] => Array
(
[0] => Array
(
[0] => Array
(
[0] => string
[1] =>
)
)
[1] => de-html_entitied string (no entities at all)
)
)
)
** getTag('param'):
Array
(
[0] => Array
(
[0] => Array
(
[0] => Array
(
[0] => bool
[1] =>
)
[1] => Array
(
[0] => string
[1] =>
)
)
[1] => foo
[2] => sometimes a boolean, sometimes a string (or, could have just used "mixed")
)
[1] => Array
(
[0] => Array
(
[0] => Array
(
[0] => bool
[1] =>
)
[1] => Array
(
[0] => int
[1] =>
)
)
[1] => bar
[2] => sometimes a boolean, sometimes an int (again, could have just used "mixed")
)
)
** getErrors:
Array
(
)
** getOtherTags:
Array
(
)
** getShortDesc:
This is the short description.
** getLongDesc:
This is the 1st line of the long description
This is the 2nd line of the long description
This is the 3rd line of the long description
2022 phpdoc-парсер
У PHPStan теперь есть собственный синтаксический анализатор блоков документов на основе AST:
https://github.com/phpstan/phpdoc-парсер
- это поддерживается в течение длительного времени
- он позволяет пересекать узлы
- он может разрешить fqn
- у него есть принтер, сохраняющий формат
Вот как вы можете изменить его с помощью пользовательского посетителя узла .
Вы можете использовать DocBlox ( http://github.com/mvriel/docblox) для генерации структуры данных XML для вас; Вы можете установить DocBlox, используя PEAR, а затем запустить команду:
docblox parse -d [FOLDER] -t [TARGET_LOCATION]
Это создаст файл с именем structure.xml
который содержит все метаданные о вашем исходном коде, включая проанализированные докблоки.
ИЛИ ЖЕ
Вы можете использовать классы DocBlox_Reflection_DocBlock* для непосредственного анализа фрагмента текста DocBlock.
Это можно сделать, убедившись, что у вас включена автозагрузка (или включены все файлы DocBlox_Reflection_DocBlock*) и выполнено следующее:
$parsed = new DocBlox_Reflection_DocBlock($docblock);
После этого вы можете использовать геттеры для извлечения необходимой вам информации.
Примечание: вам не нужно снимать звездочки; класс Reflection позаботится об этом.
Я предлагаю приложение, оно довольно классное и хорошо живое и используется во многих фреймворках php5...
http://code.google.com/p/addendum/
Проверьте тесты для примеров
Проверять, выписываться
http://pecl.php.net/package/docblock
Думаю, функция docblock_tokenize() поможет вам в этом.
Вы всегда можете просмотреть исходный код из phpDoc. Код находится под лицензией LGPL, поэтому, если вы решите скопировать его, вам нужно будет лицензировать свое программное обеспечение под той же лицензией и правильно добавить правильные уведомления.
РЕДАКТИРОВАТЬ: Если @Samuel Herzog не отметил, что вы используете его в качестве библиотеки.
Спасибо @Samuel Herzog за разъяснения.
Из вашего описания я могу только подозревать, что вы пытаетесь сделать (документация PHP кода). Поскольку вы не заявляете, почему вы пытаетесь это сделать, я могу только строить догадки.
Может быть, вы должны попробовать другой подход. Чтобы документировать PHP-код (если это то, что вы пытаетесь), я бы использовал doxygen, и, судя по вашему комментарию к коду, он уже отформатирован для doxygen.
С Graphviz doxygen также отображает хорошие диаграммы классов и деревья вызовов.
phpdoc-parser (https://github.com/phpstan/phpdoc-parser) наверное самый современный и гибкий способ парсить phpdoc (как говорит Томаш Вотруба), к сожалению документации не так много, вот простой способ начать :
<?php
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\ConstExprParser;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use PHPStan\PhpDocParser\Parser\TypeParser;
require 'vendor/autoload.php';
$comment = <<<'PHP'
/**
* @param int $foo
* @return string|false
*/
PHP;
$phpDocLexer = new Lexer();
$constantExpressionParser = new ConstExprParser();
$phpDocParser = new PhpDocParser(new TypeParser($constantExpressionParser), $constantExpressionParser);
$tokens = new TokenIterator($phpDocLexer->tokenize($comment));
$ast = $phpDocParser->parse($tokens);
print_r($ast);
// For example to get the type of the first param
// $ast->getTagsByName('@param')[0]->value->type->name; // int
Я предлагаю вам взглянуть на http://code.google.com/p/php-annotations/
Код довольно прост для изменения / понимания, если это необходимо.
Если вы пытаетесь прочитать теги @ и их значения, то лучшим решением будет использование preg_match.
Как указано в одном из ответов выше, вы можете использовать phpDocumentor. Если вы используете composer, просто добавьте "phpdocumentor/reflection-docblock": "~2.0" в ваш блок "require".
Посмотрите это для примера: https://github.com/abdulla16/decoupled-app/blob/master/composer.json
Примеры использования см.: https://github.com/abdulla16/decoupled-app/blob/master/Container/Container.php
Обновленная версия кода пользователя 1419445. DocBlockParser::parse()
Метод изменен и нуждается во втором параметре контекста. Кажется, что он также немного связан с phpDocumentor, поэтому для простоты я бы предположил, что у вас установлен Sami через Composer. Код ниже работает для Sami v4.0.16
<?php
require_once 'vendor/autoload.php';
class TestClass {
/**
* This is the short description.
*
* This is the 1st line of the long description
* This is the 2nd line of the long description
* This is the 3rd line of the long description
*
* @param bool|string $foo sometimes a boolean, sometimes a string (or, could have just used "mixed")
* @param bool|int $bar sometimes a boolean, sometimes an int (again, could have just used "mixed")
* @return string de-html_entitied string (no entities at all)
*/
public function another_test($foo, $bar) {
return strtr($foo,array_flip(get_html_translation_table(HTML_ENTITIES)));
}
}
use Sami\Parser\DocBlockParser;
use Sami\Parser\Filter\PublicFilter;
use Sami\Parser\ParserContext;
try {
$method = new ReflectionMethod('TestClass', 'another_test');
$comment = $method->getDocComment();
if ($comment !== FALSE) {
$dbp = new DocBlockParser();
$filter = new PublicFilter;
$context = new ParserContext($filter, $dbp, NULL);
$doc = $dbp->parse($comment, $context);
echo "\n** getDesc:\n";
print_r($doc->getDesc());
echo "\n** getTags:\n";
print_r($doc->getTags());
echo "\n** getTag('param'):\n";
print_r($doc->getTag('param'));
echo "\n** getErrors:\n";
print_r($doc->getErrors());
echo "\n** getOtherTags:\n";
print_r($doc->getOtherTags());
echo "\n** getShortDesc:\n";
print_r($doc->getShortDesc());
echo "\n** getLongDesc:\n";
print_r($doc->getLongDesc());
}
} catch (Exception $e) {
print_r($e);
}
?>
Взгляните на пакет менеджера комментариев Php. Это позволяет анализировать комментарии метода DocBloc. Он использует Php Reflection API для извлечения комментариев методов DocBloc