Есть ли способ найти неиспользуемые обработчики событий в Delphi?

Поиск мертвого кода в Delphi обычно очень прост: просто скомпилируйте, а затем сканируйте подпрограммы, пропускающие их синие точки. Умный компоновщик очень хорош в отслеживании их, большую часть времени.

Проблема в том, что это не работает для обработчиков событий, потому что они являются опубликованными методами, которые (теоретически) могут быть вызваны через RTTI, даже если это практически никогда не происходит на практике.

Я пытаюсь вычистить большую единицу формы VCL, которая была изогнута, сложена, обмотана и изуродована несколько раз на протяжении всей своей истории. Было бы неплохо, если бы у меня был какой-то способ найти обработчики событий, на которые на самом деле не ссылается DFM формы, и удалить их. Есть ли простой способ сделать это? Плагин IDE Expert, например?

7 ответов

Решение

Я не думаю, что это возможно с автоматической точки зрения. обработчики событий активируются, когда конкретное событие происходит внутри объекта. То, что даже четность не запускается в данном прогоне, не означает, что нет пути выполнения, который мог бы привести к нему.

Кроме того, вы можете динамически назначать обработчики во время выполнения, так что то, что используется в одной ситуации, не гарантируется.

например

button.onclick: = DefaultClickHandler;

button.onClick: = SpecialClickHandler;

Предполагая, что обработчики щелчков совпадают с сигнатурой события onclick, но вы не получите компиляцию, если подпись была неверной.


однако вы, вероятно, можете найти все заброшенные обработчики, найдя все методы, которые имеют сигнатуру (Sender: TObject), и сравнив его методы с методами в.dfm (убедитесь, что вы сохранили его как текст, если вы работая с более старой версией Delphi), в моей книге будет подозрение на автоматическое соединение с антивирусом.

-

если вы не хотите идти по пути cygwin, вы можете загрузить src и dfm в два TStirngLists и вырвать имена / идентификаторы из каждого и сгенерировать список с парой циклов и некоторыми строковыми манипуляциями. Я думаю, что около 20 минут работы, чтобы получить то, что вы можете жить с.

Используйте рефакторинг "Метод переименования", чтобы переименовать каждый обработчик событий. Установите флажок "Просмотр ссылок перед рефакторингом".

Проверьте окно рефакторинга. Если обработчик событий связан с элементом управления, в разделе "VCL Designer Updates" будет показано, какие элементы управления связаны с методом.

Это также покажет, вызван ли метод из каких-либо других модулей или назначен программно.

Примечание: это для D2006, может немного отличаться в более поздних версиях.

Это немного некрасиво (хорошо, это очень некрасиво), но для одного блока это почти надежно и не требует дополнительных инструментов:

  1. Убедитесь, что текущая версия формы проверена в системе контроля версий!
  2. Перейти к началу интерфейса класса, где находятся обработчики событий. Удалите все интерфейсы методов обработчика событий.
  3. Посмотрите на Code Explorer/Error Insight. Методы, которые имеют реализации, но не имеют интерфейсов, будут выделены. Удалить реализации.
  4. Теперь сохраните устройство. Delphi по очереди будет жаловаться на отсутствующий обработчик событий для каждого события, которое фактически обрабатывается. Запишите их по мере появления ошибок.
  5. Проверьте оригинальную версию формы и удалите обработчики событий для чего-либо, чего нет в вашем списке.

ModelMaker Code Explorer содержит так называемое представление обработчика событий. Он также показывает обработчики событий, не связанные с каким-либо компонентом.

Не существует решения, которое гарантированно дало бы правильный ответ в самом общем случае (основываясь, как вы заметили, на возможности вызова их через RTTI).

Одним из решений было бы сделать тесты покрытия кода и внимательно посмотреть на обработчики, которые никогда не были достигнуты.

Я не знаю о существующем приложении или плагине, чтобы сделать это, но это не должно быть сложно для сценария.

Предполагая, что вы не используете RTTI или вручную назначаете обработчики событий: (я пользователь C++Builder, а не Delphi, поэтому следующее может быть не совсем правильным.)

  1. Составьте список всех опубликованных методов в вашем коде.
    • Правильный способ сделать это - прочитать *.pas, Найдите каждый текстовый блок, который начинается с class декларация или published директива и заканчивается end, private, или же public, В каждом из этих текстовых блоков извлеките каждый procedure,
    • Самый простой способ сделать это - составить список распространенных типов обработчиков событий и предположить, что они опубликованы.
  2. Получив этот список, распечатайте все из списка, которого нет в вашем файле DFM.

Мне удобнее всего использовать инструменты Cygwin или Linux для написания сценариев. Вот скрипт bash, который работает в Cygwin и должен делать то, что вы хотите.

#!/bin/bash

for file in `find -name *.pas`; do
    echo $file:

    # Get a list of common event handling procedures.
    # Add more types between the | symbols.
    egrep '^[[:space:]]+procedure.*(Click|FormCreate|FormClose|Change|Execute)\(' $file | 
    awk '{print $2}' | cut -f 1 -d '(' > published.txt

    # Get a list of used event procedures.
    egrep '^[[:space:]]+On.* =' ${file%.pas}.dfm | awk '{print $3}' > used.txt

    # Compare the two.
    # Files listed in the left column are published but not used, so you can delete them.
    # Files in the right column were not by our crude search for published event 
    # handlers, so you can update the first egrep command to find them.
    comm -3 published.txt used.txt

    echo

done

# Clean up.
rm published.txt used.txt

Чтобы действительно использовать это, если вы не знакомы с Cygwin:

  • Скачайте и установите Cygwin. Я думаю, что установка по умолчанию должна дать вам все инструменты, которые я использовал, но я не уверен.
  • Сохраните скрипт в исходный каталог как cleanup.sh,
  • Запустите командную строку Cygwin.
  • Если ваш источник находится в c:\MyApp, введите cd /cygdrive/c/myapp
  • Тип ./cleanup.sh и нажмите Enter.

Там гораздо проще, чем у Крейга.

Перейти к подозрительному обработчику событий. Переименуйте его непротиворечивым способом - я делаю это, помещая перед именем знак x, перехожу к реализации и делаю то же самое. Посмотрите, что об этом думает компилятор.

Если это не радует, просто поменяйте имена обратно.

Вы можете использовать тот же подход, чтобы исключить элементы данных, которые больше ничего не делают.

Другие вопросы по тегам