📄 uparse.pas
字号:
files and add their parsers to the list. The actual reading and parsing of the
files of pascal code is done in ~[link ParseFile]. The files will only be read
and the head (kind of file and the first uses-clause) will be parsed.
Further passing must be done by calling the different methods of the parsers
as done in ~[link DoParseFiles].
~param Files the list of files to parse; if the objects-Property is not nil
(that means Boolean(objects[i]) = True) and it is a
project-file all used units will be parsed, too
~param Dirs the list of directories whose files will be parsed;
must be the absolute short names; that's means they're unique;
if the objects-Property is not nil all subdirectories will also
be parsed
~param NotFiles the list of files which will not be parsed if in Dirs or used
~param NotDirs the list of directories whose files will not be parsed;
must be the absolute short names; that's means they're unique;
if the objects-Property is not nil all subdirectories will also
not be parsed }
procedure TParserManager.ParseList(Files, Dirs, NotFiles, NotDirs: TStrings);
var i, j :Integer; //general counters
Count :Integer; //number of items in the lists
//length of directory-path (for relative path)
len :Integer;
List :TStringList; //list for found files in directories
begin
Count := Files.Count;
if assigned(FProgress) then
begin
FProgress.SetWorkText('Parsing single Files...');
FProgress.SetMaximum(Count);
end;
i := 0; //for each file to parse
while (i < Count) and (not assigned(FProgress) or not FProgress.ShouldAbort) do
begin
if assigned(FProgress) then
begin
FProgress.SetProgressText(Format('Parsing File %d of %d', [i + 1, Count]));
FProgress.SetProcessText(Files[i]);
end;
//parse the file
ParseFile(Files[i], Boolean(Files.Objects[i]), Dirs, NotFiles, NotDirs);
if assigned(FProgress) then
FProgress.StepProgress;
inc(i);
end;
if not assigned(FProgress) or not FProgress.ShouldAbort then
begin
List := TStringList.Create; //create list for the files in the directories
try
List.Sorted := True;
List.Duplicates := dupAccept;
Count := Dirs.Count;
if assigned(FProgress) then
begin
FProgress.SetWorkText('Parsing Directories...');
FProgress.SetMaximum(Count * 5);
end;
j := 0; //for each directory
while (j < Count) and
(not assigned(FProgress) or not FProgress.ShouldAbort) do
begin
List.Clear; //search all files in the directory
FindPasFiles(ExpandFileName(Dirs[j]), List, Boolean(Dirs.Objects[j]));
//save length of absolute path (to delete it when showing the name)
len := length(ExpandFileName(Dirs[j])) + 2;
if assigned(FProgress) then
FProgress.SetProgressText(Format('Found %d Files in %s',
[List.Count, Dirs[j]]));
i := 0;
while (i < List.Count) and //for all found pascal files
(not assigned(FProgress) or not FProgress.ShouldAbort) do
begin
if assigned(FProgress) then //show relative path
FProgress.SetProcessText(copy(List[i], len,
high(length(List[i]))));
//if it should be parsed
if FileDirAllowed(List[i], Dirs, NotDirs) then
//parse the file
ParseFile(List[i], False, Dirs, NotFiles, NotDirs);
if assigned(FProgress) then
FProgress.StepProgress;
inc(i);
end; //for each file in the directory
inc(j);
end; //for each directory
finally
List.Free;
end;
end; //if not FProgress.ShouldAbort
end;
{Preparses a file or files in a directory.
~param FileName the name of the file or directory to parse
~param IsDir if FileName points to a directory
~param Recursive if all used files/files in sub-directories should also be
parsed }
procedure TParserManager.PreparseOneFile(const FileName: String;
IsDir, Recursive: Boolean);
var Empty :TStringList; //an empty list
i :Integer; //general counter
//length of directory-path (for relative path)
len :Integer;
List :TStringList; //list for found files in directories
begin
Empty := TStringList.Create; //create empty list
try
if not IsDir then
begin
if assigned(FProgress) then
begin
FProgress.SetWorkText('Parsing single File...');
FProgress.SetMaximum(1);
FProgress.SetProgressText('Parsing File 1 of 1');
FProgress.SetProcessText(FileName);
end;
ParseFile(FileName, Recursive, Empty, Empty, Empty); //parse the file
if assigned(FProgress) then
FProgress.StepProgress;
end
else
begin
List := TStringList.Create; //create list for the files in the directories
try
List.Sorted := True;
List.Duplicates := dupAccept;
if assigned(FProgress) then
begin
FProgress.SetWorkText('Parsing Directory...');
FProgress.SetMaximum(1);
end;
//search all files in the directory
FindPasFiles(ExpandFileName(FileName), List, Recursive);
//save length of absolute path (to delete it when showing the name)
if assigned(FProgress) then
begin
FProgress.SetMaximum(List.Count);
FProgress.SetProgressText(Format('Found %d Files', [List.Count]));
end;
len := length(ExpandFileName(FileName)) + 2;
i := 0;
while (i < List.Count) and //for all found pascal files
(not assigned(FProgress) or not FProgress.ShouldAbort) do
begin
if assigned(FProgress) then //show relative path
FProgress.SetProcessText(copy(List[i], len, high(length(List[i]))));
ParseFile(List[i], False, Empty, Empty, Empty); //parse the file
if assigned(FProgress) then
FProgress.StepProgress;
inc(i);
end; //for each file in the directory
finally
List.Free; //free list of files in the directory
end;
end;
finally
Empty.Free; //free empty list
end;
end;
{Encapsulates the parsing of several pascal-files. This function provides a
simple way to call the various functions and methods of different classes in
the right sequence.
~result if the parsing wasn't aborted by the user }
function TParserManager.ParseFiles: Boolean;
var AProgress :TProgressAdapter; //a dummy-object if none given
begin
Result := True; //so far not aborted
if not assigned(FProgress) then //no FProgress-object given?
begin
AProgress := TProgressAdapter.Create; //create a dummy object
FProgress := AProgress; //and use it
end
else
AProgress := nil; //nothing to free
try
try
//do the actual parsing of the files
DoParseFiles;
except
on E: EAbortProgress do //if parsing has been aborted
Result := False; //simply return false
else
raise;
end;
finally
if assigned(AProgress) then //if created
begin
FProgress := nil;
AProgress.Free; //free dummy-object
end;
end;
end;
{Handles a message from a parser.
~param Information the information about the message
~param Parser the parser generating the message }
procedure TParserManager.HandleMessage(const Information:
TParseMessageInformation;
Parser: TFileParser);
begin
if assigned(FOnMessage) then //handler for message available?
FOnMessage(Information, Self) //handle it there
else
if IsDebuggerPresent then //application is being debugged?
asm int 3 end; //stop it (by a hard break point)
end;
{Handles a warning message from a parser.
~param Message the warning message
~param Parser the parser generating the message or nil }
procedure TParserManager.AddWarning(const Message: String;
Parser: TFileParser);
//information to add the warning messsage
var Information :TParseMessageInformation;
begin
//put/wrap the message in the structure for the information about it
Information.MessageKind := pmkWarning;
Information.MessageType := etParameters;
Information.TheFile := nil;
Information.ErrorPosition := UndefPosition;
Information.EffectiveFile := nil;
Information.EffectiveErrorPosition := UndefPosition;
Information.Message := Message;
HandleMessage(Information, Parser); //handle the warning message
end;
{Handles a hint message.
~param Message the hint message }
procedure TParserManager.AddHint(const Message: String);
//information to add the hint
var Information :TParseMessageInformation;
begin
//put/wrap the message in the structure for the information about it
Information.MessageKind := pmkHint;
Information.MessageType := etNone;
Information.TheFile := nil;
Information.ErrorPosition := UndefPosition;
Information.EffectiveFile := nil;
Information.EffectiveErrorPosition := UndefPosition;
Information.Message := Message;
HandleMessage(Information, nil); //handle the hint
end;
{Called, if an unknown unit is used by a file.
~param Sender the sender of the event; the parser of the file that uses the
unknown unit
~param UnitName the name of the unit
~result the parser of the unit if it could be parsed or nil }
function TParserManager.UnknownUnit(Sender: TFileParser;
const UnitName: String): TPascalFile;
//index of the file in the files to parse if used
var Index :Integer;
Empty :TStringList; //an empty list
begin
Result := nil;
Index := LibFileNames.IndexOf(UnitName); //search if it is a lib file
if Index <> -1 then //is a lib file?
begin
Empty := TStringList.Create;
try
ParseFile(LibFilePaths[Index], False, Empty, Empty, Empty); //parse it
finally
Empty.Free;
end;
Result := FList[0]; //get the newest parsed file
assert(Result.FilePath = LibFilePaths[Index]);
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -