Delphi XE2: отключено на 7-20 строк в отладчике и номера строк ошибок компилятора также отключены на ту же величину

У меня проблема с большой кодовой базой 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}, и я подозреваю, что включаемые файлы могут напрямую испортить нумерацию строк компилятора.

Я не могу сказать наверняка, но я подозреваю, что все эти старые «заставляют его работать как Turbo Pascal для DOS» переключатели компилятора являются причиной этого. Я хотел бы знать, знает ли кто-нибудь об этом наверняка. Это происходит только в некоторых местах кода, и с проектом, который имеет более 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) и затем нажмите «Скачать», чтобы загрузить его.

Ответы на вопрос(2)

Ваш ответ на вопрос