Разбор комментариев PHP Doc в структуру данных - PullRequest
25 голосов
/ 16 января 2011

Я использую 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 Код документа, который может существовать в дикой природе.

Ответы [ 12 ]

21 голосов
/ 19 июля 2012

Я удивлен, что об этом еще не говорилось: как насчет использования 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();
}
16 голосов
/ 16 июля 2012

Вы можете использовать класс " DocBlockParser " из Fabien Potencier Sami ("Еще один генератор документации API PHP") проект с открытым исходным кодом.
Прежде всего, получите Сами из 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
6 голосов
/ 18 июня 2011

Вы можете использовать DocBlox (http://github.com/mvriel/docblox) для генерации структуры данных XML для вас; вы можете установить DocBlox, используя PEAR , а затем выполнить команду:

docblox parse -d [FOLDER] -t [TARGET_LOCATION]

Это создаст файл с именем structure.xml, который будет содержать все метаданные о вашем исходном коде, включая проанализированные докблоки.

OR

Вы можете использовать DocBlox_Reflection_DocBlock* классов для непосредственного анализа фрагмента текста DocBlock.

Это можно сделать, убедившись, что у вас включена автозагрузка (или включены все файлы DocBlox_Reflection_DocBlock *) и выполнено следующее:

$parsed = new DocBlox_Reflection_DocBlock($docblock);

После этого вы можете использовать getter для извлечения необходимой вам информации.

Примечание: вам не нужно удалять звездочки; класс Reflection принимаетпозаботься об этом.

5 голосов
/ 17 июля 2012

Я предлагаю дополнение, оно довольно классное и хорошо работает и используется во многих фреймворках php5 ...

http://code.google.com/p/addendum/

Проверьте тесты на примерах

http://code.google.com/p/addendum/source/browse/trunk#trunk%2Fannotations%2Ftests

5 голосов
/ 04 февраля 2011

Выезд

http://pecl.php.net/package/docblock

Функция docblock_tokenize (), я думаю, поможет вам в этом.

4 голосов
/ 16 января 2011

Вы всегда можете просмотреть источник из phpDoc . Код находится под LGPL , поэтому, если вы решите скопировать его, вам нужно будет лицензировать свое программное обеспечение под той же лицензией и правильно добавить соответствующие уведомления.

РЕДАКТИРОВАТЬ: Если @Samuel Herzog не отметил, что вы используете его в качестве библиотеки.

Спасибо @Samuel Herzog за разъяснения.

3 голосов
/ 16 января 2011

Из вашего описания я могу только подозревать, что вы пытаетесь сделать (документация PHP-кода).Поскольку вы не заявляете, почему вы пытаетесь это сделать, я могу только строить догадки.

Возможно, вам следует попробовать другой подход.Для документирования кода PHP (если это то, что вы пытаетесь), я бы использовал doxygen и, судя по вашему комментарию к коду, он уже отформатирован для doxygen., doxygen также отображает хорошие диаграммы классов и деревья вызовов.

2 голосов
/ 18 июля 2012

Предлагаю вам взглянуть на http://code.google.com/p/php-annotations/

Код достаточно прост для изменения / понимания, если это необходимо.

2 голосов
/ 15 июля 2012

Если вы пытаетесь прочитать теги @ и их значения, то лучшим решением будет использование preg_match.

1 голос
/ 27 марта 2019

Посмотрите на пакет Php Comment Manager . Это позволяет анализировать комментарии метода DocBloc. Он использует Php Reflection API для извлечения комментариев DocBloc методов

...