mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-01 23:40:26 +02:00
codetools: added unit ppugraph to parse groups of ppu files
git-svn-id: trunk@15655 -
This commit is contained in:
parent
168bd041aa
commit
bf2774ed3d
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -185,6 +185,7 @@ components/codetools/multikeywordlisttool.pas svneol=native#text/pascal
|
||||
components/codetools/nonpascalcodetools.pas svneol=native#text/plain
|
||||
components/codetools/pascalparsertool.pas svneol=native#text/pascal
|
||||
components/codetools/pascalreadertool.pas svneol=native#text/pascal
|
||||
components/codetools/ppugraph.pas svneol=native#text/plain
|
||||
components/codetools/ppuparser.pas svneol=native#text/plain
|
||||
components/codetools/resourcecodetool.pas svneol=native#text/pascal
|
||||
components/codetools/sourcechanger.pas svneol=native#text/pascal
|
||||
|
@ -24,7 +24,7 @@ uses
|
||||
CodeCache, KeywordFuncLists, SourceLog, ExprEval, DefineTemplates, FileProcs,
|
||||
CodeToolsStrConsts, DirectoryCacher, CCodeParserTool, H2PasTool,
|
||||
MultiKeyWordListTool, ResourceCodeTool, CodeToolsStructs, CacheCodeTools,
|
||||
PPUParser,
|
||||
PPUParser, PPUGraph,
|
||||
// fast xml units, changes not merged in current fpc
|
||||
Laz_DOM, Laz_XMLCfg, Laz_XMLRead, Laz_XMLWrite, Laz_XMLStreaming;
|
||||
|
||||
|
@ -123,12 +123,12 @@ type
|
||||
end;
|
||||
|
||||
function CompareGraphNodeByNode(GraphNode1, GraphNode2: Pointer): integer;
|
||||
function ComparePointerWithGraphNodeNode(p, GraphNode: Pointer): integer;
|
||||
function CompareNodeWithGraphNodeNode(p, GraphNode: Pointer): integer;
|
||||
|
||||
function CompareGraphEdgeByFromNode(GraphEdge1, GraphEdge2: Pointer): integer;
|
||||
function ComparePointerWithGraphEdgeFromNode(p, GraphEdge: Pointer): integer;
|
||||
function CompareNodeWithGraphEdgeFromNode(p, GraphEdge: Pointer): integer;
|
||||
function CompareGraphEdgeByToNode(GraphEdge1, GraphEdge2: Pointer): integer;
|
||||
function ComparePointerWithGraphEdgeToNode(p, GraphEdge: Pointer): integer;
|
||||
function CompareNodeWithGraphEdgeToNode(p, GraphEdge: Pointer): integer;
|
||||
|
||||
function CompareGraphEdgeByNodes(GraphEdge1, GraphEdge2: Pointer): integer;
|
||||
function CompareEdgeKeyWithGraphEdge(EdgeKey, GraphEdge: Pointer): integer;
|
||||
@ -151,7 +151,7 @@ begin
|
||||
//DebugLn(['CompareGraphNodeByNode ',Node1.DescAsString,' ',Node2.DescAsString,' ',Result]);
|
||||
end;
|
||||
|
||||
function ComparePointerWithGraphNodeNode(p, GraphNode: Pointer): integer;
|
||||
function CompareNodeWithGraphNodeNode(p, GraphNode: Pointer): integer;
|
||||
var
|
||||
Node: TCodeTreeNode;
|
||||
begin
|
||||
@ -180,7 +180,7 @@ begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function ComparePointerWithGraphEdgeFromNode(p, GraphEdge: Pointer): integer;
|
||||
function CompareNodeWithGraphEdgeFromNode(p, GraphEdge: Pointer): integer;
|
||||
var
|
||||
Node: TCodeTreeNode;
|
||||
begin
|
||||
@ -208,7 +208,7 @@ begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function ComparePointerWithGraphEdgeToNode(p, GraphEdge: Pointer): integer;
|
||||
function CompareNodeWithGraphEdgeToNode(p, GraphEdge: Pointer): integer;
|
||||
var
|
||||
Node: TCodeTreeNode;
|
||||
begin
|
||||
@ -382,6 +382,8 @@ var
|
||||
begin
|
||||
if Source=Self then exit;
|
||||
Clear;
|
||||
FNodeClass:=Source.FNodeClass;
|
||||
FEdgeClass:=Source.FEdgeClass;
|
||||
// copy nodes
|
||||
AVLNode:=Source.Nodes.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
@ -841,14 +843,14 @@ end;
|
||||
|
||||
function TCodeGraph.FindAVLNodeOfNode(Node: TCodeTreeNode): TAVLTreeNode;
|
||||
begin
|
||||
Result:=Nodes.FindKey(Node,@ComparePointerWithGraphNodeNode);
|
||||
Result:=Nodes.FindKey(Node,@CompareNodeWithGraphNodeNode);
|
||||
end;
|
||||
|
||||
function TCodeGraph.FindAVLNodeOfToNode(InTree: TAVLTree; ToNode: TCodeTreeNode
|
||||
): TAVLTreeNode;
|
||||
begin
|
||||
if InTree<>nil then
|
||||
Result:=InTree.FindKey(ToNode,@ComparePointerWithGraphEdgeToNode)
|
||||
Result:=InTree.FindKey(ToNode,@CompareNodeWithGraphEdgeToNode)
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
@ -857,7 +859,7 @@ function TCodeGraph.FindAVLNodeOfFromNode(OutTree: TAVLTree;
|
||||
FromNode: TCodeTreeNode): TAVLTreeNode;
|
||||
begin
|
||||
if OutTree<>nil then
|
||||
Result:=OutTree.FindKey(FromNode,@ComparePointerWithGraphEdgeFromNode)
|
||||
Result:=OutTree.FindKey(FromNode,@CompareNodeWithGraphEdgeFromNode)
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
|
@ -28,39 +28,34 @@ program PPUDependencies;
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
Classes, SysUtils, PPUParser, FileProcs;
|
||||
Classes, SysUtils, PPUParser, FileProcs, PPUGraph;
|
||||
|
||||
var
|
||||
PPU: TPPU;
|
||||
Filename: String;
|
||||
UsedUnits: TStringList;
|
||||
Groups: TPPUGroups;
|
||||
Group: TPPUGroup;
|
||||
i: Integer;
|
||||
Member: TPPUMember;
|
||||
begin
|
||||
if (Paramcount<1) then begin
|
||||
writeln('Usage:');
|
||||
writeln(' ',ParamStr(0),' <ppu filename>');
|
||||
writeln(' ',ParamStr(0),' <ppu filename1> ...');
|
||||
Halt;
|
||||
end;
|
||||
|
||||
Filename:=ParamStr(1);
|
||||
|
||||
PPU:=TPPU.Create;
|
||||
UsedUnits:=TStringList.Create;
|
||||
|
||||
Groups:=TPPUGroups.Create;
|
||||
try
|
||||
PPU.LoadFromFile(Filename);
|
||||
debugln('================================================================');
|
||||
PPU.Dump('');
|
||||
debugln('================================================================');
|
||||
UsedUnits.Clear;
|
||||
PPU.GetMainUsesSectionNames(UsedUnits);
|
||||
debugln('Main used units: ',UsedUnits.DelimitedText);
|
||||
UsedUnits.Clear;
|
||||
PPU.GetImplementationUsesSectionNames(UsedUnits);
|
||||
debugln('Implementation used units: ',UsedUnits.DelimitedText);
|
||||
debugln('Intialization proc: ',PPU.GetInitProcName);
|
||||
debugln('Finalization proc: ',PPU.GetFinalProcName);
|
||||
Group:=Groups.AddGroup('Default');
|
||||
for i:=1 to Paramcount do begin
|
||||
Filename:=ParamStr(i);
|
||||
debugln(Filename);
|
||||
Member:=Group.AddMember(ExtractFileNameOnly(Filename));
|
||||
Member.PPUFilename:=Filename;
|
||||
end;
|
||||
|
||||
Groups.UpdateDependencies;
|
||||
finally
|
||||
PPU.Free;
|
||||
UsedUnits.Free;
|
||||
Groups.Free;
|
||||
end;
|
||||
end.
|
||||
|
||||
|
338
components/codetools/ppugraph.pas
Normal file
338
components/codetools/ppugraph.pas
Normal file
@ -0,0 +1,338 @@
|
||||
{
|
||||
***************************************************************************
|
||||
* *
|
||||
* This source is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This code 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. *
|
||||
* *
|
||||
* A copy of the GNU General Public License is available on the World *
|
||||
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||
* obtain it by writing to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
Author: Mattias Gaertner
|
||||
|
||||
Abstract:
|
||||
Functions and classes to build dependency graphs for ppu files.
|
||||
}
|
||||
unit PPUGraph;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, PPUParser, CodeTree, AVL_Tree, FileProcs, BasicCodeTools;
|
||||
|
||||
type
|
||||
TPPUGroup = class;
|
||||
|
||||
{ TPPUMember }
|
||||
|
||||
TPPUMember = class
|
||||
public
|
||||
Unitname: string;
|
||||
PPUFilename: string;
|
||||
KeyNode: TCodeTreeNode;
|
||||
InitializationMangledName: string;
|
||||
FinalizationMangledName: string;
|
||||
Group: TPPUGroup;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
function UpdateDependencies: boolean;
|
||||
end;
|
||||
|
||||
TPPUGroups = class;
|
||||
|
||||
{ TPPUGroup }
|
||||
|
||||
TPPUGroup = class
|
||||
private
|
||||
FMembers: TAVLTree;// tree of TPPUMember sorted for unitname
|
||||
function FindAVLNodeOfMemberWithUnitName(const AName: string): TAVLTreeNode;
|
||||
procedure InternalRemoveMember(AMember: TPPUMember);
|
||||
public
|
||||
Name: string;
|
||||
KeyNode: TCodeTreeNode;
|
||||
Groups: TPPUGroups;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure Clear;
|
||||
function AddMember(const NewUnitName: string): TPPUMember;
|
||||
function FindMemberWithUnitName(const AName: string): TPPUMember;
|
||||
function UpdateDependencies: boolean;
|
||||
end;
|
||||
|
||||
{ TPPUGroups }
|
||||
|
||||
TPPUGroups = class
|
||||
private
|
||||
FGroups: TAVLTree;// tree of TPPUGroup sorted for name
|
||||
FMembers: TAVLTree;// tree of TPPUMember sorted for unitname
|
||||
function FindAVLNodeOfGroupWithName(const AName: string): TAVLTreeNode;
|
||||
function FindAVLNodeOfMemberWithName(const AName: string): TAVLTreeNode;
|
||||
procedure InternalRemoveMember(AMember: TPPUMember);
|
||||
procedure InternalRemoveGroup(AGroup: TPPUGroup);
|
||||
public
|
||||
Name: string;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure Clear;
|
||||
function AddGroup(const NewName: string): TPPUGroup;
|
||||
function FindGroupWithName(const AName: string): TPPUGroup;
|
||||
function FindMemberWithUnitName(const AName: string): TPPUMember;
|
||||
function UpdateDependencies: boolean;
|
||||
end;
|
||||
|
||||
function ComparePPUMembersByUnitName(Member1, Member2: Pointer): integer;
|
||||
function CompareNameWithPPUMemberName(NamePChar, Member: Pointer): integer;
|
||||
|
||||
function ComparePPUGroupsByName(Group1, Group2: Pointer): integer;
|
||||
function CompareNameWithPPUGroupName(NamePChar, Group: Pointer): integer;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
function ComparePPUMembersByUnitName(Member1, Member2: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareIdentifierPtrs(Pointer(TPPUMember(Member1).Unitname),
|
||||
Pointer(TPPUMember(Member2).Unitname));
|
||||
end;
|
||||
|
||||
function CompareNameWithPPUMemberName(NamePChar, Member: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareIdentifierPtrs(NamePChar,Pointer(TPPUMember(Member).Unitname));
|
||||
end;
|
||||
|
||||
function ComparePPUGroupsByName(Group1, Group2: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareIdentifierPtrs(Pointer(TPPUGroup(Group1).Name),
|
||||
Pointer(TPPUGroup(Group2).Name));
|
||||
end;
|
||||
|
||||
function CompareNameWithPPUGroupName(NamePChar, Group: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareIdentifierPtrs(NamePChar,Pointer(TPPUGroup(Group).Name));
|
||||
end;
|
||||
|
||||
{ TPPUMember }
|
||||
|
||||
constructor TPPUMember.Create;
|
||||
begin
|
||||
KeyNode:=NodeMemManager.NewNode;
|
||||
end;
|
||||
|
||||
destructor TPPUMember.Destroy;
|
||||
begin
|
||||
if KeyNode<>nil then
|
||||
NodeMemManager.DisposeNode(KeyNode);
|
||||
KeyNode:=nil;
|
||||
if Group<>nil then
|
||||
Group.InternalRemoveMember(Self);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TPPUMember.UpdateDependencies: boolean;
|
||||
var
|
||||
PPU: TPPU;
|
||||
UsedUnits: TStringList;
|
||||
begin
|
||||
Result:=false;
|
||||
PPU:=TPPU.Create;
|
||||
UsedUnits:=TStringList.Create;
|
||||
try
|
||||
PPU.LoadFromFile(PPUFilename);
|
||||
debugln('================================================================');
|
||||
DebugLn(['TPPUMember.UpdateDependencies UnitName=',Unitname,' Filename=',PPUFilename]);
|
||||
PPU.Dump('');
|
||||
debugln('================================================================');
|
||||
UsedUnits.Clear;
|
||||
PPU.GetMainUsesSectionNames(UsedUnits);
|
||||
debugln('Main used units: ',UsedUnits.DelimitedText);
|
||||
UsedUnits.Clear;
|
||||
PPU.GetImplementationUsesSectionNames(UsedUnits);
|
||||
debugln('Implementation used units: ',UsedUnits.DelimitedText);
|
||||
InitializationMangledName:=PPU.GetInitProcName;
|
||||
debugln('Initialization proc: ',InitializationMangledName);
|
||||
FinalizationMangledName:=PPU.GetFinalProcName;
|
||||
debugln('Finalization proc: ',FinalizationMangledName);
|
||||
finally
|
||||
PPU.Free;
|
||||
UsedUnits.Free;
|
||||
end;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
{ TPPUGroup }
|
||||
|
||||
function TPPUGroup.FindAVLNodeOfMemberWithUnitName(const AName: string
|
||||
): TAVLTreeNode;
|
||||
begin
|
||||
Result:=FMembers.FindKey(PChar(AName),@CompareNameWithPPUMemberName);
|
||||
end;
|
||||
|
||||
procedure TPPUGroup.InternalRemoveMember(AMember: TPPUMember);
|
||||
begin
|
||||
FMembers.RemovePointer(AMember);
|
||||
if Groups<>nil then
|
||||
Groups.InternalRemoveMember(AMember);
|
||||
end;
|
||||
|
||||
constructor TPPUGroup.Create;
|
||||
begin
|
||||
FMembers:=TAVLTree.Create(@ComparePPUMembersByUnitName);
|
||||
KeyNode:=NodeMemManager.NewNode;
|
||||
end;
|
||||
|
||||
destructor TPPUGroup.Destroy;
|
||||
begin
|
||||
Clear;
|
||||
FreeAndNil(FMembers);
|
||||
if KeyNode<>nil then
|
||||
NodeMemManager.DisposeNode(KeyNode);
|
||||
KeyNode:=nil;
|
||||
if Groups<>nil then
|
||||
Groups.InternalRemoveGroup(Self);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPPUGroup.Clear;
|
||||
begin
|
||||
while FMembers.Count>0 do
|
||||
TPPUMember(FMembers.Root.Data).Free;
|
||||
end;
|
||||
|
||||
function TPPUGroup.AddMember(const NewUnitName: string): TPPUMember;
|
||||
begin
|
||||
Result:=FindMemberWithUnitName(NewUnitName);
|
||||
if Result<>nil then exit;
|
||||
Result:=TPPUMember.Create;
|
||||
Result.Unitname:=NewUnitName;
|
||||
FMembers.Add(Result);
|
||||
Result.Group:=Self;
|
||||
Groups.FMembers.Add(Result);
|
||||
end;
|
||||
|
||||
function TPPUGroup.FindMemberWithUnitName(const AName: string): TPPUMember;
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
begin
|
||||
AVLNode:=FindAVLNodeOfMemberWithUnitName(AName);
|
||||
if AVLNode<>nil then
|
||||
Result:=TPPUMember(AVLNode.Data)
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TPPUGroup.UpdateDependencies: boolean;
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
begin
|
||||
Result:=false;
|
||||
AVLNode:=FMembers.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
if not TPPUMember(AVLNode.Data).UpdateDependencies then exit;
|
||||
AVLNode:=FMembers.FindSuccessor(AVLNode);
|
||||
end;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
{ TPPUGroups }
|
||||
|
||||
function TPPUGroups.FindAVLNodeOfGroupWithName(const AName: string
|
||||
): TAVLTreeNode;
|
||||
begin
|
||||
Result:=FGroups.FindKey(PChar(AName),@CompareNameWithPPUGroupName);
|
||||
end;
|
||||
|
||||
function TPPUGroups.FindAVLNodeOfMemberWithName(const AName: string
|
||||
): TAVLTreeNode;
|
||||
begin
|
||||
Result:=FMembers.FindKey(PChar(AName),@CompareNameWithPPUMemberName);
|
||||
end;
|
||||
|
||||
procedure TPPUGroups.InternalRemoveMember(AMember: TPPUMember);
|
||||
begin
|
||||
FMembers.RemovePointer(AMember);
|
||||
end;
|
||||
|
||||
procedure TPPUGroups.InternalRemoveGroup(AGroup: TPPUGroup);
|
||||
begin
|
||||
FGroups.RemovePointer(AGroup);
|
||||
end;
|
||||
|
||||
constructor TPPUGroups.Create;
|
||||
begin
|
||||
FGroups:=TAVLTree.Create(@ComparePPUGroupsByName);
|
||||
FMembers:=TAVLTree.Create(@ComparePPUMembersByUnitName);
|
||||
end;
|
||||
|
||||
destructor TPPUGroups.Destroy;
|
||||
begin
|
||||
Clear;
|
||||
FreeAndNil(FGroups);
|
||||
FreeAndNil(FMembers);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TPPUGroups.Clear;
|
||||
begin
|
||||
while FGroups.Count>0 do
|
||||
TPPUGroup(FGroups.Root.Data).Free;
|
||||
end;
|
||||
|
||||
function TPPUGroups.AddGroup(const NewName: string): TPPUGroup;
|
||||
begin
|
||||
Result:=FindGroupWithName(NewName);
|
||||
if Result<>nil then exit;
|
||||
Result:=TPPUGroup.Create;
|
||||
Result.Name:=NewName;
|
||||
FGroups.Add(Result);
|
||||
Result.Groups:=Self;
|
||||
end;
|
||||
|
||||
function TPPUGroups.FindGroupWithName(const AName: string): TPPUGroup;
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
begin
|
||||
AVLNode:=FindAVLNodeOfGroupWithName(AName);
|
||||
if AVLNode<>nil then
|
||||
Result:=TPPUGroup(AVLNode.Data)
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TPPUGroups.FindMemberWithUnitName(const AName: string): TPPUMember;
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
begin
|
||||
AVLNode:=FindAVLNodeOfMemberWithName(AName);
|
||||
if AVLNode<>nil then
|
||||
Result:=TPPUMember(AVLNode.Data)
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TPPUGroups.UpdateDependencies: boolean;
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
begin
|
||||
Result:=false;
|
||||
AVLNode:=FGroups.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
if not TPPUGroup(AVLNode.Data).UpdateDependencies then exit;
|
||||
AVLNode:=FGroups.FindSuccessor(AVLNode);
|
||||
end;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user