【发布时间】:2009-02-10 11:11:20
【问题描述】:
是否有任何工具(最好是免费软件)可以分析 Pascal/Delphi 语法并自动删除未使用的变量?
在我的例子中,我正在使用一个非常大的 Delphi 代码库,编译器提示报告了超过一千个“变量 'x' 已声明但从未使用”的情况。
我需要花费数小时才能手动删除它们,而且我可能会出错,但正确的工具应该能够安全且自动地执行此操作。
我在网上搜索了但没有找到...这里有人知道这样的工具吗?
谢谢...
马克·布拉福德
【问题讨论】:
是否有任何工具(最好是免费软件)可以分析 Pascal/Delphi 语法并自动删除未使用的变量?
在我的例子中,我正在使用一个非常大的 Delphi 代码库,编译器提示报告了超过一千个“变量 'x' 已声明但从未使用”的情况。
我需要花费数小时才能手动删除它们,而且我可能会出错,但正确的工具应该能够安全且自动地执行此操作。
我在网上搜索了但没有找到...这里有人知道这样的工具吗?
谢谢...
马克·布拉福德
【问题讨论】:
我明白你的意思,并且完全同意这样的工具在处理遗留代码时会很有用。不幸的是,我不知道任何现有的工具(我应该在这里添加免费软件工具,静态分析工具当然应该能够轻松完成,但我不知道任何免费的静态代码分析工具)能够做到这一点.
但我想你可以在几分钟内轻松编写出这样的工具。一个带有备忘录和按钮的小 GUI 就足够了。然后只需将编译器提示复制到备忘录中并按下按钮。然后该工具解析每一行。它可以很容易地检查该行是否包含您正在寻找的提示,并且每个这样的行具有相同的结构,因此解析应该相对容易。然后它可以提取文件名和行号,打开文件并删除变量声明。如果在一行中声明多个变量,这可能有点棘手,但我认为这是可行的。
与自己删除所有变量声明的任务相比,我不知道这是否对您来说太过分了。但是我很想看到这样的工具,所以随意写吧:)
希望至少有一点帮助。
好吧,我真的看不出这里有什么问题。解析部分:
function ParseHint (const HintText : String; out HintInfo : THintInfo) : Boolean;
var
I, J : Integer;
HintName : String;
begin
Result := False;
for I := 1 to Length (HintText) do
begin
if (HintText [I] = '(') then
begin
J := I + 1;
while (HintText [J] <> ')') do Inc (J);
HintInfo.LineNumber := StrToInt (MidStr (HintText, I+1, J-(I+1)));
HintInfo.SourceFile := MidStr (HintText, 12, I-12);
HintName := MidStr (HintText, J+3, 5);
if (HintName <> 'H2164') then Exit (False);
end;
if (HintText [I] = '''') then
begin
J := I + 1;
while (HintText [J] <> '''') do Inc (J);
HintInfo.VarName := MidStr (HintText, I+1, J-(I+1));
Exit (True);
end;
end;
end;
嗯,读取源文件应该很容易,所以唯一剩下的部分就是从它的声明行中删除变量。我们可以简单地搜索该行中出现的 HintInfo.VarName 并检查出现前后的字符是否不是字母而只有''、'、'或':'。如果是这种情况,我们可以将其删除。这涵盖了所有这些情况:
var UnusedVar : Integer;
var
UnusedVar,
AnotherVar : Integer;
var
UnusedVar, AnotherVar : Integer;
如果我错了或者我忘记了任何情况,请告诉我,但我认为这会起作用,并且会解决使用编译器生成的提示从 delphi 源文件中删除未使用变量的问题。
【讨论】:
解决方案很简单,但需要这些时间来确保您不会犯错。首先,您可以使用 Alt-F8 一个接一个地浏览每个报告(而 Alt-F7 可以后退)。这使得定位它们变得非常容易。光标为您放在行上。然后只需按两次“/”键即可将其注释掉。不要删除它,评论它。这样,如果您犯了错误,您就不会丢失任何信息。变量的存在和它的数据类型仍然被记录下来。您可以稍后再整理。
对此有一个警告:条件编译可能会在以不同方式构建时使某些变量未使用。如果发生这种情况,那么只需再次取消注释变量,并将条件也放在声明周围。
【讨论】:
您确定不应该使用这些变量吗?我知道编译器发现它们现在没有被使用,但这是正确的,也许应该使用其中的许多,但是开发人员使用 x2 而不是 x1,例如复制和粘贴?
虽然您可能想删除所有未经审查的变量,但我不会这么仓促,它们可能表明您希望修复代码中的错误。
例子:
procedure PlotPixelAtCenter(rect: Rectangle)
var
x, y: Integer;
begin
x := (rect.Left + rect.Right) div 2;
x := (rect.Top + rect.Bottom) div 2; // <-- bug here, should be y :=
PlotPixel(x, y);
end;
在此示例中,您将收到有关未使用变量的错误,但这是一个潜伏的错误。当然,在这个例子中,错误应该很容易找到,因为绘图可能会关闭,但其他类似的错误可能更难发现。
【讨论】:
如果没有这样的工具并且你有一些耐心,我正在构建一个Delphi分析和修复工具。删除未使用的符号也在列表中。这是一个低优先级项目,所以我无法估计它何时准备就绪。
只是为了解释为什么这不是一项简单的任务:
任务 1 和 2 很难(幸运的是我已经完成了)。 Delphi 语言相当复杂。而且您需要所有语言元素才能重新创建源代码。
任务 3 很简单。只需标记所有未使用的符号。但要注意单元接口部分中的符号。它们可能不被使用,但以后需要(或其他项目)。
任务 4 取决于。
方法 A 使用中间格式(例如字符串列表),然后您可以使用模型查找每个未使用符号的声明(自下而上,否则您可能会更改行号)。你删除所有不需要的。如果它是列表中的最后一个 var,请不要忘记删除 var 关键字!
方法 B 完全重写源文件。在这种情况下,您必须保留所有不太有趣的 cmets(但我的模型也需要这样做)。您只需从模型中删除未使用的符号并重写它。 始终确保创建备份,因为这可能会导致灾难。
【讨论】: