Delphi XE2: Off por 7-20 linhas no depurador e números de linha de erro do compilador também desligado pela mesma quantidade
Eu estou tendo um problema com um grande código Delphi onde eu trabalho onde como um efeito colateral de portar do Delphi 2007 para o XE2, agora encontramos os seguintes problemas estranhos, relacionados:
Você não pode definir pontos de interrupção ou um único passo através do código, mesmo na compilação de depuração, porque a numeração de linhas é toda confusa, apenas em algumas das unidades.
Introduzir um erro de sintaxe deliberadamente na linha 2010 fará com que o cursor se concentre na linha 2020, mais ou menos 3 ou 4 linhas, algo assim:
.
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
Espero que alguém tenha visto isso antes. Os elementos do problema podem incluir:
O código contém muitas diretivas de compilador estranhas como {$ REALCOMPATIBILITY ON} e {$ H -} / {$ H +} diretivas, milhares de diretivas {$ H +} / {$ H-} no código.
Em segundo lugar, o código usa muitas diretivas {$ I INCLUDE}, e eu suspeito que incluir arquivos pode atrapalhar diretamente a numeração de linhas do compilador.
Eu sou incapaz de dizer com certeza, mas eu suspeito que todos esses antigos "fazer funcionar como turbo pascal para DOS" interruptores de compilador são a razão por trás disso. Eu gostaria de saber se alguém sabe alguma coisa sobre isso com certeza. Isso só acontece em alguns lugares no código, e com um projeto que tem mais de 500 unidades, algumas das quais atingem 10K / 20KLOC de tamanho, é definitivamente frustrante. O que eu posso dizer é que não são apenas as unidades que têm as diretivas {$ I include.inc} que fazem bagunça, e que muitas unidades que contêm muitas diretivas de {$ H -} / {$ H +} ou {$ REALCOMPATIBILITY} não tem esse problema. Se eu pudesse ver o que as unidades que se comportam mal têm em comum, eu poderia descobrir isso.
Atualização: A questão da terminação de linha faz sentido. Eu corri este código que detectou problemas. O código de correção está comentado porque, se você descompactá-lo e apagar todo o código-fonte, o problema é seu. Ele está carregando um arquivo não-unicode em um TStringList unicode e salvando-o novamente. Tudo bem no meu mundo porque é tudo versão controlada e backup. Sua milhagem pode variar.
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.
Atualização 2: Se você quiser um scanner / fixador para este problema, você pode baixar o meu (com a fonte) aqui. Link é o Google Drive. Você pode ver o código-fonte do link, mas clique no menu suspenso "Arquivo" (parte da interface de usuário da web do Google Drive) e clique em "Download" para baixá-lo.