fpc/utils/fpdoc/fpdocclasstree.pp
michael 07d8f573a2 * get rid of some warnings
git-svn-id: trunk@48009 -
(cherry picked from commit 7be3d2f80c)
2021-08-16 17:10:07 +02:00

272 lines
6.8 KiB
ObjectPascal

unit fpdocclasstree;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, dGlobals, pastree, contnrs{$IFDEF TREE_TEST}, DOM ,XMLWrite{$ENDIF};
Type
{ TPasElementNode }
TPasElementNode = Class
Private
FElement : TPasClassType;
FParentNode: TPasElementNode;
FChildren : TFPObjectList;
function GetChild(aIndex : Integer): TPasElementNode;
function GetChildCount: Integer;
Public
Constructor Create (aElement : TPasClassType);
Destructor Destroy; override;
Procedure AddChild(C : TPasElementNode);
Procedure SortChildren;
Property Element : TPasClassType Read FElement;
Property ParentNode : TPasElementNode read FParentNode;
Property Children [aIndex : Integer] : TPasElementNode Read GetChild;
Property ChildCount : Integer Read GetChildCount;
end;
{ TClassTreeBuilder }
TClassTreeBuilder = Class
Private
FEngine:TFPDocEngine;
FElementList : TFPObjectHashTable;
FObjectKind : TPasObjKind;
FPackage: TPasPackage;
FParentObject : TPasClassType;
FRootNode : TPasElementNode;
FRootObjectName : string;
FRootObjectPathName : string;
Protected
function AddToList(aElement: TPasClassType): TPasElementNode;
Public
Constructor Create(AEngine:TFPDocEngine; APackage : TPasPackage;
AObjectKind : TPasObjKind = okClass);
Destructor Destroy; override;
Function BuildTree(AObjects : TStringList) : Integer;
{$IFDEF TREE_TEST}
Procedure SaveToXml(AFileName: String);
{$ENDIF}
Property RootNode : TPasElementNode Read FRootNode;
Property PasElToNodes: TFPObjectHashTable read FElementList;
function GetPasElNode (APasEl: TPasElement) : TPasElementNode;
end;
implementation
{ TPasElementNode }
function SortOnElementName(Item1, Item2: Pointer): Integer;
begin
Result:=CompareText(TPasElementNode(Item1).Element.Name,TPasElementNode(Item2).Element.Name);
end;
function TPasElementNode.GetChild(aIndex : Integer): TPasElementNode;
begin
if Assigned(FChildren) then
Result:=TPasElementNode(FChildren[aIndex])
else
Raise EListError.Create('Index out of range');
end;
function TPasElementNode.GetChildCount: Integer;
begin
if Assigned(FChildren) then
Result:=FChildren.Count
else
Result:=0
end;
constructor TPasElementNode.Create(aElement: TPasClassType);
begin
FElement:=aElement;
end;
destructor TPasElementNode.Destroy;
begin
FreeAndNil(FChildren);
inherited Destroy;
end;
procedure TPasElementNode.AddChild(C: TPasElementNode);
begin
if FChildren=Nil then
FChildren:=TFPObjectList.Create(True);
FChildren.Add(C);
end;
procedure TPasElementNode.SortChildren;
begin
if Assigned(FChildren) then
FChildren.Sort(@SortOnElementName);
end;
constructor TClassTreeBuilder.Create(AEngine:TFPDocEngine; APackage : TPasPackage;
AObjectKind: TPasObjKind);
begin
FEngine:= AEngine;
FPackage:= APAckage;
FObjectKind:=AObjectKind;
Case FObjectkind of
okInterface :
begin
FRootObjectPathName:='#rtl.System.IInterface';
FRootObjectName:= 'IInterface';
end;
okObject, okClass :
begin
FRootObjectPathName:='#rtl.System.TObject';
FRootObjectName:= 'TObject';
end
else
begin
FRootObjectPathName:='#rtl.System.TObject';
FRootObjectName:= 'TObject';
end;
end;
FParentObject:=TPasClassType.Create(FRootObjectName,FEngine.FindModule('System'));
if not Assigned(FParentObject) then
FParentObject:=TPasClassType.Create(FRootObjectName,FPackage);
FParentObject.ObjKind:=FObjectKind;
FRootNode:=TPasElementNode.Create(FParentObject);
FRootNode.FParentNode := nil;
FElementList:=TFPObjectHashTable.Create(False);
FElementList.Add(FRootObjectPathName,FRootNode);
end;
destructor TClassTreeBuilder.Destroy;
begin
FreeAndNil(FParentObject);
FreeAndNil(FRootNode);
FreeAndNil(FElementList);
Inherited;
end;
function TClassTreeBuilder.AddToList ( aElement: TPasClassType
) : TPasElementNode;
Var
aParentNode : TPasElementNode;
aName : String;
begin
Result:= nil;
if (aElement.ObjKind <> FObjectKind) then exit;
aParentNode:= nil;
if aElement=Nil then
aName:=FRootObjectName
else
aName:=aElement.PathName;
Result:=TPasElementNode(FElementList.Items[aName]);
if (Result=Nil) then
begin
if aElement.AncestorType is TPasClassType then
aParentNode:=AddToList(aElement.AncestorType as TPasClassType);
if not Assigned(aParentNode) then
aParentNode:=FRootNode;
Result:=TPasElementNode.Create(aElement);
aParentNode.AddChild(Result);
Result.FParentNode := aParentNode;
FElementList.Add(aName,Result);
end;
end;
function TClassTreeBuilder.BuildTree ( AObjects: TStringList ) : Integer;
(*
Procedure DumpNode(Prefix : String; N : TPasElementNode);
Var
I : Integer;
begin
Writeln(Prefix,N.FElement.Name);
if Assigned(N.FChildren) then
For I:=0 to N.FChildren.Count-1 do
DumpNode(Prefix+' ',TPasElementNode(N.FChildren[i]));
end;
*)
Var
I : Integer;
PC : TPasClassType;
begin
Result:=0;
For I:=0 to AObjects.Count-1 do
// Advanced records
if AObjects.Objects[i] is TPasClassType then
begin
PC:=AObjects.Objects[i] as TPasClassType;
AddToList(PC);
end;
end;
function TClassTreeBuilder.GetPasElNode ( APasEl: TPasElement
) : TPasElementNode;
begin
Result:= TPasElementNode(FElementList.Items[APasEl.PathName]);
end;
{$IFDEF TREE_TEST}
procedure TClassTreeBuilder.SaveToXml ( AFileName: String ) ;
procedure AddPasElChildsToXml (ParentxmlEl : TDOMElement ; ParentPasEl: TPasElementNode ) ;
var
CounterVar: Integer;
PasElNode: TPasElementNode;
AXmlDoc: TDOMDocument;
xmlEl: TDOMElement;
M: TPasModule;
begin
if not Assigned(ParentPasEl) or (ParentPasEl.ChildCount = 0) then exit;
AXmlDoc:= ParentxmlEl.OwnerDocument;
for CounterVar := 0 to ParentPasEl.ChildCount-1 do
begin
PasElNode:= ParentPasEl.Children[CounterVar];
xmlEl:= AXmlDoc.CreateElement(UnicodeString(PasElNode.Element.Name));
M:= PasElNode.Element.GetModule;
xmlEl['unit'] := UnicodeString(M.Name);
xmlEl['package'] := UnicodeString(M.PackageName);
ParentxmlEl.AppendChild(xmlEl);
AddPasElChildsToXml(xmlEl, PasElNode);
end;
end;
var
XmlDoc: TXMLDocument;
XmlRootEl: TDOMElement;
M: TPasModule;
begin
XmlDoc:= TXMLDocument.Create;
try
XmlRootEl:= XmlDoc.CreateElement(UnicodeString(FRootNode.Element.Name));
M:= FRootNode.Element.GetModule;
if Assigned(M) then
begin
XmlRootEl['unit'] := UnicodeString(M.Name);
XmlRootEl['package'] := UnicodeString(M.PackageName);
end
else
begin
XmlRootEl['unit'] := 'system';
XmlRootEl['package'] := 'rtl';
end;
XmlDoc.AppendChild(XmlRootEl);
AddPasElChildsToXml(XmlRootEl, FRootNode);
WriteXMLFile(XmlDoc, AFileName);
finally
XmlDoc.Free;
end;
end;
{$ENDIF}
end.