有没有办法在Delphi中找到未使用的事件处理程序?
在Delphi中查找死代码通常非常简单:只需编译并扫描缺少蓝点的例程。聪明的链接器在大多数情况下都能很好地跟踪他们 问题是,这对事件处理程序不起作用,因为它们是已发布的方法(理论上)可以通过RTTI以某种方式调用,即使在实际操作中几乎从未发生过这种情况有没有办法在Delphi中找到未使用的事件处理程序?,delphi,event-handling,vcl,dead-code,Delphi,Event Handling,Vcl,Dead Code,在Delphi中查找死代码通常非常简单:只需编译并扫描缺少蓝点的例程。聪明的链接器在大多数情况下都能很好地跟踪他们 问题是,这对事件处理程序不起作用,因为它们是已发布的方法(理论上)可以通过RTTI以某种方式调用,即使在实际操作中几乎从未发生过这种情况 我正试图清理一个巨大的VCL表格单元,它在历史上被多次弯曲、折叠、旋转和破坏。如果我有办法找到表单的DFM实际上没有引用的事件处理程序并将其删除,那就太好了。有什么简单的方法可以做到这一点吗?例如,插件式IDE专家?没有解决方案可以保证在最一般的
我正试图清理一个巨大的VCL表格单元,它在历史上被多次弯曲、折叠、旋转和破坏。如果我有办法找到表单的DFM实际上没有引用的事件处理程序并将其删除,那就太好了。有什么简单的方法可以做到这一点吗?例如,插件式IDE专家?没有解决方案可以保证在最一般的情况下给出正确的答案(正如您所注意的,基于通过RTTI调用他们的可能性) 一种解决方案是进行代码覆盖率测试,并仔细查看从未访问过的处理程序。这有点难看(好吧,它非常难看),但对于一个单元来说,它几乎是万无一失的,并且不需要额外的工具:
我不知道有没有现成的应用程序或插件可以做到这一点,但编写脚本应该不难 假设您没有使用RTTI或手动分配事件处理程序:(我是C++Builder用户,而不是Delphi用户,因此以下内容可能不太正确。)
- 正确的方法是读取
。查找以*.pas
声明或类
指令开头,以发布的
、结束
或私有
结尾的每个文本块。在每个文本块中,提取每个公共
过程
- 实现这一点的简单方法是列出常见事件处理程序类型,并假设它们已发布
#!/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
- 键入
,然后按Enter键/cleanup.sh
但是,通过查找所有具有(Sender:TObject)方法签名的方法并将其与.dfm中的方法进行比较,您可能会找到所有被放弃的处理程序(如果您使用的是旧版本的delphi,请确保将其保存为文本),在我的书中,没有自动连接的东西是可疑的 --
如果不想沿着cygwin的路径走,可以将src和dfm加载到两个TStirngLists中,从每个TStirngLists中删除名称/标识,并生成一个包含两个循环和一些字符串操作的列表。我猜大概要花20分钟的时间才能得到你能接受的东西。有一种方法比克雷格的简单得多 转到可疑事件处理程序。以一致的方式重命名它——我通过在名称前面放一个x来完成这一操作,然后转到实现并执行相同的操作。看看编译器是怎么想的 如果它不高兴,你就把名字改回去 您可以使用相同的方法来消除不再执行任何操作的数据元素。使用“重命名方法”重构来重命名每个事件处理程序。选中“重构前查看引用”复选框 检查重构窗口。如果事件处理程序链接到控件,则会有一个“VCL设计器更新”部分显示哪些控件链接到该方法 这还将显示该方法是从任何其他单元调用的,还是以编程方式分配的
注意:这是针对D2006的,在以后的版本中可能略有不同。包含所谓的。它还显示未连接到任何组件的事件处理程序。我不是在寻找“最一般的情况”;我在寻找最常见的情况:对照DFM中引用的处理程序,检查PAS文件表单声明顶部声明的事件处理程序列表,并报告任何孤立事件。谢谢,但正如我对MarkusQ所说的,我在这里看到的是最常见的情况,而不是例外情况。我很清楚,有