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( function TCodeCompletionCodeTool.FixForwardDefinitions(
SourceChangeCache: TSourceChangeCache): boolean; SourceChangeCache: TSourceChangeCache): boolean;
const
NodeMovedFlag = 1;
var var
NodeMoves: TCodeGraph;// an edge means, move the FromNode in front of the ToNode NodeMoves: TCodeGraph;// an edge means, move the FromNode in front of the ToNode
@ -2093,30 +2095,64 @@ var
NodeMoves.AddEdge(Node,InsertInFrontOf); NodeMoves.AddEdge(Node,InsertInFrontOf);
end; end;
function ApplyNodeMove(GraphEdge: TCodeGraphEdge): boolean; function WholeSectionIsMoved(SectionNode: TCodeTreeNode): boolean;
var var
MoveNode: TCodeTreeNode; Node: TCodeTreeNode;
ToNode: TCodeTreeNode; GraphNode: TCodeGraphNode;
begin begin
Result:=false; Node:=SectionNode.FirstChild;
MoveNode:=GraphEdge.FromNode.Node; while Node<>nil do begin
ToNode:=GraphEdge.ToNode.Node; GraphNode:=NodeMoves.GetGraphNode(Node,false);
DebugLn(['ApplyNodeMove Node=',ExtractNode(MoveNode,[]),' To=',ExtractNode(ToNode,[])]); if (GraphNode=nil) or (GraphNode.OutTreeCount=0) then
exit(false);
Node:=Node.NextBrother;
end;
Result:=true;
end; 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 var
AVLNode: TAVLTreeNode; AVLNode: TAVLTreeNode;
GraphEdge: TCodeGraphEdge; GraphEdge: TCodeGraphEdge;
Node: TCodeTreeNode;
FromPos: LongInt;
ToPos: LongInt;
NodeSrc: String;
begin begin
Result:=false; 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 if GraphNode.InTree<>nil then begin
AVLNode:=GraphNode.InTree.FindLowest; AVLNode:=GraphNode.InTree.FindLowest;
while AVLNode<>nil do begin while AVLNode<>nil do begin
GraphEdge:=TCodeGraphEdge(AVLNode.Data); 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); AVLNode:=GraphNode.InTree.FindSuccessor(AVLNode);
end; end;
end; end;
@ -2129,10 +2165,19 @@ var
ListOfGraphNodes: TFPList; ListOfGraphNodes: TFPList;
i: Integer; i: Integer;
GraphNode: TCodeGraphNode; GraphNode: TCodeGraphNode;
InsertPos: LongInt;
Indent: LongInt;
begin begin
Result:=false; Result:=false;
if NodeMoves.Edges.Count=0 then exit(true); 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 // sort topologically and break all circles
repeat repeat
GraphEdge:=NodeMoves.GetTopologicalSortedList(ListOfGraphNodes); GraphEdge:=NodeMoves.GetTopologicalSortedList(ListOfGraphNodes);
@ -2145,9 +2190,14 @@ var
// apply changes // apply changes
// the ListOfGraphNodes is sorted topologically with nodes at end must be // the ListOfGraphNodes is sorted topologically with nodes at end must be
// moved first // moved first
NodeMoves.ClearNodeFlags;
for i:=ListOfGraphNodes.Count-1 downto 0 do begin for i:=ListOfGraphNodes.Count-1 downto 0 do begin
GraphNode:=TCodeGraphNode(ListOfGraphNodes[i]); 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; end;
Result:=SourceChangeCache.Apply; Result:=SourceChangeCache.Apply;
end; end;
@ -2169,6 +2219,7 @@ var
try try
// move the pointer types to the same type sections // move the pointer types to the same type sections
if not BuildUnitDefinitionGraph(Definitions,Graph,false) then exit; if not BuildUnitDefinitionGraph(Definitions,Graph,false) then exit;
SourceChangeCache.MainScanner:=Scanner;
if Definitions=nil then exit(true); if Definitions=nil then exit(true);
InitNodeMoves; InitNodeMoves;

View File

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

View File

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

View File

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