⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uparse.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 5 页
字号:



{Gets the list of files to parse only if they are used by other files. }
procedure TParserManager.GetLibList;
var       Paths     :TStringList; //list of paths of all found files
          i         :Integer;     //counter through the list
          Name      :String;      //an entry in the list
          FileInfo  :TSearchRec;  //data to get long name of files
begin
 Paths := TStringList.Create;     //create list of all found files
 try
   Paths.Sorted := True;
   Paths.Duplicates := dupIgnore;
   for i := 0 to FLibs.Count - 1 do  //for each entry in the list
    begin
     Name := FLibs[i];                 //get it
     //remove trailing PathSeparators
     if (Name <> '') and (Name[length(Name)] in ['\', '/']) then
      Delete(Name, length(Name), 1);

     if FileExists(Name)
{$IFDEF LINUX}
        and not DirectoryExists(Name)
{$ENDIF}
                                      then //it is a file?
      //add to the list of files
      Paths.add(ExtractShortPathName(ExpandFileName(Name)))
     else
      //search directory and add files to the list
      FindPasFiles(ExtractShortPathName(ExpandFileName(Name)), Paths,
                   Boolean(FLibs.Objects[i]));
    end;


   for i := 0 to Paths.Count - 1 do //for each found file
    if FindFirst(Paths[i],            //get its long name = internal name
{$IFNDEF LINUX}
  {$IFDEF conditionalexpressions}
    {$WARN SYMBOL_PLATFORM OFF}
  {$ENDIF}
                 faHidden
  {$IFDEF conditionalexpressions}
    {$WARN SYMBOL_PLATFORM ON}
  {$ENDIF}
{$ELSE}
                 0
{$ENDIF}
                 , FileInfo) = 0 then          //file found?
     try
       //is a simple unit (not a program etc.)?
       if LowerCase(ExtractFileExt(FileInfo.Name)) = '.pas' then
        begin
         //get base name of file; this should also be the internal name
         Name := ChangeFileExt(FileInfo.Name, '');            //in Delphi
         if FLibFileNames.IndexOf(Name) = -1 then //no file with that name yet?
          //add it (register it) to the lists
          FLibFilePaths.Insert(FLibFileNames.Add(Name), Paths[i])
         else
          //generate a warning message
          AddWarning('Libs: Several files with the name "' + Name +
                     '", ignoring file: ' + Paths[i], nil);
        end;
     finally
      FindClose(FileInfo);            //end the "search"
     end;
 finally
  Paths.Free;                     //free list of found files
 end;
end;





{Sorts the list of files depending on their usage, i.e. the files not using
 other files will be first and project files and packages will be last.
~param List     the list to sort }
procedure TParserManager.SortFileList(List: TFileList);

type      TAdded = (        //if files are already added
                    aNo,      //no, still have to
                    aYes,     //yes, already added
                    aAdding); //currently adding (detecting cross-references)


          //the list of files in original order
var       OrgList     :array of TPascalFile;
          //if the files are already added; same order as in ~[link OrgList]
          Added       :array of TAdded;
          //new sorted list of the files
          NewList     :array of TPascalFile;
          //insertion point of new files in NewList
          NewItem     :Integer;

 {Returns the index of the file in the original list.
 ~param AFile the file to search
 ~result the index of the file in the original list }
 function Find(AFile: TPascalFile): Integer;
 begin
  Result := Length(OrgList) - 1;
  while OrgList[Result] <> AFile do
   begin
    dec(Result);
    assert(Result >= 0);
   end;
 end;

 {Adds the file to the list after all used files have been added.
 ~param Index the index of the file to add in the original list }
 procedure Add(Index: Integer);
 var       List     :TStrings;    //used files (in interface)
           i        :Integer;     //counter though used units
           ind      :Integer;     //index of unit in original list
 begin
  assert(Added[Index] = aNo);
  Added[Index] := aAdding;        //file is being added at the moment

  //list of used files (in interface)
  List := OrgList[Index].UsedUnitList[fpInterface];
  for i := 0 to List.Count - 1 do //for each used unit
   begin
    assert(assigned(List.Objects[i]));
    ind := Find(TPascalFile(List.Objects[i]));  //get index of file

    if Added[ind] = aNo then                    //file not added yet?
     Add(ind)                                     //add it
    else
     if (Added[ind] = aAdding) then             //cross-referencing of units?
      AddWarning('Cross-using of units ' +
                 TPascalFile(List.Objects[i]).InternalFileName + ' and ' +
                 OrgList[Index].InternalFileName + '!', nil);
   end;

  Added[Index] := aYes;           //file is now added
  NewList[NewItem] := OrgList[Index];
  inc(NewItem);                   //move insertion point in new list
 end;

var       Count       :Integer;          //number of files in list
          i           :Integer;          //counter through the list
begin
 Count := List.Count;                    //get number of files
 if Count > 1 then                       //need to be sorted?
  begin
   SetLength(OrgList, Count);            //create original list to sort
   for i := 0 to Count - 1 do            //fill original list
    OrgList[i] := List[i];

   SetLength(Added, Count);
   FillChar(Added[0], Count * SizeOf(Added[0]), aNo); //no file added so far

   SetLength(NewList, Count);            //create new sorted list
   NewItem := 0;                         //NewList is empty so far
{$IFOPT C+}
   //no file added so far
   FillChar(NewList[0], Count * SizeOf(NewList[0]), Integer(nil));
{$ENDIF}


   //now sort the files by their usage of each other
   for i := 0 to Count - 1 do           //for each file in original list
    begin
     assert(Added[i] in [aNo, aYes]);
     if Added[i] = aNo then               //if not already added
      Add(i);                                //add it
    end;

   assert(NewItem = Count);             //same number of files added
{$IFOPT C+}
   for i := 0 to Count - 1 do           //check:
    assert(Added[i] = aYes);              //all files have been added
{$ENDIF}


   List.RemoveAll(False);               //clear list
   for i := 0 to Count - 1 do           //for each (now sorted) file
    begin
     assert(assigned(NewList[i]));
     assert(not List.IsIn(NewList[i]));
     List.AddFileToThisList(NewList[i]);  //add it again to list
    end;

  end; //if Count > 1
end;









{Generates a warning-message if the internal (pascal) name of the file differs
 from the name of the file in the file-system.
~param TheFile the file, whose name should be tested, if its names differ }
procedure TParserManager.TestFileName(TheFile: TPascalFile);
var       SearchRec   :TSearchRec;   //to obtain the long name of the file
begin
 //get long name of the file
 if FindFirst(TheFile.FilePath, faAnyFile, SearchRec) = 0 then
  try
    if LowerCase(ChangeFileExt(SearchRec.Name, '')) <>   //are they different?
       LowerCase(TheFile.InternalFileName) then
     AddWarning(Format('Name of file "%s" differs: %s',    //add a warning
                       [TheFile.InternalFileName, SearchRec.Name]), nil);
  finally
   FindClose(SearchRec);
  end;
end;


{$IFOPT C+}

{Tests the inheritance-hierarchy-linking between record-like types; this is for
 debugging purposes only.
~param Kind the kind of record-like types to check
~param List list of all files that contain all record-like types
~result if the linking is correct }
function TParserManager.TestRecordLikeLinks(Kind: TRecordKind;
                                            List: TFileList): Boolean;

 {Deletes all inherited classes (children) of the given class from the list.
  All children of the children and so on will also be deleted recursively.
 ~param Parent   the class, whose children should be removed from the list
 ~param Children the list in which to search and remove the children }
 procedure DeleteAllChildren(Parent: TIdentifier; Children: TIdentifierList);
 var       Ident            :TIdentifier;  //a record-like identifier
           i                :Integer;      //counter through the list
           Count            :Integer;      //number of identifiers left
 begin
  i := Children.Count - 1;            //run through the whole list
  while i >= 0 do
   begin
    Ident := Children[i];               //get an identifier
    if TRecordType(Ident).GetParent = Parent then //it's a child?
     begin
      Children.Remove(i, False);          //delete this child
      DeleteAllChildren(Ident, Children); //delete all children of it
      dec(i);                             //and next identifier

      Count := Children.Count - 1;        //test, if sub-children have been
      if Count < i then                   //deleted and end of list moved
       i := Count;                          //make sure, it's a valid index
     end
    else
     dec(i);                              //next identifier
   end;
 end;

var       AllList          :TIdentifierList; //list of all identifiers
          ParentsList      :TIdentifierList; //list of all without a parent
          i, j             :Integer;         //general counters
          FileD            :TPascalFile;     //each file
          Ident            :TIdentifier;     //each identifier
          Count            :Integer;         //number of identifiers in AllList
begin
 AllList := TIdentifierList.Create;        //create list for all identifiers
 try
   //search all identifiers of that kind of record-like types
   for i := 0 to List.Count - 1 do         //for each file
    begin
     FileD := List[i];                       //get the file
     for j := 0 to FileD.Idents.Count - 1 do //for each identifier
      begin
       Ident := FileD.Idents[j];               //get the identifier
       //if it is a record-like type of thet kind
       if (Ident is TRecordType) and (TRecordType(Ident).Kind = Kind) then
        AllList.AddIdent(Ident);                 //add it to the list
      end;
    end;

   Count := AllList.Count;                 //get number of found identifiers
   if Count > 0 then                       //any identifiers there?
    begin
     ParentsList := TIdentifierList.Create;  //create list for all parents
     try
       for i := Count - 1 downto 0 do        //for each identifier
        begin
         Ident := AllList[i];                  //get it
         assert(Ident is TRecordType);
         //if it has no parent it is a top-level parent
         if not assigned(TRecordType(Ident).GetParent()) then
          begin
           ParentsList.AddIdent(Ident);       //add it to the list of parents
           AllList.RemoveIdent(Ident, False); //& remove it from the other list
          end;
        end;

       //for each parent remove all known children (and their children ...)
       for i := 0 to ParentsList.Count - 1 do
        DeleteAllChildren(ParentsList[i], AllList);

     finally
      ParentsList.RemoveAll(False);          //free the list of parents
      ParentsList.Free;
     end;

     Count := AllList.Count;                 //number of remaining identifiers
    end; //if Count > 0


    //all identifiers have to be linked or be a parent; no remaining allowed
    Result := Count = 0;
 finally
  AllList.RemoveAll(False);                //free the list of identifiers
  AllList.Free;
 end;
end;

{$ENDIF}









































{Parses the specified new files. }
procedure TParserManager.ParseNewFiles;

 {Splits the list of files and directories into two. All files will be added
  to Files, all directories to Dir.
 ~param List  list of files and directories to add to the others lists
 ~param Files list to add the files of List to
 ~param Dirs  list to add the directories of List to }
 procedure SplitLists(List, Files, Dirs: TStrings);
 var       i         :Integer;     //counter through the list
           Name      :String;      //an entry in the list
 begin
  for i := 0 to List.Count - 1 do  //for each entry in the list
   begin
    Name := List[i];               //get it
    //remove trailing PathSeparators
    if (Name <> '') and (Name[length(Name)] in ['\', '/']) then
     Delete(Name, length(Name), 1);

    if FileExists(Name)
{$IFDEF LINUX}
        and not DirectoryExists(Name)
{$ENDIF}
    then         //is it a file?
     Files.AddObject(ExtractShortPathName(ExpandFileName(Name)),
                     List.Objects[i])         //add to list of files
    else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -