mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-14 15:39:20 +02:00
codetools: TUsesGraph.FindShortestPath
git-svn-id: trunk@42725 -
This commit is contained in:
parent
79670c113d
commit
15838492b6
@ -32,7 +32,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
Classes, SysUtils, AVL_Tree, FileProcs, FindDeclarationTool, CodeBeautifier,
|
Classes, SysUtils, AVL_Tree, FileProcs, FindDeclarationTool, CodeBeautifier,
|
||||||
CodeGraph, CodeCache, StdCodeTools, DirectoryCacher, LinkScanner,
|
CodeGraph, CodeCache, StdCodeTools, DirectoryCacher, LinkScanner,
|
||||||
CustomCodeTool, CodeTree, CodeAtom;
|
CustomCodeTool, CodeTree, CodeAtom, CodeToolsStructs;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -115,6 +115,7 @@ type
|
|||||||
procedure Clear;
|
procedure Clear;
|
||||||
procedure ConsistencyCheck;
|
procedure ConsistencyCheck;
|
||||||
function GetUnit(const ExpFilename: string; CreateIfNotExists: boolean): TUGUnit;
|
function GetUnit(const ExpFilename: string; CreateIfNotExists: boolean): TUGUnit;
|
||||||
|
function FindUnit(const AnUnitName: string): TUGUnit; // slow
|
||||||
|
|
||||||
procedure AddStartUnit(ExpFilename: string);
|
procedure AddStartUnit(ExpFilename: string);
|
||||||
procedure AddTargetUnit(ExpFilename: string);
|
procedure AddTargetUnit(ExpFilename: string);
|
||||||
@ -126,6 +127,8 @@ type
|
|||||||
function UnitCanFindTarget(ExpFilename: string): boolean;
|
function UnitCanFindTarget(ExpFilename: string): boolean;
|
||||||
function IsTargetDir(ExpDir: string): boolean;
|
function IsTargetDir(ExpDir: string): boolean;
|
||||||
|
|
||||||
|
function FindShortestPath(StartUnit, EndUnit: TUGUnit): TFPList; // list of TUGUnit, nil if no path exists
|
||||||
|
|
||||||
property FilesTree: TAVLTree read FFiles; // tree of TUGUnit sorted for Filename (all parsed)
|
property FilesTree: TAVLTree read FFiles; // tree of TUGUnit sorted for Filename (all parsed)
|
||||||
property QueuedFilesTree: TAVLTree read FQueuedFiles; // tree of TUGUnit sorted for Filename
|
property QueuedFilesTree: TAVLTree read FQueuedFiles; // tree of TUGUnit sorted for Filename
|
||||||
property TargetFilesTree: TAVLTree read FTargetFiles; // tree of TUGUnit sorted for Filename
|
property TargetFilesTree: TAVLTree read FTargetFiles; // tree of TUGUnit sorted for Filename
|
||||||
@ -300,6 +303,19 @@ begin
|
|||||||
Result:=nil;
|
Result:=nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TUsesGraph.FindUnit(const AnUnitName: string): TUGUnit;
|
||||||
|
var
|
||||||
|
AVLNode: TAVLTreeNode;
|
||||||
|
begin
|
||||||
|
AVLNode:=FFiles.FindLowest;
|
||||||
|
while AVLNode<>nil do begin
|
||||||
|
Result:=TUGUnit(AVLNode.Data);
|
||||||
|
if CompareText(ExtractFileNameOnly(Result.Filename),AnUnitName)=0 then
|
||||||
|
exit;
|
||||||
|
AVLNode:=FFiles.FindSuccessor(AVLNode);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TUsesGraph.AddStartUnit(ExpFilename: string);
|
procedure TUsesGraph.AddStartUnit(ExpFilename: string);
|
||||||
var
|
var
|
||||||
NewUnit: TUGUnit;
|
NewUnit: TUGUnit;
|
||||||
@ -591,5 +607,56 @@ begin
|
|||||||
Result:=false;
|
Result:=false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TUsesGraph.FindShortestPath(StartUnit, EndUnit: TUGUnit): TFPList;
|
||||||
|
// broad search first
|
||||||
|
var
|
||||||
|
Queue: TFPList;
|
||||||
|
NodeToPrevNode: TPointerToPointerTree;
|
||||||
|
CurUnit: TUGUnit;
|
||||||
|
i: Integer;
|
||||||
|
CurUses: TUGUses;
|
||||||
|
UsesUnit: TUGUnit;
|
||||||
|
PrevUnit: TUGUnit;
|
||||||
|
begin
|
||||||
|
Result:=nil;
|
||||||
|
if (StartUnit=nil) or (EndUnit=nil) then exit;
|
||||||
|
Queue:=TFPList.Create;
|
||||||
|
NodeToPrevNode:=TPointerToPointerTree.Create;
|
||||||
|
try
|
||||||
|
Queue.Add(EndUnit);
|
||||||
|
NodeToPrevNode[EndUnit]:=EndUnit; // set end marker
|
||||||
|
while Queue.Count>0 do begin
|
||||||
|
CurUnit:=TUGUnit(Queue[0]);
|
||||||
|
Queue.Delete(0);
|
||||||
|
if CurUnit.UsedByUnits=nil then continue;
|
||||||
|
for i:=0 to CurUnit.UsesUnits.Count-1 do begin
|
||||||
|
CurUses:=TUGUses(CurUnit.UsedByUnits[i]);
|
||||||
|
if CurUses.InImplementation then continue;
|
||||||
|
UsesUnit:=CurUses.UsesUnit;
|
||||||
|
if NodeToPrevNode.Contains(UsesUnit) then
|
||||||
|
continue; // already visited
|
||||||
|
NodeToPrevNode[UsesUnit]:=CurUnit;
|
||||||
|
if UsesUnit=StartUnit then begin
|
||||||
|
// target found
|
||||||
|
// => create list from StartUnit to EndUnit
|
||||||
|
Result:=TFPList.Create;
|
||||||
|
CurUnit:=StartUnit;
|
||||||
|
repeat
|
||||||
|
Result.Add(CurUnit);
|
||||||
|
PrevUnit:=TUGUnit(NodeToPrevNode[CurUnit]);
|
||||||
|
if PrevUnit=CurUnit then exit; // end marker found
|
||||||
|
CurUnit:=PrevUnit;
|
||||||
|
until false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
Queue.Add(UsesUnit);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
NodeToPrevNode.Free;
|
||||||
|
Queue.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user