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

📄 udocumentdoc.pas

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














    {Generates an index about all identifiers and files beginning with the
     character.
    ~param List       the list of all identifiers and files to generate the
                      index of
    ~param EntryIndex the index of the first entry with the letter
    ~param Index      the character to generate the index for
    ~result the first entry not in the index (i.e. EntryIndex for the next
            letter) }
    function DoGenerateIndex(List: TIdentifierFileList; EntryIndex: Integer;
                             Index: Char): Integer; virtual; abstract;

    //Generates an index about all identifiers and files.
    procedure GenerateIndex;






    property DocumentDocMessagesID: TMessageID read FDocumentDocMessagesID;
    property GenerateFileTreeFiles: Boolean read FGenerateFileTreeFiles;
    property GenerateClassesTreeFiles: Boolean read FGenerateClassesTreeFiles;
    property GenerateXFigFiles: Boolean read FGenerateXFigFiles;
    property GenerateWMFFiles: Boolean read FGenerateWMFFiles;
  public
    //Creates the generator object.
    constructor Create; override;
    //Destroys the generator object.
    destructor Destroy; override;


    //Will be called for all names of identifier-type identifiers.
    function TypeIdentifierText(Ident: TIdentifier): String; override;
    //Will be called for all expressions.
    function ExprText(const ExprStr: String;
                      SourceIdent: TIdentifier): String; override;
    //Will be called for read- and write-attributes of properties.
    function PropertyReadWrite(const ReadWrite: String; Prop: TProperty;
                               SourceIdent: TIdentifier): String; override;
    //Will be called for implements-attribute of properties.
    function PropertyImplements(Prop: TProperty;
                                SourceIdent: TIdentifier): String; override;
    //Will be called for a reference on a method of an implemented interface.
    function InterfaceMethod(const TheName: String; MethodOf: TRecordType;
                             SourceIdent: TIdentifier): String; override;
    //Will be called for a reference on a method.
    function MethodName(const Name: String; MethodOf: TRecordType;
                        SourceIdent: TIdentifier): String; override;



    //Returns the number of available options in generators of this class.
    class function GetOptionCount: Cardinal; override;
    //Gets a description of an option.
    class procedure GetOptionDescription(Index: Cardinal;
                                         var Desc: TOptionDescription);
                                                                      override;
    //Gets the value of an option.
    function GetOption(Index: Cardinal): TOptionValue; override;
    //Sets the value of an option.
    procedure SetOption(Index: Cardinal; const Value: TOptionValue); override;



    //Handles text by encoding special characters of the format.
    function HandleRawText(const Text: String): String; virtual;


    //Returns the current and for the current format escaped text.
    function Localize(Text: TDocumentationTexts): String;
    //Returns the current and for the current format escaped text with the
    //parameters.
    function LocalizeFmt(Text: TDocumentationTexts;
                         const Args: array of const): String;




    //Returns the unique ID of an identifier to be used in the documentation.
    function GetURIOf(Ident: TIdentifier;
                      TheFile: TPascalFile = nil): String; virtual;

  end;






      //plural names/texts of the kinds of record-like types
const Plurals: array[TRecordKind] of TDocumentationTexts =
               (dtRecordsHeader,
                dtObjectsHeader, dtClassesHeader,
                dtInterfacesHeader, dtDispInterfacesHeader);




implementation


uses Windows, SysUtils,
     General,
     UVectorGraphics,
     UTokenParser;







   { * * *  ***  * * *  ***   TDocumentDoc   ***  * * *  ***  * * *  }



    //the descriptions of messages that can be added in the class
    //~[link TDocumentDoc]
var DocumentDocMessageDescriptions: TMessageDescriptions = nil;




{Creates the generator object and the list of messages. }
constructor TDocumentDoc.Create;
begin
 inherited Create;                  //create object

 //register messages of this class
 FDocumentDocMessagesID := RegisterMessages(DocumentDocMessageDescriptions);


 FGenerateFileTreeFiles := True;    //generate all possible files
 FGenerateClassesTreeFiles := True;
 FGenerateXFigFiles := True;
{$IFNDEF LINUX}
 FGenerateWMFFiles := True;
{$ENDIF}

 FFileTreeFileBaseName := 'UnitUse'; //set names of the files
 FClassTreeFileBaseName[rkRecord] := DescFilePreFix[rkRecord] + 'List';
 FClassTreeFileBaseName[rkObject] := DescFilePreFix[rkObject] + 'List';
 FClassTreeFileBaseName[rkClass] := DescFilePreFix[rkClass] + 'List';
 FClassTreeFileBaseName[rkInterface] := DescFilePreFix[rkInterface] + 'List';
 FClassTreeFileBaseName[rkDispInterface] := DescFilePreFix[rkDispInterface] +
                                            'List';
end;


{Destroys the generator object. }
destructor TDocumentDoc.Destroy;
begin
 //unregister messages of this class
 UnRegisterMessages(FDocumentDocMessagesID);

 inherited Destroy;                 //free the object
end;












{Will be called for all names of identifier-type identifiers. This means it
 will be called by the class ~[linkClass TIdentType] for any known type
 identifier. A link on the identifier is returned.
~param Ident a type identifier to that a link should be generated
~result a link on the identifier }
function TDocumentDoc.TypeIdentifierText(Ident: TIdentifier): String;
begin
 if DoNotDocumentIdentifier(Ident) then       //not documented?
  //just return the text of it
  Result := IdentifierText(Ident.InFile.InternalFileName + '.' +
                           Ident.Name)
 else
  //create and return the link
  Result := GetIdentNameLink(Ident);
