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

📄 unamespaces.pas

📁 DelphiDoc is a program for automatic generation of documentation on a Delphi-Project. At the momen
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{  JADD - Just Another DelphiDoc: Documentation from Delphi Source Code

Copyright (C) 2003-2008   Gerold Veith

This file is part of JADD - Just Another DelphiDoc.

DelphiDoc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as
published by the Free Software Foundation.

DelphiDoc is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
}


unit UNameSpaces;

{Contains several classes to define namespaces to be used in
 ~[linkUnit UCodeParser].~[linkClass TCodeParser]. Namespaces are used to
 define where to search for identifiers (declaration) when one is encountered
 (used). They are chained, that means, if it is not found in the current
 namespace the previous will be searched and so on, until found or the end of
 the chain has been reached.~[br]
 Don't confuse these namespaces with the ones used in .NET and Delphi 8+ for
 "units" (or classes).
}

interface

uses UBaseIdents, UExtIdents,
     UFileParser;


type


   { * * *  ***  * * *  ***   TNameSpace   ***  * * *  ***  * * *  }

  {The (abstract) base-class of all namespaces. Namespaces are used to
   define where to search for identifiers (declaration) when one is encountered
   (used). They are chained, that means, if it is not found in the current
   namespace the previous will be searched and so on, until found or the end of
   the chain has been reached.~[br]
   Don't confuse these namespaces with the ones used in .NET and Delphi 8+ for
   "units" (or classes). }
  TNameSpace = class
  private
  protected
    //the previous namespace to be searched, if identifier is not found in this
    FPreNameSpace: TNameSpace;
  public
    //Searches the identifier in this namespace and the previous ones.
    function FindIdent(const IdentName: String;
                       var SourceFile: TPascalFile): TIdentifier; virtual;

    property PreNameSpace: TNameSpace read FPreNameSpace write FPreNameSpace;
  end;




   { * * *  ***  * * *  ***   TThisFileNameSpace   ***  * * *  ***  * * *  }

  {The namespace of the current file. All used units will be searched, too.
   This namespace must be the first namespace, i.e. PreNameSpace not
   assigned. }
  TThisFileNameSpace = class(TNameSpace)
  private
    //this file/the file to be searched for identifiers
    FThisFile: TPascalFile;

    //the parser of the file, used to count the number of references of each
    //used unit
    //~feature maybe move the reference count into the ~[link TPascalFile file]
    //         itself
    FFileParser: TFileParser;
  public
    //Creates the namespace object and assigns the file to be searched.
    constructor Create(ThisFile: TPascalFile; FileParser: TFileParser);

    //Searches the identifier in the file and the used units.
    function FindIdent(const IdentName: String;
                       var SourceFile: TPascalFile): TIdentifier; override;

    property ThisFile: TPascalFile read FThisFile;
  end;




   { * * *  ***  * * *  ***   TWithNameSpace   ***  * * *  ***  * * *  }

  {The namespace of a with-statement, also the base-class for
   function/methods-namespaces. The record-like type/identifier and its
   ancestors will be searched for identifiers. }
  TWithNameSpace = class(TNameSpace)
  protected
    //the record-like identifier to be searched for identifiers
    FRecIdent: TRecordType;
    //the current file with the with-statement
    FCurrentFile: TPascalFile;

    //if the identifier is used in the same file as ~[link FRecIdent] is
    //declared or in the class FRecIdent (i.e. if protected members should be
    //returned)
    FIsOrHasInherited: Boolean;
  public
    //Creates the namespace object and assigns the record-like identifier to
    //be searched.
    constructor Create(RecIdent: TRecordType; CurrentFile: TPascalFile;
                       IsOrHasInherited: Boolean);

    //Searches the identifier in the record-like identifier.
    function FindIdent(const IdentName: String;
                       var SourceFile: TPascalFile): TIdentifier; override;
  end;




   { * * *  ***  * * *  ***   TLocalFuncNameSpace   ***  * * *  ***  * * *  }

  {The namespace of a function. All local identifiers (variables, constants,
   types, etc.), the function-identifier itself, the special names "Self" and
   "Result" and the parameters will be searched for identifiers. If it is a
   method also the class (and ancestors) will be searched. }
  TLocalFuncNameSpace = class(TWithNameSpace)
  private
    //all local identifiers
    FLocalIdents: TIdentifierList;
    //the identifier of the function itself
    FFuncIdent: TFunction;
    //identifier for "Self" and/or for the function (Result internally)
    FSpecialList: TIdentifierList;
    //if the identifier "Result" is the result of the function ($X+ ?)
    FResultIdent: Boolean;

    //all identifiers of except-on-clauses are saved within here
    //~[code on E: Exception do] ... <-- the E's
    FSubLocalIdents: TIdentifierList;
    //all in the function used global identifiers are added to this list
    FUsedIdents: TIdentifierList;
  public
    //Creates the namespace object and assigns the function-identifier.
    constructor Create(FuncIdent: TFunction);
    //Destroys the namespace object.
    destructor Destroy; override;


    //Searches the identifier in the (local) identifiers of the function.
    function FindIdent(const IdentName: String;
                       var SourceFile: TPascalFile): TIdentifier; override;


    //Adds an identifier that is defined inside the function.
    procedure AddSubLocalIdent(Ident: TIdentifier);

    //Adds the identifier to the list of in this function used identifiers.
    procedure AddUsedIdent(Ident: TIdentifier);
    //Adds all in this (nested) function used identifiers to the list of used
    //identifiers of the given function-namespace.
    procedure MoveGlobalIdentsTo(NameSpace: TLocalFuncNameSpace);
    //Moves the list of used identifiers to the function-identifier.
    procedure MoveGlobalsToFunction;


    property LocalIdents: TIdentifierList read FLocalIdents;
    property FuncIdent: TFunction read FFuncIdent;
    property ResultIdent: Boolean read FResultIdent write FResultIdent;
  end;




   { * * *  ***  * * *  ***   TOnExceptNameSpace   ***  * * *  ***  * * *  }

  {The namespace for a except-on-clause with a name for the exception-object
   given. ~[code on E: Exception do ...] will result in the creation of a
   TOnExceptNameSpace-object for the duration of "...". An identifier for the
   exception-variable will be created. }
  TOnExceptNameSpace = class(TNameSpace)
  private
    //lower-case name of the exception-variable (for faster comparison)
    FLCName: String;
    //the exception-variable
    FVariable: TVariable;
  public
    //Creates the namespace object and creates the exception-variable.
    constructor Create(const Name: String; ThisFile: TPascalFile;
                       const ExcName: String; ExcIdent: TRecordType);
    //Moves the exception-variable to the function-namespace.
    destructor Destroy; override;

    //Compares the identifier to the exception-variable.
    function FindIdent(const IdentName: String;
                       var SourceFile: TPascalFile): TIdentifier; override;
  end;


  

