Как стать автором
Обновить

Комментарии 29

не показывайте это разработчикам MODx (они скрипты в БД держат....)
Боюсь они это сами могут увидеть.
Почему не показывать? ;-)
Хотел было предложить написать расширение для PHPUnit, чтобы можно было мокать нативные функции в тестах, но оказалось, что такое уже есть.
Ага. Только, если я правильно понял, там перекрытие функций осуществляется за счет namespace'ов, что проще и, думаю, даже правильнее в том контексте.
www.php.net/manual/ru/features.commandline.options.php
-w Отображает исходный текст без комментариев и пробелов

Composer — если указать папку для файлов:
autoload": {
«classmap»: [«lib»],

— сгенерит autoload_classmap.php файл со списком всех файлов, обработает и папки и подпапки.
Все таки сравнивать запуск из консоли с обработкой tokenizer'ом не совсем корректно. Безусловно такого же результата можно добиться и другими способами. Я привел простейший пример обработки.

Что касается composer — конечно, я знал, что у него есть такая возможность. Но опять же, мой генератор автозагрузки родился в результате экспериментов с tokenizer'ом. И он так же генерирует список всех файлов, из подпапок и подпапок подпапок.
Разница лишь в том, что тут одна функция, которая заправляет всем анализом и по которой можно понять принцип работы tokenizer'а, а composer — это пакетный менеджер, в котором ни одна тысяча строчек кода.
Специально открыл исходники composer по части генерации автозагрузчика — и увидел следующее:
// ... тут пара регулярок, затем вот это
preg_match_all('{
            (?:
                 \b(?<![\$:>])(?P<type>class|interface'.$traits.') \s+ (?P<name>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)
               | \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\s*\\\\\s*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*)? \s*[\{;]
            )
        }ix', $contents, $matches);
// .. еще пара регулярок


Я ничего не имею против регулярных выражений, но разобраться тут сложно, да и подход совершенно другой. Прелесть tokenizer'а в том, что он обрабатывает именно языковые конструкции, а не все подряд. Т.о. я уверен, что моя функция обработает только php-код.
для такой простой задачи как реализовано — не суть. главное что работает как надо.

а использование tokenizer имеет смысл при реализации например хитрой системы макросов для php или
конвертера кода под новые версии php в старые версии и наоборот.

НЛО прилетело и опубликовало эту надпись здесь
И это весьма достойное применение tokenizer'у.
А, например, я с помощью токенайзера узнаю в каком методе в моём проекте на symfony 1.4 произошла ошибка. Беру из эксепшна file и line, строю дерево и нахожу ближайший сверху токен функции.
Мне казалось, я что-то подобное видел в yii. Там при ошибке/эксепшене отображалась функция, в которой это событие произошло.
Хотелось бы взглянуть на реализацию, в yii я побоялся лезть. Применение очень интересное.
Это дерево вызовов (история), не совсем то. Называется debug_backtrace(). Используется, например, при реализации Singleton в PHP5.2.
Что такое debug_backtrace() я знаю, просто в ассоциациях всплыла именно эта фишка, красиво у них она реализована. Как она устроена, я не смотрел, но предположил, что именно так ее можно реализовать. В любом случае, спасибо за поянение.
Еще одна возможность, которую обеспечивает токинайзер — написание простого обфускатора кода.
Так же, есть мысль использовать его для анализа качества сторонних решений для коробочного продукта. Например, можно выявить, что разработчик из модели пытается обратиться к контроллеру или из контроллера напрямую взаимодействовать с бд (неймспейсы очень помогают в этом).
С обусфактором вопрос спорный, тут наверное все же лучше использовать какое-то готовое решение т.к. система может получиться не шуточной, но возможность такая есть конечно.
А вот с анализом коробочного продукта — идея хорошая, я приму на заметку, спасибо!
У меня обфускатор получился не более 80-100 строк кода. он, конечно, не идеален, но решает маркетинговые задачи не хуже готовых коробочных. учитывая, что при желании любой обфусцированный код можно деобфусцировать, а для сторонних решений есть уже готовые деобфускаторы, то простой обфускатор, использующий токинайзер более чем не плох:)
Так родилась библиотечка Runtime, с помощью которой, можно во время выполнения скрипта запретить использование любых стандартных функций, или переопределить их.

