📄 unamespaces.pas
字号:
{ 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 + -