implementation

uses SysUtils, Classes,
     UPascalConsts;




   { * * *  ***  * * *  ***   TNameSpace   ***  * * *  ***  * * *  }


{Searches the identifier in this namespace and the previous ones. In this
 abstract namespace there is nothing to search, so only the previous is
 searched or nil is returned if there is none.
~param IdentName  the name of the identifier to search
~param SourceFile if it is a file and not an identifier, it is returned through
                  this parameter
~result the identifier, if found, or nil }
function TNameSpace.FindIdent(const IdentName: String;
                              var SourceFile: TPascalFile): TIdentifier;
begin
 if assigned(FPreNameSpace) then   //is there a previous namespace?
  //search the previous namespace for the identifier
  Result := FPreNameSpace.FindIdent(IdentName, SourceFile)
 else
  begin                              //identifier not found
   SourceFile := nil;                //just return nil
   Result := nil;
  end;
end;







   { * * *  ***  * * *  ***   TThisFileNameSpace   ***  * * *  ***  * * *  }


{Creates the namespace object and assigns the file to be searched.
~param ThisFile   the file of the namespace/to be searched for identifiers
~param FileParser the parser of the file, used to count the number of
                  references of each used unit }
constructor TThisFileNameSpace.Create(ThisFile: TPascalFile;
                                      FileParser: TFileParser);
begin
 inherited Create;                   //create object

 assert(assigned(ThisFile));
 FThisFile := ThisFile;              //save the file
 FFileParser := FileParser;          //and its parser
end;


{Searches the identifier in the file and the used units.
~param IdentName  the name of the identifier to search
~param SourceFile if it is a file and not an identifier, it is returned through
                  this parameter
~result the identifier, if found, or nil }
function TThisFileNameSpace.FindIdent(const IdentName: String;
                                     var SourceFile: TPascalFile): TIdentifier;

 {Checks every used unit in the list, if it contains the identifier in its
  interface.
 ~param List the list of used units
 ~param Part the part whose uses clause is being searched
 ~result the identifier in one of the units or nil }
 function CheckUsedUnits(List: TStrings; Part: TFilePart): TIdentifier;
 var      UnitIndex     :Integer;      //counter through used units
 begin
  Result := nil;
  //search each unit used (in that part of the file) until found
  UnitIndex := List.Count - 1;
  while not assigned(Result) and (UnitIndex >= 0) do
   begin
    //find identifier in the used unit
    Result := TPascalFile(List.Objects[UnitIndex]).Idents.
                                                     GetIdentByName(IdentName);
    if assigned(Result) then
     //check if it is declared in the interface of the used unit
     if Result.Scope <> sInterface then
      Result := nil
     else
      FFileParser.CountUnitReference(Part, UnitIndex);  //count the reference
    Dec(UnitIndex);                      //check the next unit
   end;
 end;

var      UnitIndex         :Integer;       //index of used unit
begin
 assert(not assigned(FPreNameSpace));

 SourceFile := nil;
 Result := FThisFile.Idents.GetIdentByName(IdentName); //search in this file
 if not assigned(Result) then
  if LowerCase(IdentName) = LowerCase(FThisFile.InternalFileName) then
   SourceFile := FThisFile                    //is this file
  else
   begin
    //is the name of a used unit?
    UnitIndex := FThisFile.UsedUnitList[fpMain].IndexOf(IdentName);
    if UnitIndex <> -1 then                  //is a used unit (in interface)
     begin
      SourceFile := TPascalFile(FThisFile.UsedUnitList[fpMain].
                                                           Objects[UnitIndex]);

⌨️ 快捷键说明

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