mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-15 20:19:50 +02:00
codetools: ppu: supporting circle dependencies
git-svn-id: trunk@15662 -
This commit is contained in:
parent
9f416e3595
commit
dc901f9855
@ -96,6 +96,7 @@ type
|
||||
function FindGraphNodeWithNumberOfInEdges(MinNumber, MaxNumber: integer
|
||||
): TCodeGraphNode;
|
||||
|
||||
function PathExists(FromNode, ToNode: TCodeTreeNode): boolean;
|
||||
function AddEdge(FromNode, ToNode: TCodeTreeNode): TCodeGraphEdge;
|
||||
function GetEdge(FromNode, ToNode: TCodeTreeNode;
|
||||
CreateIfNotExists: boolean): TCodeGraphEdge;
|
||||
@ -513,6 +514,33 @@ begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TCodeGraph.PathExists(FromNode, ToNode: TCodeTreeNode): boolean;
|
||||
|
||||
function Search(GraphNode: TCodeGraphNode): boolean;
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
GraphEdge: TCodeGraphEdge;
|
||||
begin
|
||||
Result:=false;
|
||||
if GraphNode=nil then exit;
|
||||
if GraphNode.Node=ToNode then exit(true);
|
||||
if GraphNode.FInternalFlags>0 then exit;
|
||||
GraphNode.FInternalFlags:=1;
|
||||
if GraphNode.OutTree=nil then exit;
|
||||
AVLNode:=GraphNode.OutTree.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
GraphEdge:=TCodeGraphEdge(AVLNode.Data);
|
||||
if Search(GraphEdge.ToNode) then exit(true);
|
||||
AVLNode:=GraphNode.OutTree.FindSuccessor(AVLNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result:=false;
|
||||
ClearInternalNodeFlags;
|
||||
Result:=Search(GetGraphNode(FromNode,false));
|
||||
end;
|
||||
|
||||
function TCodeGraph.AddEdge(FromNode, ToNode: TCodeTreeNode): TCodeGraphEdge;
|
||||
begin
|
||||
Result:=GetEdge(FromNode,ToNode,true);
|
||||
|
@ -75,6 +75,7 @@ type
|
||||
procedure Clear;
|
||||
function AddMember(const NewUnitName: string): TPPUMember;
|
||||
function FindMemberWithUnitName(const AName: string): TPPUMember;
|
||||
function UpdatePPUs: boolean;
|
||||
function UpdateDependencies: boolean;
|
||||
procedure GetMissingUnits(var List: TStrings);
|
||||
property UnitGraph: TCodeGraph read FUnitGraph;
|
||||
@ -91,7 +92,6 @@ type
|
||||
function FindAVLNodeOfMemberWithName(const AName: string): TAVLTreeNode;
|
||||
procedure InternalRemoveMember(AMember: TPPUMember);
|
||||
procedure InternalRemoveGroup(AGroup: TPPUGroup);
|
||||
procedure AddDependency(Member: TPPUMember; const UsedUnit: string);
|
||||
public
|
||||
Name: string;
|
||||
constructor Create;
|
||||
@ -111,6 +111,7 @@ function CompareNameWithPPUMemberName(NamePChar, Member: Pointer): integer;
|
||||
function ComparePPUGroupsByName(Group1, Group2: Pointer): integer;
|
||||
function CompareNameWithPPUGroupName(NamePChar, Group: Pointer): integer;
|
||||
|
||||
function PPUGroupObjectAsString(Obj: TObject): string;
|
||||
|
||||
implementation
|
||||
|
||||
@ -136,6 +137,16 @@ begin
|
||||
Result:=CompareIdentifierPtrs(NamePChar,Pointer(TPPUGroup(Group).Name));
|
||||
end;
|
||||
|
||||
function PPUGroupObjectAsString(Obj: TObject): string;
|
||||
begin
|
||||
if Obj is TPPUMember then
|
||||
Result:='unit '+TPPUMember(Obj).Unitname
|
||||
else if Obj is TPPUGroup then
|
||||
Result:='group '+TPPUGroup(Obj).Name
|
||||
else
|
||||
Result:=dbgs(Obj);
|
||||
end;
|
||||
|
||||
{ TPPUMember }
|
||||
|
||||
constructor TPPUMember.Create;
|
||||
@ -232,7 +243,7 @@ begin
|
||||
UnitGraph.GetTopologicalSortedList(ListOfGraphNodes,true,false,false);
|
||||
if ListOfGraphNodes=nil then
|
||||
ListOfGraphNodes:=TFPList.Create;
|
||||
DebugLn(['TPPUGroup.UpdateTopologicalSortedList ',FMembers.Count,' ',ListOfGraphNodes.Count]);
|
||||
DebugLn(['TPPUGroup.UpdateTopologicalSortedList ',Name,' ',FMembers.Count,' ',ListOfGraphNodes.Count]);
|
||||
DebugLn(['Initialization: ================================']);
|
||||
for i:=ListOfGraphNodes.Count-1 downto 0 do begin
|
||||
GraphNode:=TCodeGraphNode(ListOfGraphNodes[i]);
|
||||
@ -299,15 +310,68 @@ begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
function TPPUGroup.UpdatePPUs: boolean;
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
Member: TPPUMember;
|
||||
begin
|
||||
Result:=true;
|
||||
// load all PPU
|
||||
AVLNode:=FMembers.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
Member:=TPPUMember(AVLNode.Data);
|
||||
if not Member.UpdatePPU then exit(false);
|
||||
AVLNode:=FMembers.FindSuccessor(AVLNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPPUGroup.UpdateDependencies: boolean;
|
||||
|
||||
procedure AddDependencies(Member: TPPUMember; UsesList: TStrings);
|
||||
procedure AddUnitDependency(Member: TPPUMember; const UsedUnit: string);
|
||||
var
|
||||
Graph: TCodeGraph;
|
||||
UsedMember: TPPUMember;
|
||||
begin
|
||||
UsedMember:=FindMemberWithUnitName(UsedUnit);
|
||||
if UsedMember=nil then exit;
|
||||
if Member.Group=UsedMember.Group then begin
|
||||
Graph:=Member.Group.UnitGraph;
|
||||
if not Graph.PathExists(UsedMember.KeyNode,Member.KeyNode) then
|
||||
Graph.AddEdge(Member.KeyNode,UsedMember.KeyNode)
|
||||
else
|
||||
DebugLn(['AddUnitDependency Unit circle found: ',Member.Unitname,' to ',UsedMember.Unitname]);
|
||||
end else begin
|
||||
if not Groups.GroupGraph.PathExists(UsedMember.Group.KeyNode,Member.Group.KeyNode) then
|
||||
Groups.GroupGraph.AddEdge(Member.Group.KeyNode,UsedMember.Group.KeyNode)
|
||||
else
|
||||
DebugLn(['AddUnitDependency Group circle found: ',Member.Group.Name,' to ',UsedMember.Group.Name]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure AddSectionDependencies(Member: TPPUMember; UsesList: TStrings);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if UsesList=nil then exit;
|
||||
for i:=0 to UsesList.Count-1 do
|
||||
Groups.AddDependency(Member,UsesList[i]);
|
||||
AddUnitDependency(Member,UsesList[i]);
|
||||
end;
|
||||
|
||||
procedure AddDependencies(Main: boolean);
|
||||
var
|
||||
AVLNode: TAVLTreeNode;
|
||||
Member: TPPUMember;
|
||||
begin
|
||||
AVLNode:=FMembers.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
Member:=TPPUMember(AVLNode.Data);
|
||||
if not Member.UpdatePPU then exit;
|
||||
if Main then
|
||||
AddSectionDependencies(Member,Member.MainUses)
|
||||
else
|
||||
AddSectionDependencies(Member,Member.ImplementationUses);
|
||||
AVLNode:=FMembers.FindSuccessor(AVLNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
@ -318,7 +382,7 @@ begin
|
||||
Result:=false;
|
||||
FUnitGraph.Clear;
|
||||
|
||||
// create nodes in the UnitGraph
|
||||
// create graph nodes
|
||||
AVLNode:=FMembers.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
Member:=TPPUMember(AVLNode.Data);
|
||||
@ -326,17 +390,12 @@ begin
|
||||
GraphNode.Data:=Member;
|
||||
AVLNode:=FMembers.FindSuccessor(AVLNode);
|
||||
end;
|
||||
|
||||
// load all PPU
|
||||
AVLNode:=FMembers.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
Member:=TPPUMember(AVLNode.Data);
|
||||
if not Member.UpdatePPU then exit;
|
||||
AddDependencies(Member,Member.MainUses);
|
||||
AddDependencies(Member,Member.ImplementationUses);
|
||||
AVLNode:=FMembers.FindSuccessor(AVLNode);
|
||||
end;
|
||||
|
||||
// add primary dependencies
|
||||
AddDependencies(true);
|
||||
// add secondary dependencies
|
||||
AddDependencies(false);
|
||||
|
||||
UpdateTopologicalSortedList;
|
||||
|
||||
Result:=true;
|
||||
@ -379,19 +438,6 @@ begin
|
||||
FGroups.RemovePointer(AGroup);
|
||||
end;
|
||||
|
||||
procedure TPPUGroups.AddDependency(Member: TPPUMember; const UsedUnit: string);
|
||||
var
|
||||
UsedMember: TPPUMember;
|
||||
begin
|
||||
UsedMember:=FindMemberWithUnitName(UsedUnit);
|
||||
if UsedMember=nil then exit;
|
||||
if Member.Group=UsedMember.Group then begin
|
||||
Member.Group.UnitGraph.AddEdge(Member.KeyNode,UsedMember.KeyNode);
|
||||
end else begin
|
||||
GroupGraph.AddEdge(Member.Group.KeyNode,UsedMember.Group.KeyNode);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TPPUGroups.Create;
|
||||
begin
|
||||
FGroups:=TAVLTree.Create(@ComparePPUGroupsByName);
|
||||
@ -466,6 +512,13 @@ begin
|
||||
end;
|
||||
// parse PPU
|
||||
AVLNode:=FGroups.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
Group:=TPPUGroup(AVLNode.Data);
|
||||
if not Group.UpdatePPUs then exit;
|
||||
AVLNode:=FGroups.FindSuccessor(AVLNode);
|
||||
end;
|
||||
// update dependencies
|
||||
AVLNode:=FGroups.FindLowest;
|
||||
while AVLNode<>nil do begin
|
||||
Group:=TPPUGroup(AVLNode.Data);
|
||||
if not Group.UpdateDependencies then exit;
|
||||
|
Loading…
Reference in New Issue
Block a user