Если я сделаю eval(«func();») тоже будет работать запрет на вызов функции?
Я думал над этой возможностью, но совсем сильно заморачиваться не хотелось. Пришел к выводу, что проще запретить eval() и create_function() в такой ситуации.
Есть тысячи способов вызвать функцию без create_function и eval. Для этого нужно использовать любую функцию, которая используется callback или вызвать её через call_user_func, или через переменную: $funcname().
Ага, такие варианты тоже есть. Их достаточно сложно отловить, поэтому эти ситуации я не стал обрабатывать.
В таких ситуациях лучше пользоваться опцией disable_functions или расширением runkit, чтобы запретить выполнение на уровне интерпретации.
А вообще, это интересная задача, возьму на заметку и попробую реализовать и такие проверки.
все бы было хорошо, но насколько я знаю token_get_all наглухо затыкается при встрече чего-то не слишком валидного, или смешанного с НЕ-php. Поэтому например Doctrine до сих пор использует парсер аннотаций на регулярках, хотя было бы круто если бы они уже были по RFC и tokenizer умел их обрабатывать как-следует. А вообще я целиком ЗА дальнейшего развития встроенного парсера.
> наглухо затыкается при встрече чего-то не слишком валидного
Эм… код либо валидный, либо нет. Если парсер работает не так как хочется на невалидном коде, то я даже не знаю к кому претензии предъявлять.

> или смешанного с НЕ-php.
О чём именно речь?

> Поэтому например Doctrine до сих пор использует парсер аннотаций на регулярках…
«Поэтому»? Для языка эти аннотации это всего лишь комментарии.

> А вообще я целиком ЗА дальнейшего развития встроенного парсера.
В какую сторону?
«Поэтому»? Для языка эти аннотации это всего лишь комментарии.
Может расскажешь это wiki.php.net/rfc/annotations?
В какую сторону?
См. выше. в сторону развития.
Как сказал товарищ sectus, — token_get_all может затыкаться из-за невалидного кода.
Я проверял работоспособность на смешанном коде, типа
- Привет, друзья!
<?php
echo "<br/> - Как дела?";
?>
<br /> - Да все в порядке!


При парсинге кода я сперва разделяю код на блоки php и не-php. То, что не-php — оборачиваю в nowdoc/heredoc, а потом склеиваю. Таким образом получается монолитный php-код, который можно нормально парсить. Производительность падает, конечно, из-за такого анализа, но пока идей лучше мне не пришло.
Парсер аннотаций и регулярки конечно же могут справиться с подобной задачей, вот только это не анализ кода получается, а анализ текста. А текст, сами понимаете, может быть совсем не таким, как ожидалось.

upd: А под встроенным парсером вы что понимаете? tokenizer или либу?
tokenizer-либу! Я и говорил выше что приходится подыскивать больному костылики… хотя по-хорошему больной должен не только излечиться, но и прозреть научившись сам определять что за набор букаф ему подсунули иначе можно с таким же успехом регулярками парсить текст а не tokenizer'ом.
Или еще худший костыль встречается — чтобы tokenizer понял код, давайте его сначала делать валидным! Вот вас в ту степь понесло, хоть и не так глубоко как некоторых.
> tokenizer-либу
Она использует лексичекий парсер самого языка. Поэтому, чтобы токенайзер смог разбирать аннотации, аннотации должны стать частью языка.

> Может расскажешь это wiki.php.net/rfc/annotations?
А чего говорить то? Это предложение(не единственное) о добавление парсинга аннотаций… в отражениях(т.е. никак не влияет на работу токенайзера). Только уже существуют библиотеки по парсингу аннотаций. Не думаю, что реализация этих библиотек как-то поможет развитию самого языка.

> Или еще худший костыль встречается — чтобы tokenizer понял код, давайте его сначала делать валидным! Вот вас в ту степь понесло, хоть и не так глубоко как некоторых.
У вас «костный язык» — не ясно что именно Вы хотели сказать. Покажите на примерах то, что вы хотите от него и с чем он не справляется.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории