codetools: added function to move pointer types to there refering types

git-svn-id: trunk@11841 -
This commit is contained in:
mattias 2007-08-21 17:34:44 +00:00
parent 898efab50a
commit ce4bd7e89a
4 changed files with 156 additions and 19 deletions

View File

@ -2072,6 +2072,8 @@ end;
function TCodeCompletionCodeTool.FixForwardDefinitions(
SourceChangeCache: TSourceChangeCache): boolean;
const
NodeMovedFlag = 1;
var
NodeMoves: TCodeGraph;// an edge means, move the FromNode in front of the ToNode
@ -2093,30 +2095,64 @@ var
NodeMoves.AddEdge(Node,InsertInFrontOf);
end;
function ApplyNodeMove(GraphEdge: TCodeGraphEdge): boolean;
function WholeSectionIsMoved(SectionNode: TCodeTreeNode): boolean;
var
MoveNode: TCodeTreeNode;
ToNode: TCodeTreeNode;
Node: TCodeTreeNode;
GraphNode: TCodeGraphNode;
begin
Result:=false;
MoveNode:=GraphEdge.FromNode.Node;
ToNode:=GraphEdge.ToNode.Node;
DebugLn(['ApplyNodeMove Node=',ExtractNode(MoveNode,[]),' To=',ExtractNode(ToNode,[])]);
Node:=SectionNode.FirstChild;
while Node<>nil do begin
GraphNode:=NodeMoves.GetGraphNode(Node,false);
if (GraphNode=nil) or (GraphNode.OutTreeCount=0) then
exit(false);
Node:=Node.NextBrother;
end;
Result:=true;
end;
function ApplyNodeMoves(GraphNode: TCodeGraphNode): boolean;
function ApplyNodeMove(GraphNode: TCodeGraphNode; MoveNode: boolean;
InsertPos, Indent: integer): boolean;
// if MoveNode=true then move code of GraphNode.Node to InsertPos
// Always: recursively all nodes that should be moved to GraphNode too
var
AVLNode: TAVLTreeNode;
GraphEdge: TCodeGraphEdge;
Node: TCodeTreeNode;
FromPos: LongInt;
ToPos: LongInt;
NodeSrc: String;
begin
Result:=false;
DebugLn(['ApplyNodeMoves ',ExtractNode(GraphNode.Node,[])]);
Node:=GraphNode.Node;
// marked as moved
GraphNode.Flags:=NodeMovedFlag;
DebugLn(['ApplyNodeMoves ',ExtractNode(Node,[])]);
if MoveNode then begin
FromPos:=FindLineEndOrCodeInFrontOfPosition(Node.StartPos);
ToPos:=FindLineEndOrCodeAfterPosition(Node.EndPos);
NodeSrc:=GetIndentStr(Indent)+Trim(copy(Src,FromPos,ToPos-FromPos));
// remove
if (Node.PriorBrother=nil)
and (Node.Parent<>nil) and (Node.Parent.Desc in AllDefinitionSections)
and WholeSectionIsMoved(Node.Parent)
then begin
// the whole section is moved and this is the first node of the section
// remove the section header too
FromPos:=FindLineEndOrCodeInFrontOfPosition(Node.Parent.StartPos);
end;
DebugLn(['ApplyNodeMove Remove: "',copy(Src,FromPos,ToPos-FromPos),'"']);
if not SourceChangeCache.Replace(gtNone,gtNone,FromPos,ToPos,'') then exit;
// insert
DebugLn(['ApplyNodeMove Insert: "',NodeSrc,'"']);
if not SourceChangeCache.Replace(gtNewLine,gtNewLine,
InsertPos,InsertPos,NodeSrc) then exit;
end;
// move dependent nodes
if GraphNode.InTree<>nil then begin
AVLNode:=GraphNode.InTree.FindLowest;
while AVLNode<>nil do begin
GraphEdge:=TCodeGraphEdge(AVLNode.Data);
if not ApplyNodeMove(GraphEdge) then exit;
if not ApplyNodeMove(GraphEdge.FromNode,true,InsertPos,Indent) then exit;
AVLNode:=GraphNode.InTree.FindSuccessor(AVLNode);
end;
end;
@ -2129,10 +2165,19 @@ var
ListOfGraphNodes: TFPList;
i: Integer;
GraphNode: TCodeGraphNode;
InsertPos: LongInt;
Indent: LongInt;
begin
Result:=false;
if NodeMoves.Edges.Count=0 then exit(true);
// check that every node has at most one destination
GraphNode:=NodeMoves.FindGraphNodeWithNumberOfOutEdges(2,-1);
if GraphNode<>nil then begin
DebugLn(['TCodeCompletionCodeTool.FixForwardDefinitions.ApplyNodeMoves inconsistency: node should be moved to several places: ',ExtractNode(GraphNode.Node,[])]);
raise Exception.Create('TCodeCompletionCodeTool.FixForwardDefinitions.ApplyNodeMoves node should be moved to several places');
end;
// sort topologically and break all circles
repeat
GraphEdge:=NodeMoves.GetTopologicalSortedList(ListOfGraphNodes);
@ -2145,9 +2190,14 @@ var
// apply changes
// the ListOfGraphNodes is sorted topologically with nodes at end must be
// moved first
NodeMoves.ClearNodeFlags;
for i:=ListOfGraphNodes.Count-1 downto 0 do begin
GraphNode:=TCodeGraphNode(ListOfGraphNodes[i]);
if not ApplyNodeMoves(GraphNode) then exit;
if GraphNode.Flags=0 then begin
InsertPos:=FindLineEndOrCodeInFrontOfPosition(GraphNode.Node.StartPos);
Indent:=GetLineIndent(Src,GraphNode.Node.StartPos);
if not ApplyNodeMove(GraphNode,false,InsertPos,Indent) then exit;
end;
end;
Result:=SourceChangeCache.Apply;
end;
@ -2169,6 +2219,7 @@ var
try
// move the pointer types to the same type sections
if not BuildUnitDefinitionGraph(Definitions,Graph,false) then exit;
SourceChangeCache.MainScanner:=Scanner;
if Definitions=nil then exit(true);
InitNodeMoves;

View File

@ -43,7 +43,10 @@ type
Node: TCodeTreeNode;
InTree: TAVLTree;// tree of TCodeGraphEdge sorted for FromNode (ToNode = Self)
OutTree: TAVLTree;// tree of TCodeGraphEdge sorted for ToNode (FromNode = Self)
Data: Pointer;
Data: Pointer; // custom data
Flags: cardinal;// custom flags
function OutTreeCount: integer;
function InTreeCount: integer;
end;
PCodeGraphEdgeKey = ^TCodeGraphEdgeKey;
@ -57,7 +60,8 @@ type
TCodeGraphEdge = class
FromNode: TCodeGraphNode;
ToNode: TCodeGraphNode;
Data: Pointer;
Data: Pointer; // custom data
Flags: cardinal;// custom flags
end;
{ TCodeGraph }
@ -69,12 +73,19 @@ type
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure ClearNodeFlags;
procedure ClearEdgeFlags;
procedure Assign(Source: TCodeGraph);
function CreateCopy: TCodeGraph;
function AddGraphNode(Node: TCodeTreeNode): TCodeGraphNode;
function GetGraphNode(Node: TCodeTreeNode; CreateIfNotExists: boolean
): TCodeGraphNode;
procedure DeleteGraphNode(Node: TCodeTreeNode);
function FindGraphNodeWithNumberOfOutEdges(MinNumber, MaxNumber: integer
): TCodeGraphNode;
function FindGraphNodeWithNumberOfInEdges(MinNumber, MaxNumber: integer
): TCodeGraphNode;
function AddEdge(FromNode, ToNode: TCodeTreeNode): TCodeGraphEdge;
function GetEdge(FromNode, ToNode: TCodeTreeNode;
CreateIfNotExists: boolean): TCodeGraphEdge;
@ -269,6 +280,28 @@ begin
Edges.Clear;
end;
procedure TCodeGraph.ClearNodeFlags;
var
AVLNode: TAVLTreeNode;
begin
AVLNode:=Nodes.FindLowest;
while AVLNode<>nil do begin
TCodeGraphNode(AVLNode.Data).Flags:=0;
AVLNode:=Nodes.FindSuccessor(AVLNode);
end;
end;
procedure TCodeGraph.ClearEdgeFlags;
var
AVLNode: TAVLTreeNode;
begin
AVLNode:=Edges.FindLowest;
while AVLNode<>nil do begin
TCodeGraphEdge(AVLNode.Data).Flags:=0;
AVLNode:=Edges.FindSuccessor(AVLNode);
end;
end;
procedure TCodeGraph.Assign(Source: TCodeGraph);
var
AVLNode: TAVLTreeNode;
@ -367,6 +400,42 @@ begin
GraphNode.Free;
end;
function TCodeGraph.FindGraphNodeWithNumberOfOutEdges(MinNumber,
MaxNumber: integer): TCodeGraphNode;
var
AVLNode: TAVLTreeNode;
Cnt: LongInt;
begin
AVLNode:=Nodes.FindLowest;
while AVLNode<>nil do begin
Result:=TCodeGraphNode(AVLNode.Data);
Cnt:=Result.OutTreeCount;
if ((MinNumber<0) or (MinNumber<=Cnt))
and ((MaxNumber<0) or (MaxNumber>=Cnt)) then
exit;
AVLNode:=Nodes.FindSuccessor(AVLNode);
end;
Result:=nil;
end;
function TCodeGraph.FindGraphNodeWithNumberOfInEdges(MinNumber,
MaxNumber: integer): TCodeGraphNode;
var
AVLNode: TAVLTreeNode;
Cnt: LongInt;
begin
AVLNode:=Nodes.FindLowest;
while AVLNode<>nil do begin
Result:=TCodeGraphNode(AVLNode.Data);
Cnt:=Result.InTreeCount;
if ((MinNumber<0) or (MinNumber<=Cnt))
and ((MaxNumber<0) or (MaxNumber>=Cnt)) then
exit;
AVLNode:=Nodes.FindSuccessor(AVLNode);
end;
Result:=nil;
end;
function TCodeGraph.AddEdge(FromNode, ToNode: TCodeTreeNode): TCodeGraphEdge;
begin
Result:=GetEdge(FromNode,ToNode,true);
@ -543,5 +612,23 @@ begin
Result:=Edges.FindKey(@EdgeKey,@CompareEdgeKeyWithGraphEdge);
end;
{ TCodeGraphNode }
function TCodeGraphNode.OutTreeCount: integer;
begin
if OutTree<>nil then
Result:=OutTree.Count
else
Result:=0;
end;
function TCodeGraphNode.InTreeCount: integer;
begin
if InTree<>nil then
Result:=InTree.Count
else
Result:=0;
end;
end.

View File

@ -26,10 +26,10 @@
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="LCL"/>
<PackageName Value="CodeTools"/>
</Item1>
<Item2>
<PackageName Value="CodeTools"/>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="3">
@ -57,7 +57,6 @@
</SearchPaths>
<CodeGeneration>
<Generate Value="Faster"/>
<TargetCPU Value="arm"/>
</CodeGeneration>
<Other>
<CompilerPath Value="$(CompPath)"/>

View File

@ -31,8 +31,8 @@ program FixDefinitionOrder;
{$mode objfpc}{$H+}
uses
System, Classes, SysUtils, CodeCache, CodeToolManager, FileProcs,
CodeTree, DirectivesTree;
Classes, SysUtils, CodeCache, CodeToolManager, FileProcs, CodeTree,
DirectivesTree;
var
Filename: string;