Статьи

Представляем php-tracer-weaver

Одна из менее известных особенностей xdebug — это следы его функций . Если вы не слышали об этом раньше, он «позволяет вам регистрировать все вызовы функций, включая параметры и возвращаемые значения в файл» , чтобы процитировать руководство. Поработав с ним некоторое время, я понял, что эту информацию можно анализировать и использовать для определения типов параметров и типов возвращаемых функций.

Итак, в качестве доказательства концепции я написал скрипт для анализа следов функций из xdebug и использую его для обработки исходного файла php и вставки комментариев @param с @param и @return . Мне пришлось объединить динамический анализ (отслеживание функций) с некоторым статическим анализом, чтобы иметь возможность сопоставлять различные подтипы в их супертипе, что сделало всю сделку немного сложнее, чем предполагалось вначале.

Есть еще возможности для улучшения, но в прошлый четверг на местной встрече php я продемонстрировал проект, и теперь он доступен через github .

Использование делится на два этапа. Сначала вы запускаете код, используя инструментарий xdebug для генерации трассировки. Я создал скрипт-обертку, чтобы сделать это проще. Просто вызовите скрипт php с помощью trace.sh foo.php , а не php foo.php . Это будет запускать сценарий в обычном режиме при генерации трассировки в файле dumpfile.xt .

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

Следующий шаг — проанализировать эти данные и использовать их для создания комментариев к докблоку. Это делается с помощью инструмента weave.php . Вы, вероятно, захотите вызывать weave.php несколько раз (для каждого файла в вашем проекте, для которого вы хотите сгенерировать документацию).

Вот пример, чтобы показать процесс:

Мы начнем с очень простого файла, без комментариев docblock:

 <?php class Foo { function stuff($x) { return 42; } } class Bar {} $f = new Foo(); $f->stuff(new Bar()); 

Первый шаг — запустить файл, используя trace.sh :

 $ /path/to/php-tracer/weaver/trace.sh foo.php Running script with instrumentation: foo.php TRACE COMPLETE 

Далее мы вплетим документацию обратно в файл:

 $ /path/to/php-tracer/weaver/weave.php foo.php foo.php 

И это все .. Наш файл теперь выглядит так:

 <?php class Foo { /** * @param Bar * @return integer */ function stuff($x) { return 42; } } class Bar {} $f = new Foo(); $f->stuff(new Bar()); 

Реализация скорее эффективна для памяти, чем для процессора, что означает, что она будет работать с большими базами кода, но для ее обработки потребуется некоторое время.