end;

{Will be called for texts of expressions, for instance like used as the index
 of an array or the value of a constant. The text should be parsed and
 identifiers should be underlaid with a link to their declaration if possible.
~param ExprStr     the text of the expression
~param SourceIdent the identifier from that the description that included this
                   expression has been requested
~result the formatted expression with links
~todo reimplement, I'm not really happy with it, but it does work in most
      cases
~todo FileGiven has to check for Unit-Aliases! }
function TDocumentDoc.ExprText(const ExprStr: String;
                               SourceIdent: TIdentifier): String;
var      SourceRec   :TRecordType;       //current record-like type
         State       :(                  //general state in the expression
                       sNo,              //after operator or similar character
                       sIdent,           //after an identifier (or dot)
                       sBrace,           //after an opening brace or bracket
                       sString);         //after a string

         Parser      :TTokenParser;      //parser of the expression
         Token       :String;            //a token in the expression
         Next        :String;            //the next token after an identifier
         FileGiven   :Boolean;           //file of identifier was given

         Position    :TPosition;         //position to start search
         Ident       :TIdentifier;       //identifiers in the expression
         dot         :Integer;           //index of a "." in the token

         //file of record-like type to search identifiers in
         RecIdent    :TRecordType;       //used record-like type
         IdentName   :String;            //a used member of a record-like type
begin
 assert(assigned(SourceIdent));
 assert(assigned(SourceIdent.InFile));

 Result := '';                           //no expression parsed so far

 if SourceIdent is TRecordType then       //get current record-like type
  SourceRec := TRecordType(SourceIdent)     //is is one, use it
 else
  SourceRec := SourceIdent.MemberOf;        //use its record-like type

 if assigned(SourceIdent) then           //get position to search from
  begin
   if SourceIdent is TRecordType then      //if it is a record-like type
    Position := SourceIdent.Position         //use its position
   else
    Position := SourceIdent.ForwardDefPos;   //use always the first declaration
  end
 else
  begin
   Position.Row := -1;                     //search from the beginning
   Position.Column := 1;
  end;


 Parser := TTokenParser.Create;          //create tokenizer
 try
   Parser.PascalDialect := SourceIdent.InFile.PascalDialect;

   Parser.ParseString(ExprStr);          //parse expression text

   State := sNo;                         //begin without a special state
   while Parser.GetIdentWithPointsToken(Token) do //parse each token
    begin                                  //is an identifier?
     if (Token <> '') and (Token[1] in StartIdentifierChars) then
      begin
       State := sIdent;                      //next token is after identifier
       if LowerCase(Token) = 'nil' then      //is nil?
        Result := Result + ReservedWord(Token) //just add to the expression
       else
        begin
         Result := Result + ' ';               //add a space before it

         Parser.PushPosition;
         Parser.GetToken(Next);                //preview the following token
         Parser.PopPosition;
         //not initialization of a record, i.e. a field of the record?
         if Next <> ':' then
          begin
           dot := pos('.', Token);

           if assigned(SourceRec) then            //is in a record-like type?
            begin
             if dot = 0 then
              dot := length(Token) + 1;

             //search the identifier in it by this name
             Ident := SourceRec.IdentList.GetIdentByName(copy(Token, 1,
                                                              dot - 1));
             if assigned(Ident) then
              begin
               if DoNotDocumentIdentifier(Ident) then //not documented?
                //just add the text
                Result := Result + IdentifierText(copy(Token, 1, dot - 1))
               else
                //add link to it
                Result := Result + GetRecordFieldNameLink(Ident);
               Delete(Token, 1, dot);                 //remove identifier
              end
             else
              dot := pos('.', Token);
            end
           else
            Ident := nil;                           //not found so far

           if not assigned(Ident) then
            begin
             //search the identifier by this name (globally)
             Ident := FindIdentifier(Token, SourceIdent.InFile, Position);

             if assigned(Ident) then               //the identifier found?
              begin
               FileGiven := (dot <> 0) and           //file name given?
                            (length(Ident.InFile.InternalFileName) =
                             dot - 1) and
                            (CompareText(Ident.InFile.InternalFileName,
                                         copy(Token, 1, dot - 1)) = 0);
               if dot = 0 then          //get full length of identifier or file
                dot := length(Token) + 1;


               if DoNotDocumentIdentifier(Ident) then
                begin
                 //add text of identifier
                 Result := Result + IdentifierText(copy(Token, 1, dot - 1));
                 if FileGiven then
                  begin
                   Delete(Token, 1, dot);                //delete file
                   dot := pos('.', Token);               //get identifier text
                   if dot = 0 then
                    dot := length(Token);
                   //add real text of identifier
                   Result := Result + IdentifierText(copy(Token, 1, dot - 1));
                   FileGiven := False;             //file text already removed
                  end;
                end
               else
                //get link to identifier
                Result := Result + GetIdentNameLink(Ident, FileGiven);

               if FileGiven then                     //if file given
                begin
                 Delete(Token, 1, dot);                //delete it

⌨️ 快捷键说明

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