spiegel-keyman/common/windows/delphi/tools/sentrytool/Keyman.System.SentryTool.DelphiSearchFile.pas
2022-06-10 11:35:34 +10:00

113 lines
2.4 KiB
ObjectPascal

unit Keyman.System.SentryTool.DelphiSearchFile;
interface
uses
System.Classes,
System.SysUtils;
type
TDelphiSearchFile = class
private
FFiles: TStringList;
FPaths: TStringList;
FPathIndex: Integer;
procedure ParseDPR(const AProjectFile: string);
procedure SearchPath(const Path: string);
public
constructor Create(const AProjectFile, ASearchPath: string);
destructor Destroy; override;
function FindFile(const UnitName: string): string;
property Files: TStringList read FFiles;
end;
implementation
uses
System.RegularExpressions;
{ TDelphiSearchFile }
constructor TDelphiSearchFile.Create(const AProjectFile, ASearchPath: string);
begin
FFiles := TStringList.Create;
FPaths := TStringList.Create;
FPaths.Delimiter := ';';
FPaths.DelimitedText := ASearchPath;
if AProjectFile <> '' then
ParseDPR(AProjectFile);
end;
function ExpandRelativePath(const RootPath, Filename: string): string;
begin
if not IsRelativePath(Filename) then
Exit(Filename);
Result := ExpandFileName(RootPath + Filename);
end;
procedure TDelphiSearchFile.ParseDPR(const AProjectFile: string);
var
i: Integer;
dpr: TStringList;
re: TRegEx;
m: TMatch;
RootPath: string;
const
pathMatch = '\s+([a-z_][a-z0-9_.]+)\s+in\s+''([^'']+)''';
begin
RootPath := ExtractFilePath(AProjectFile);
re := TRegEx.Create(pathMatch, [roIgnoreCase]);
dpr := TStringList.Create;
try
dpr.LoadFromFile(AProjectFile);
for i := 0 to dpr.Count - 1 do
begin
m := re.Match(dpr[i]);
if m.Success then
FFiles.AddPair(m.Groups[1].Value, ExpandRelativePath(RootPath, m.Groups[2].Value));
end;
finally
dpr.Free;
end;
end;
destructor TDelphiSearchFile.Destroy;
begin
FreeAndNil(FFiles);
FreeAndNil(FPaths);
inherited;
end;
procedure TDelphiSearchFile.SearchPath(const Path: string);
var
f: TSearchRec;
begin
if FindFirst(IncludeTrailingPathDelimiter(Path) + '*.pas', 0, f) = 0 then
begin
repeat
FFiles.AddPair(ChangeFileExt(f.Name, ''), IncludeTrailingPathDelimiter(Path) + f.Name);
until FindNext(f) <> 0;
FindClose(f);
end;
end;
function TDelphiSearchFile.FindFile(const UnitName: string): string;
begin
Result := FFiles.Values[UnitName];
if Result <> '' then
Exit;
while FPathIndex < FPaths.Count - 1 do
begin
SearchPath(FPaths[FPathIndex]);
Inc(FPathIndex);
Result := FFiles.Values[UnitName];
if Result <> '' then
Exit;
end;
end;
end.