codetools: find overloads: compute shortest paths

git-svn-id: trunk@19768 -
This commit is contained in:
mattias 2009-05-02 14:15:24 +00:00
parent 7f4737ea06
commit fe9fc19598
2 changed files with 139 additions and 7 deletions

View File

@ -22,6 +22,9 @@
Abstract: Abstract:
A graph of declaration overloads. A graph of declaration overloads.
Create via CodeToolBoss.GatherOverloads(Code,X,Y,Graph).
Add units via Graph.ScanToolForIdentifier.
} }
unit FindOverloads; unit FindOverloads;
@ -34,6 +37,7 @@ uses
CodeCache, FindDeclarationTool, AVL_Tree, FindDeclarationCache, StdCodeTools; CodeCache, FindDeclarationTool, AVL_Tree, FindDeclarationCache, StdCodeTools;
type type
TOverloadsGraphEdge = class;
{ TOverloadsGraphNode } { TOverloadsGraphNode }
@ -41,6 +45,8 @@ type
public public
Identifier: string; Identifier: string;
Tool: TFindDeclarationTool; Tool: TFindDeclarationTool;
ShortestPathLength: integer;
ShortestPathEdge: TOverloadsGraphEdge;
function AsDebugString: string; function AsDebugString: string;
end; end;
@ -57,6 +63,7 @@ type
public public
Typ: TOverloadsGraphEdgeType; Typ: TOverloadsGraphEdgeType;
function AsDebugString: string; function AsDebugString: string;
function Cost: integer;
end; end;
{ TDeclarationOverloadsGraph } { TDeclarationOverloadsGraph }
@ -66,7 +73,9 @@ type
FGraph: TCodeGraph; FGraph: TCodeGraph;
FIdentifier: string; FIdentifier: string;
FOnGetCodeToolForBuffer: TOnGetCodeToolForBuffer; FOnGetCodeToolForBuffer: TOnGetCodeToolForBuffer;
FShortestNodes: TAVLTree;
FStartCode: TCodeBuffer; FStartCode: TCodeBuffer;
FStartCodeNode: TCodeTreeNode;
FStartX: integer; FStartX: integer;
FStartY: integer; FStartY: integer;
function AddContext(Tool: TFindDeclarationTool; function AddContext(Tool: TFindDeclarationTool;
@ -80,11 +89,15 @@ type
function Init(Code: TCodeBuffer; X,Y: integer): Boolean; function Init(Code: TCodeBuffer; X,Y: integer): Boolean;
procedure ScanToolForIdentifier(Tool: TStandardCodeTool; procedure ScanToolForIdentifier(Tool: TStandardCodeTool;
OnlyInterface: boolean); OnlyInterface: boolean);
property Identifier: string read FIdentifier; procedure ComputeShortestPaths;
public
property Graph: TCodeGraph read FGraph; property Graph: TCodeGraph read FGraph;
property Identifier: string read FIdentifier;
property ShortestNodes: TAVLTree read FShortestNodes;// nodes sorted for ShortestPathLength (after ComputeShortestPaths)
property StartCode: TCodeBuffer read FStartCode; property StartCode: TCodeBuffer read FStartCode;
property StartX: integer read FStartX; property StartX: integer read FStartX;
property StartY: integer read FStartY; property StartY: integer read FStartY;
property StartCodeNode: TCodeTreeNode read FStartCodeNode;
property OnGetCodeToolForBuffer: TOnGetCodeToolForBuffer property OnGetCodeToolForBuffer: TOnGetCodeToolForBuffer
read FOnGetCodeToolForBuffer write FOnGetCodeToolForBuffer; read FOnGetCodeToolForBuffer write FOnGetCodeToolForBuffer;
end; end;
@ -96,8 +109,21 @@ const
'Alias-Old' 'Alias-Old'
); );
function CompareOverloadsNodesByPathLen(Node1, Node2: TOverloadsGraphNode): integer;
implementation implementation
function CompareOverloadsNodesByPathLen(Node1, Node2: TOverloadsGraphNode
): integer;
begin
if Node1.ShortestPathLength>Node2.ShortestPathLength then
Result:=1
else if Node1.ShortestPathLength<Node2.ShortestPathLength then
Result:=-1
else
Result:=0;
end;
{ TDeclarationOverloadsGraph } { TDeclarationOverloadsGraph }
function TDeclarationOverloadsGraph.AddContext(Tool: TFindDeclarationTool; function TDeclarationOverloadsGraph.AddContext(Tool: TFindDeclarationTool;
@ -234,7 +260,13 @@ end;
procedure TDeclarationOverloadsGraph.Clear; procedure TDeclarationOverloadsGraph.Clear;
begin begin
FreeAndNil(FShortestNodes);
Graph.Clear;
FStartCodeNode:=nil;
FStartCode:=nil;
FStartX:=0;
FStartY:=0;
FIdentifier:='';
end; end;
function TDeclarationOverloadsGraph.Init(Code: TCodeBuffer; X, Y: integer function TDeclarationOverloadsGraph.Init(Code: TCodeBuffer; X, Y: integer
@ -242,7 +274,6 @@ function TDeclarationOverloadsGraph.Init(Code: TCodeBuffer; X, Y: integer
var var
Tool: TFindDeclarationTool; Tool: TFindDeclarationTool;
CleanPos: integer; CleanPos: integer;
CodeNode: TCodeTreeNode;
begin begin
Result:=false; Result:=false;
FStartCode:=Code; FStartCode:=Code;
@ -254,13 +285,13 @@ begin
DebugLn(['TDeclarationOverloadsGraph.Init Tool.CaretToCleanPos failed']); DebugLn(['TDeclarationOverloadsGraph.Init Tool.CaretToCleanPos failed']);
exit(false); exit(false);
end; end;
CodeNode:=Tool.FindDeepestNodeAtPos(CleanPos,true); fStartCodeNode:=Tool.FindDeepestNodeAtPos(CleanPos,true);
//DebugLn(['TDeclarationOverloadsGraph.Init Add start context']); //DebugLn(['TDeclarationOverloadsGraph.Init Add start context']);
AddContext(Tool,CodeNode); AddContext(Tool,StartCodeNode);
fIdentifier:=''; fIdentifier:='';
if CodeNode.Desc in AllIdentifierDefinitions+[ctnEnumIdentifier] then if fStartCodeNode.Desc in AllIdentifierDefinitions+[ctnEnumIdentifier] then
fIdentifier:=GetIdentifier(@Tool.Src[CodeNode.StartPos]); fIdentifier:=GetIdentifier(@Tool.Src[fStartCodeNode.StartPos]);
Result:=true; Result:=true;
end; end;
@ -324,6 +355,95 @@ begin
end; end;
end; end;
procedure TDeclarationOverloadsGraph.ComputeShortestPaths;
var
AVLNode: TAVLTreeNode;
GraphNode: TOverloadsGraphNode;
StartGraphNode: TOverloadsGraphNode;
WorkNodes: TAVLTree;
Edge: TOverloadsGraphEdge;
GraphNode2: TOverloadsGraphNode;
begin
(* Dijkstra-Algorithm:
for v in V do l(v):=inf
l(u) := 0
W:=V
while W not empty do
v := { v in W | l(v) minimal }
W:=W-{v}
for x in Adj(v), x in W do
if l(v)+w(v,x)<l(x) then
l(x):=l(v)+w(v,x)
k(x):=(v,x)
*)
StartGraphNode:=TOverloadsGraphNode(Graph.GetGraphNode(StartCodeNode,false));
if StartGraphNode=nil then exit;
WorkNodes:=nil;
try
// set all ShortestPathLength to infinity (except the start which gets 0)
// and sort all nodes in a tree
WorkNodes:=TAVLTree.Create(TListSortCompare(@CompareOverloadsNodesByPathLen));
AVLNode:=Graph.Nodes.FindLowest;
while AVLNode<>nil do begin
GraphNode:=TOverloadsGraphNode(AVLNode.Data);
GraphNode.ShortestPathEdge:=nil;
if GraphNode.Node=StartCodeNode then
GraphNode.ShortestPathLength:=0
else
GraphNode.ShortestPathLength:=high(integer) div 2;
WorkNodes.Add(GraphNode);
AVLNode:=Graph.Nodes.FindSuccessor(AVLNode);
end;
// for each remaining node that has currently the shortest path ...
while WorkNodes.Count>0 do begin
GraphNode:=TOverloadsGraphNode(WorkNodes.FindLowest.Data);
// this node's ShortestPathLength is final
WorkNodes.Remove(GraphNode);
// update adjacent nodes
AVLNode:=GraphNode.OutTree.FindLowest;
while AVLNode<>nil do begin
Edge:=TOverloadsGraphEdge(AVLNode.Data);
GraphNode2:=TOverloadsGraphNode(Edge.ToNode);
if GraphNode.ShortestPathLength+Edge.Cost<GraphNode2.ShortestPathLength
then begin
GraphNode2.ShortestPathLength:=GraphNode.ShortestPathLength+Edge.Cost;
GraphNode2.ShortestPathEdge:=Edge;
end;
AVLNode:=GraphNode.OutTree.FindSuccessor(AVLNode);
end;
// update incident nodes
AVLNode:=GraphNode.InTree.FindLowest;
while AVLNode<>nil do begin
Edge:=TOverloadsGraphEdge(AVLNode.Data);
GraphNode2:=TOverloadsGraphNode(Edge.FromNode);
if GraphNode.ShortestPathLength+Edge.Cost<GraphNode2.ShortestPathLength
then begin
GraphNode2.ShortestPathLength:=GraphNode.ShortestPathLength+Edge.Cost;
GraphNode2.ShortestPathEdge:=Edge;
end;
AVLNode:=GraphNode.InTree.FindSuccessor(AVLNode);
end;
end;
finally
WorkNodes.Free;
end;
// build ShortestNodes
if FShortestNodes=nil then
FShortestNodes:=TAVLTree.Create(TListSortCompare(@CompareOverloadsNodesByPathLen))
else
FShortestNodes.Clear;
AVLNode:=Graph.Nodes.FindLowest;
while AVLNode<>nil do begin
GraphNode:=TOverloadsGraphNode(AVLNode.Data);
FShortestNodes.Add(GraphNode);
AVLNode:=Graph.Nodes.FindSuccessor(AVLNode);
end;
end;
{ TOverloadsGraphNode } { TOverloadsGraphNode }
function TOverloadsGraphNode.AsDebugString: string; function TOverloadsGraphNode.AsDebugString: string;
@ -346,5 +466,15 @@ begin
+(ToNode as TOverloadsGraphNode).AsDebugString; +(ToNode as TOverloadsGraphNode).AsDebugString;
end; end;
function TOverloadsGraphEdge.Cost: integer;
begin
case Typ of
ogetParentChild: Result:=10;
ogetAncestorInherited: Result:=1;
ogetAliasOld: Result:=1;
else Result:=100;
end;
end;
end. end.

View File

@ -477,6 +477,7 @@ begin
end else begin end else begin
StageTitle:='Finished'; StageTitle:='Finished';
StagePosition:=StagePosMax; StagePosition:=StagePosMax;
Graph.ComputeShortestPaths;
end; end;
DebugLn(['TFindOverloadsWorker.Work END ',StageTitle,' ',StagePosition,'/',StagePosMax]); DebugLn(['TFindOverloadsWorker.Work END ',StageTitle,' ',StagePosition,'/',StagePosMax]);
end; end;
@ -490,6 +491,7 @@ procedure TFindOverloadsWorker.StopSearching;
begin begin
CompletedScopes:=Scopes; CompletedScopes:=Scopes;
FScanFiles.Clear; FScanFiles.Clear;
Graph.ComputeShortestPaths;
end; end;
initialization initialization