14

我在工作的大型 Delphi 代码库中遇到问题,作为从 Delphi 2007 移植到 XE2 的副作用,我们现在遇到以下奇怪的相关问题:

  • 即使在调试版本中,您也无法设置断点或单步执行代码,因为行号完全混乱,仅在某些单元中。

  • 在第 2010 行故意引入语法错误会导致光标聚焦在第 2020 行,给或取 3 或 4 行,如下所示:

.

 procedure Correct;
 begin
    DoSomething; // syntax error reported HERE but the real error is below.
    // more stuff here.
 end;

 procedure OllKorrect;  
 begin
        ThisLineIsFine();
        __VARIABLE_NOT_DEFINED__ := 1; // intentional error
 end

我希望有人以前见过这个。问题的要素可能包括:

该代码包含许多奇怪的编译器指令,例如 {$REALCOMPATIBILITY ON} 和 {$H-}/{$H+} 指令,代码中有数千个 {$H+}/{$H-} 指令。

其次,代码使用了很多 {$I INCLUDE} 指令,我怀疑包含文件可能会直接弄乱编译器的行号。

我不能肯定地说,但我怀疑所有这些旧的“让它像 DOS 的 turbo pascal 一样工作”编译器开关是其背后的原因。我想知道是否有人肯定对此有所了解。它只发生在代码中的某些地方,并且对于一个拥有超过 500 个单元的项目,其中一些达到 10K/20KLOC 的大小,这绝对是令人沮丧的。我能说的是,不仅有 {$I include.inc} 指令的单元会搞砸,而且许多包含大量 {$H-}/{$H+} 或 {$REALCOMPATIBILITY} 指令的单元也会没有这个问题。如果我能看到行为不端的单位有什么共同点,我就能弄清楚这一点。

更新:线路终止问题是有道理的。我运行了检测到问题的代码。修复代码已被注释掉,因为如果您取消注释它并删除所有源代码,那就是您的问题。它将非 unicode 文件加载到 unicode TStringList 中并将其保存回来。这在我的世界里没问题,因为它的所有版本都受控和备份。你的旅费可能会改变。

program linefeedsProject1;

{$APPTYPE CONSOLE}

uses
  IOUtils,
  Classes,
  Types,
  SysUtils;


  var
    broken,notBroken:Integer;

  function fix(filename:String):Boolean;
  var
    sl:TStringList;
  begin
    sl := TStringList.Create;
    try
    sl.LoadFromFile(filename);
    //TODO:Change file extensions.
    sl.SaveToFile(filename);
    finally
      sl.Free;
    end;
  end;

  function scan(filename:String):Boolean;
  var
  crFlag:Boolean;
  lfFlag:Boolean;
  missingCr:Integer;
  missingLf:Integer;
   f:TFileStream;
   buf:Array[0..1024] of AnsiChar;
   n:Integer;
   procedure scanChars;
   var
    i:Integer;
   begin
     for i := 0 to n-1 do
     begin
       if buf[i]=#13 then
       begin
          crFlag := true;
          lfFlag := false;
       end
       else if buf[i]=#10 then
       begin
           if not crFlag then
            inc(missingCr);
          lfFlag := true;
          crFlag := false;
       end
       else begin
         if (crFlag) then
          inc(missingLf);
         crFlag := false;
         lfFlag := false;
       end;
     end;
   end;
  begin
   result := false;
   crFlag := false;
   lfFlag := false;
   missingCr := 0;
   missingLf := 0;
    f := TFileStream.Create(filename, fmOpenRead);
    try
      while f.Position< f.Size do
      begin
        n := f.Read(buf[0],1024);
        scanChars;
      end;

     if (missingCr>0) or (missingLf>0) then
     begin
          WriteLn('  ', filename);
          Inc(broken);
          result := true;
     end
     else
     begin
        Inc(notBroken);
     end
    finally
      f.Free;
    end;

  end;
var
 files:TStringDynArray;
 afile:String;
 begin
  try
  broken := 0;
  notBroken := 0;
    files := TDirectory.GetFiles('C:\dev\abackupcopyofyoursourcecode',  '*.pas',
    TSearchOption.soTopDirectoryOnly );
    // tried TSearchOption.soAllDirectories and it exploded. not recommended.

    for afile in files do
    begin
       if scan(afile) then
       begin
           // fix(afile); // uncomment at your own risk and only on a backup copy of your code.
       end;

    end;


    WriteLn('Broken ', broken);
    WriteLn('not broken ',notBroken);

   // readln;

     except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

更新 2:如果你想要一个扫描仪/修复器来解决这个问题,你可以在这里下载我的(带有源代码)。 链接是 Google Drive。您可以从链接中查看源代码,但单击“文件”下拉菜单(Google Drive Web 用户界面的一部分),然后单击“下载”进行下载。

4

3 回答 3

23

我以前见过这样的事情,而 IME 通常是由于计算行号时的编译器错误。如果您在某些点有非标准换行符(不是 CRLF)——这可能会发生——IDE 将执行正确的换行符,但编译器不会将它们视为新行,因此之后的所有内容都会被丢弃。

当我遇到这样的文件时,我会在 EditPad 中打开它,将所有换行符转换为其他样式(Unix 或 Mac 样式),然后将所有换行符转换为 Windows 样式并保存。这确保了文件中的每一行都以 CRLF 结尾,并且在重建后,蓝点未正确排列的问题消失了。

于 2013-04-24T23:42:11.290 回答
10

这是由不匹配的行终止字符引起的常见问题。(行尾缺少 CR 或 LF 的代码。)这也可能是由于 .dcu 与在编辑器中打开的源文件不匹配造成的。

首先,最简单的解决方法是在常规文本编辑器(例如记事本)中打开源文件。做一个小改动(插入一个空行然后删除它),然后保存文件。记事本将修复行尾。

如果这不是问题,请在 IDE 的搜索路径中查找驱动器上可能存在的 .dcu(或 .pas)文件的额外副本。有时编译器看到的版本与编辑器中打开的版本不同。

于 2013-04-24T23:42:50.223 回答
0

如前几篇文章所述,它肯定与行尾相连。尝试将其编辑掉是非常困难的,因为 Embarcadero 编辑器试图发挥自己的魔力并保留当前部分的行尾(或者看起来如此),

解决方法:在 IDE 编辑器窗口中单击鼠标右键,选择“格式化源代码”(Ctrl-D)并接受。

这将修复所有行尾并消除问题(对我来说无论如何)。作为副产品,您将获得格式正确的源代码:-)

于 2019-04-02T10:48:23.620 回答