Delphi 2007 から XE2 への移植の副作用として、私が働いている大規模な Delphi コードベースで問題が発生しています。現在、次の奇妙な関連する問題が発生しています。
一部のユニットでのみ行番号がすべて台無しになっているため、デバッグ ビルドでもブレークポイントを設定したり、コードを 1 ステップ実行したりすることはできません。
意図的に 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-} ディレクティブなど、多くの奇妙なコンパイラ ディレクティブが含まれています。
第 2 に、コードは多くの {$I INCLUDE} ディレクティブを使用しており、インクルード ファイルがコンパイラの行番号付けを直接台無しにする可能性があると思われます。
確かなことは言えませんが、これらの古い「DOS のターボ パスカルのように動作させる」コンパイラ スイッチが原因であると思われます。誰かがこれについて確かなことを知っているかどうか知りたいです。これはコードの一部の場所でのみ発生し、500 ユニットを超えるプロジェクトでは、サイズが 10K/20KLOC に達するものもあり、間違いなくイライラします。私が言えることは、混乱するのは {$I include.inc} ディレクティブを持つユニットだけではなく、多くの {$H-}/{$H+} または {$REALCOMPATIBILITY} ディレクティブを含む多くのユニットが失敗するということです。この問題はありません。挙動不審なユニットの共通点がわかれば、それがわかる。
更新: 回線終端の問題は理にかなっています。問題を検出したこのコードを実行しました。修正コードがコメント アウトされているのは、コメントを外してすべてのソース コードが消去されてしまうと、それが問題になるからです。非ユニコード ファイルをユニコード 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ドライブです。リンクからソースコードを表示できますが、「ファイル」プルダウンメニュー(GoogleドライブのWebユーザーインターフェースの一部)をクリックし、「ダウンロード」をクリックしてダウンロードしてください。