h2pas: added tool to remove double semicolons

git-svn-id: trunk@12115 -
This commit is contained in:
mattias 2007-09-21 17:07:15 +00:00
parent 63185c68cf
commit 3a2a355c95
6 changed files with 303 additions and 98 deletions

View File

@ -94,7 +94,7 @@ function FindLineEndOrCodeInFrontOfPosition(const Source: string;
StopAtDirectives: boolean = true): integer; StopAtDirectives: boolean = true): integer;
function FindLineEndOrCodeAfterPosition(const Source: string; function FindLineEndOrCodeAfterPosition(const Source: string;
Position, MaxPosition: integer; NestedComments: boolean; Position, MaxPosition: integer; NestedComments: boolean;
StopAtDirectives: boolean = true): integer; StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false): integer;
function FindFirstLineEndInFrontOfInCode(const Source: string; function FindFirstLineEndInFrontOfInCode(const Source: string;
Position, MinPosition: integer; NestedComments: boolean): integer; Position, MinPosition: integer; NestedComments: boolean): integer;
function FindFirstLineEndAfterInCode(const Source: string; function FindFirstLineEndAfterInCode(const Source: string;
@ -1752,10 +1752,32 @@ end;
function FindLineEndOrCodeAfterPosition(const Source: string; function FindLineEndOrCodeAfterPosition(const Source: string;
Position, MaxPosition: integer; NestedComments: boolean; Position, MaxPosition: integer; NestedComments: boolean;
StopAtDirectives: boolean): integer; StopAtDirectives: boolean; SkipEmptyLines: boolean): integer;
{ search forward for a line end or code { search forward for a line end or code
ignore line ends in comments ignore line ends in comments
Result is Position of Start of Line End Result is Position of Start of Line End
if SkipEmptyLines=true, it will skip empty lines at the end
Examples: | is the Position and # is the Result
1. var i: integer;|#
var j: integer;
2. var i: integer;| (*
*) #var j: integer;
3. SkipEmptyLines=false
var i: integer;|
#
// comment
var j: integer;
4. SkipEmptyLines=true
var i: integer;|
#// comment
var j: integer;
} }
var SrcLen: integer; var SrcLen: integer;
@ -1809,6 +1831,27 @@ var SrcLen: integer;
end; end;
Result:=true; Result:=true;
end; end;
procedure DoSkipEmptyLines(var p: integer);
var
OldPos: LongInt;
begin
OldPos:=p;
repeat
while (p<=SrcLen) and (Source[p] in [' ',#9]) do inc(p);
if (p<=SrcLen) and (Source[p] in [#10,#13]) then begin
// an empty line => skip
OldPos:=p;// remember position in front of new line characters
inc(p);
if (p<=SrcLen) and (Source[p] in [#10,#13]) and (Source[p]<>Source[p-1])
then
inc(p);
end else begin
p:=OldPos;
exit;
end;
until false;
end;
begin begin
SrcLen:=length(Source); SrcLen:=length(Source);
@ -1820,7 +1863,10 @@ begin
'{','(','/': '{','(','/':
if not ReadComment(Result) then exit; if not ReadComment(Result) then exit;
#10,#13: #10,#13:
exit; begin
if SkipEmptyLines then DoSkipEmptyLines(Result);
exit;
end;
#9,' ',';': #9,' ',';':
inc(Result); inc(Result);
else else

View File

@ -1363,54 +1363,82 @@ var
procedure CheckAlias(Node: TCodeTreeNode); procedure CheckAlias(Node: TCodeTreeNode);
var var
WrongType: Boolean;
ReferingNode: TCodeTreeNode; ReferingNode: TCodeTreeNode;
ReferingNodeText: String; ReferingNodeText: String;
ReferingPos: LongInt; ReferingPos: LongInt;
NodeExt: TCodeTreeNodeExtension; NodeExt: TCodeTreeNodeExtension;
AVLNode: TAVLTreeNode; AVLNode: TAVLTreeNode;
begin BracketStartPos: LongInt;
// check if definition is an alias NeededType: TCodeTreeNodeDesc;
// Example: const A = B;
if (Node.Parent=nil) then exit; procedure GetReferingNode;
if not (Node.Parent.Desc in [ctnConstSection,ctnTypeSection]) then exit; begin
// this is a const or type if ReferingNodeText<>'' then exit;
MoveCursorToNodeStart(Node);
ReadNextAtom;
if CurPos.Flag<>cafWord then exit;
ReadNextAtom;
if CurPos.Flag<>cafEqual then exit;
ReadNextAtom;
if CurPos.Flag<>cafWord then exit;
ReferingPos:=CurPos.StartPos;
ReadNextAtom;
if CurPos.Flag<>cafSemicolon then exit;
// this is a const or type alias
//DebugLn(['TCodeCompletionCodeTool.FindAliasDefinitions Alias: ',Node.DescAsString,' ',ExtractNode(Node,[])]);
WrongType:=false;
ReferingNode:=nil;
if OnlyWrongType then begin
ReferingNodeText:=GetIdentifier(@Src[ReferingPos]); ReferingNodeText:=GetIdentifier(@Src[ReferingPos]);
AVLNode:=FindCodeTreeNodeExtAVLNode(AllNodes,ReferingNodeText); AVLNode:=FindCodeTreeNodeExtAVLNode(AllNodes,ReferingNodeText);
if (AVLNode<>nil) then begin if (AVLNode<>nil) then begin
NodeExt:=TCodeTreeNodeExtension(AVLNode.Data); NodeExt:=TCodeTreeNodeExtension(AVLNode.Data);
ReferingNode:=NodeExt.Node; ReferingNode:=NodeExt.Node;
if ReferingNode.Desc<>Node.Desc then begin end;
// this alias has wrong type end;
WrongType:=true;
DebugLn(['TCodeCompletionCodeTool.FindAliasDefinitions Wrong: ',Node.DescAsString,' ',ExtractNode(Node,[]),' ',Node.DescAsString,'<>',ReferingNode.DescAsString]); begin
// check if definition is an alias
// Example: const A = B; or const A = B();
if (Node.Parent=nil) then exit;
if not (Node.Parent.Desc in [ctnConstSection,ctnTypeSection]) then exit;
// this is a const or type
MoveCursorToNodeStart(Node);
// read A
ReadNextAtom;
if CurPos.Flag<>cafWord then exit;
// read =
ReadNextAtom;
if CurPos.Flag<>cafEqual then exit;
// read B
ReadNextAtom;
if CurPos.Flag<>cafWord then exit;
ReferingPos:=CurPos.StartPos;
ReadNextAtom;
if CurPos.Flag=cafRoundBracketOpen then begin
BracketStartPos:=CurPos.StartPos;
ReadTilBracketClose(true);
//BracketEndPos:=CurPos.StartPos;
ReadNextAtom;
end else
BracketStartPos:=0;
if CurPos.Flag<>cafSemicolon then exit;
ReferingNode:=nil;
NeededType:=ctnNone;
if BracketStartPos>0 then begin
if WordIsKeyWord.DoIt(@Src[ReferingPos]) then exit;
// this is a type cast
NeededType:=ctnConstDefinition;
end else begin
// this is a const or type alias
//DebugLn(['TCodeCompletionCodeTool.FindAliasDefinitions Alias: ',Node.DescAsString,' ',ExtractNode(Node,[])]);
if OnlyWrongType then begin
GetReferingNode;
if (ReferingNode<>nil) then begin
NeededType:=ReferingNode.Desc;
end; end;
end; end;
end; end;
if WrongType or (not OnlyWrongType) then begin if NeededType=ctnNone then exit;
if (NeededType<>Node.Desc) or (not OnlyWrongType) then begin
// add alias // add alias
if NeededType<>Node.Desc then begin
DebugLn(['TCodeCompletionCodeTool.FindAliasDefinitions Wrong: ',Node.DescAsString,' ',ExtractNode(Node,[]),' ',Node.DescAsString,'<>',ReferingNode.DescAsString]);
end;
if TreeOfCodeTreeNodeExt=nil then if TreeOfCodeTreeNodeExt=nil then
TreeOfCodeTreeNodeExt:=TAVLTree.Create(@CompareCodeTreeNodeExt); TreeOfCodeTreeNodeExt:=TAVLTree.Create(@CompareCodeTreeNodeExt);
NodeExt:=NodeExtMemManager.NewNode; NodeExt:=NodeExtMemManager.NewNode;
NodeExt.Node:=Node; NodeExt.Node:=Node;
NodeExt.Txt:=GetRedefinitionNodeText(Node); NodeExt.Txt:=GetRedefinitionNodeText(Node);
NodeExt.Data:=ReferingNode; NodeExt.Data:=ReferingNode;
NodeExt.Flags:=NeededType;
TreeOfCodeTreeNodeExt.Add(NodeExt); TreeOfCodeTreeNodeExt.Add(NodeExt);
end; end;
end; end;
@ -1492,7 +1520,7 @@ function TCodeCompletionCodeTool.FixAliasDefinitions(
): boolean; ): boolean;
{ replaces public dummy functions with a constant. { replaces public dummy functions with a constant.
The function body will be removed. The function body will be removed.
See the function FindConstFunctions. See the function FindAliasDefinitions.
} }
function FindReferingNode(DefNode: TCodeTreeNode): TCodeTreeNode; function FindReferingNode(DefNode: TCodeTreeNode): TCodeTreeNode;
var var
@ -1521,6 +1549,7 @@ var
ReferingNodeBehind: TCodeTreeNode; ReferingNodeBehind: TCodeTreeNode;
NewSrc: String; NewSrc: String;
FromPos: LongInt; FromPos: LongInt;
ReferingType: TCodeTreeNodeDesc;
begin begin
Result:=false; Result:=false;
if SourceChangeCache=nil then exit; if SourceChangeCache=nil then exit;
@ -1535,9 +1564,10 @@ begin
NodeExt:=TCodeTreeNodeExtension(AVLNode.Data); NodeExt:=TCodeTreeNodeExtension(AVLNode.Data);
DefNode:=NodeExt.Node; DefNode:=NodeExt.Node;
ReferingNode:=TCodeTreeNode(NodeExt.Data); ReferingNode:=TCodeTreeNode(NodeExt.Data);
ReferingType:=TCodeTreeNodeDesc(NodeExt.Flags);
if (ReferingNode=nil) if (ReferingNode=nil)
or (not (ReferingNode.Desc in [ctnTypeDefinition,ctnConstDefinition])) or (not (ReferingNode.Desc in [ctnTypeDefinition,ctnConstDefinition]))
or (DefNode.Desc=ReferingNode.Desc) then begin or (DefNode.Desc=ReferingType) then begin
TreeOfCodeTreeNodeExt.Delete(AVLNode); TreeOfCodeTreeNodeExt.Delete(AVLNode);
end; end;
AVLNode:=NextAVLNode; AVLNode:=NextAVLNode;
@ -1549,10 +1579,11 @@ begin
NodeExt:=TCodeTreeNodeExtension(AVLNode.Data); NodeExt:=TCodeTreeNodeExtension(AVLNode.Data);
DefNode:=NodeExt.Node; DefNode:=NodeExt.Node;
ReferingNode:=TCodeTreeNode(NodeExt.Data); ReferingNode:=TCodeTreeNode(NodeExt.Data);
ReferingType:=TCodeTreeNodeDesc(NodeExt.Flags);
//DebugLn(['TCodeCompletionCodeTool.FixAliasDefinitions Old=',DefNode.DescAsString,' New=',ReferingNode.DescAsString]); //DebugLn(['TCodeCompletionCodeTool.FixAliasDefinitions Old=',DefNode.DescAsString,' New=',NodeDescToStr(ReferingType)]);
case ReferingNode.Desc of case ReferingType of
ctnTypeDefinition: NewSrc:='type'; ctnTypeDefinition: NewSrc:='type';
ctnConstDefinition: NewSrc:='const'; ctnConstDefinition: NewSrc:='const';
else NewSrc:='bug'; else NewSrc:='bug';
@ -1569,7 +1600,7 @@ begin
// this is not the start of the section // this is not the start of the section
ReferingNodeInFront:=FindReferingNode(DefNode.PriorBrother); ReferingNodeInFront:=FindReferingNode(DefNode.PriorBrother);
if (ReferingNodeInFront=nil) if (ReferingNodeInFront=nil)
or (ReferingNodeInFront.Desc<>ReferingNode.Desc) then begin or (ReferingNodeInFront.Desc<>ReferingType) then begin
// the node in front has a different section // the node in front has a different section
FromPos:=FindLineEndOrCodeInFrontOfPosition(DefNode.StartPos); FromPos:=FindLineEndOrCodeInFrontOfPosition(DefNode.StartPos);
if not SourceChangeCache.Replace(gtEmptyLine,gtNewLine, if not SourceChangeCache.Replace(gtEmptyLine,gtNewLine,
@ -1592,9 +1623,11 @@ begin
ctnConstDefinition: NewSrc:='const'; ctnConstDefinition: NewSrc:='const';
else NewSrc:=''; else NewSrc:='';
end; end;
FromPos:=FindLineEndOrCodeInFrontOfPosition(DefNode.NextBrother.StartPos); if NewSrc<>'' then begin
if not SourceChangeCache.Replace(gtEmptyLine,gtNewLine, FromPos:=FindLineEndOrCodeInFrontOfPosition(DefNode.NextBrother.StartPos);
FromPos,FromPos,NewSrc) then exit; if not SourceChangeCache.Replace(gtEmptyLine,gtNewLine,
FromPos,FromPos,NewSrc) then exit;
end;
end; end;
end; end;
@ -1892,7 +1925,7 @@ var
ResultType: PChar; ResultType: PChar;
begin begin
if (ProcNode=nil) or (ProcNode.Desc<>ctnProcedure) then exit; if (ProcNode=nil) or (ProcNode.Desc<>ctnProcedure) then exit;
DebugLn(['CheckProcNode START ',ExtractProcHead(ProcNode,[])]); //DebugLn(['CheckProcNode START ',ExtractProcHead(ProcNode,[])]);
MoveCursorToNodeStart(ProcNode); MoveCursorToNodeStart(ProcNode);
ReadNextAtom; ReadNextAtom;
// read 'function' // read 'function'
@ -1954,7 +1987,7 @@ var
end; end;
if Node.Desc<>ctnBeginBlock then exit; if Node.Desc<>ctnBeginBlock then exit;
DebugLn(['CheckProcNode has begin block']); //DebugLn(['CheckProcNode has begin block']);
// check begin block is only a single assignment // check begin block is only a single assignment
MoveCursorToNodeStart(Node); MoveCursorToNodeStart(Node);
@ -1982,7 +2015,7 @@ var
// read ) // read )
ReadNextAtom; ReadNextAtom;
if CurPos.Flag<>cafRoundBracketClose then exit; if CurPos.Flag<>cafRoundBracketClose then exit;
DebugLn(['CheckProcNode FOUND']); //DebugLn(['CheckProcNode FOUND']);
// save values // save values
ResultNodeExt:=NodeExtMemManager.NewNode; ResultNodeExt:=NodeExtMemManager.NewNode;
@ -2428,7 +2461,7 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
if Node.Desc=ctnTypeSection then begin if Node.Desc=ctnTypeSection then begin
// remove type section // remove type section
FromPos:=FindLineEndOrCodeInFrontOfPosition(Node.StartPos); FromPos:=FindLineEndOrCodeInFrontOfPosition(Node.StartPos);
ToPos:=FindLineEndOrCodeAfterPosition(Node.EndPos); ToPos:=FindLineEndOrCodeAfterPosition(Node.EndPos,true);
DebugLn(['CreateTypeSectionForCircle Removing type section: ',ExtractCode(FromPos,ToPos,[])]); DebugLn(['CreateTypeSectionForCircle Removing type section: ',ExtractCode(FromPos,ToPos,[])]);
SourceChangeCache.Replace(gtNone,gtNone,FromPos,ToPos,''); SourceChangeCache.Replace(gtNone,gtNone,FromPos,ToPos,'');
// add all types of type section to new type section // add all types of type section to new type section
@ -2457,7 +2490,6 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
if not Result then exit; if not Result then exit;
// rebuild graph // rebuild graph
Result:=UpdateGraph(Definitions,Graph,true); Result:=UpdateGraph(Definitions,Graph,true);
DebugLn(['CreateTypeSectionForCircle ',Src]);
end; end;
function FixCircle(var Definitions: TAVLTree; function FixCircle(var Definitions: TAVLTree;
@ -2553,7 +2585,7 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
try try
Graph.DeleteSelfCircles; Graph.DeleteSelfCircles;
repeat repeat
WriteCodeGraphDebugReport(Graph); //WriteCodeGraphDebugReport(Graph);
CircleEdge:=Graph.GetTopologicalSortedList(ListOfGraphNodes,true,false,false); CircleEdge:=Graph.GetTopologicalSortedList(ListOfGraphNodes,true,false,false);
if CircleEdge=nil then break; if CircleEdge=nil then break;
DebugLn(['FixForwardDefinitions.CheckCircles Circle found containing ', DebugLn(['FixForwardDefinitions.CheckCircles Circle found containing ',
@ -2613,7 +2645,18 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
Node:=GetFirstVarDefSequenceNode(Node); Node:=GetFirstVarDefSequenceNode(Node);
while (Node<>nil) do begin while (Node<>nil) do begin
if not NodeWillBeMoved(Node) then exit(false); if not NodeWillBeMoved(Node) then exit(false);
if (Node.FirstChild<>nil) then break; if (Node.FirstChild<>nil) then break;// this is the last of the sequence
Node:=Node.NextBrother;
end;
Result:=true;
end;
function WholeSectionWillBeMoved(Node: TCodeTreeNode): boolean;
// test, if all child nodes will be moved
begin
Node:=Node.FirstChild;
while (Node<>nil) do begin
if not NodeWillBeMoved(Node) then exit(false);
Node:=Node.NextBrother; Node:=Node.NextBrother;
end; end;
Result:=true; Result:=true;
@ -2622,16 +2665,16 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
var var
AVLNode: TAVLTreeNode; AVLNode: TAVLTreeNode;
CurMove: TNodeMoveEdge; CurMove: TNodeMoveEdge;
GraphNode: TCodeGraphNode; GraphNode: TCodeGraphNode;// move what
PosGraphNode: TCodeGraphNode; PosGraphNode: TCodeGraphNode;// move where (in front of)
Node: TCodeTreeNode; Node: TCodeTreeNode;
FromPos: LongInt; FromPos: LongInt;
ToPos: LongInt; ToPos: LongInt;
DestNode: TCodeTreeNode; DestNode: TCodeTreeNode;
NextAVLNode: TAVLTreeNode; NextAVLNode: TAVLTreeNode;
NextMove: TNodeMoveEdge; NextMove: TNodeMoveEdge;
NextGraphNode: TCodeGraphNode; NextGraphNode: TCodeGraphNode;// move what next
NextPosGraphNode: TCodeGraphNode; NextPosGraphNode: TCodeGraphNode;// move where next (in front of)
NextInsertAtSamePos: boolean; NextInsertAtSamePos: boolean;
NeedSection: TCodeTreeNodeDesc; NeedSection: TCodeTreeNodeDesc;
LastSection: TCodeTreeNodeDesc; LastSection: TCodeTreeNodeDesc;
@ -2640,6 +2683,7 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
Indent: LongInt; Indent: LongInt;
DestSection: TCodeTreeNodeDesc; DestSection: TCodeTreeNodeDesc;
NewTxt: String; NewTxt: String;
DestNodeInFront: TCodeTreeNode;
begin begin
Result:=false; Result:=false;
AVLNode:=TreeOfNodeMoveEdges.FindLowest; AVLNode:=TreeOfNodeMoveEdges.FindLowest;
@ -2647,15 +2691,16 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
LastInsertAtSamePos:=false; LastInsertAtSamePos:=false;
DestNode:=nil; DestNode:=nil;
DestSection:=ctnNone; DestSection:=ctnNone;
// process every move
while AVLNode<>nil do begin while AVLNode<>nil do begin
CurMove:=TNodeMoveEdge(AVLNode.Data); CurMove:=TNodeMoveEdge(AVLNode.Data);
GraphNode:=CurMove.GraphNode; GraphNode:=CurMove.GraphNode;// move what
PosGraphNode:=TCodeGraphNode(GraphNode.Data); PosGraphNode:=TCodeGraphNode(GraphNode.Data);// move where (in front of)
NextAVLNode:=TreeOfNodeMoveEdges.FindSuccessor(AVLNode); NextAVLNode:=TreeOfNodeMoveEdges.FindSuccessor(AVLNode);
if NextAVLNode<>nil then begin if NextAVLNode<>nil then begin
NextMove:=TNodeMoveEdge(NextAVLNode.Data); NextMove:=TNodeMoveEdge(NextAVLNode.Data);
NextGraphNode:=NextMove.GraphNode; NextGraphNode:=NextMove.GraphNode;// move what next
NextPosGraphNode:=TCodeGraphNode(NextGraphNode.Data); NextPosGraphNode:=TCodeGraphNode(NextGraphNode.Data);// move where next
NextInsertAtSamePos:=NextPosGraphNode=PosGraphNode; NextInsertAtSamePos:=NextPosGraphNode=PosGraphNode;
end else begin end else begin
NextInsertAtSamePos:=false; NextInsertAtSamePos:=false;
@ -2669,7 +2714,23 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
DestNode:=PosGraphNode.Node; DestNode:=PosGraphNode.Node;
// remove node // remove node
if Node.Desc=ctnVarDefinition then begin if (Node.Parent<>nil)
and (Node.Parent.Desc in AllDefinitionSections)
and WholeSectionWillBeMoved(Node.Parent) then begin
// the whole type/var/const section will be moved
if Node.PriorBrother=nil then begin
// this is the first node of the section
// => remove the whole section
FromPos:=FindLineEndOrCodeInFrontOfPosition(Node.Parent.StartPos);
ToPos:=FindLineEndOrCodeAfterPosition(Node.Parent.EndPos,true);
end else begin
// this is not the first node of the section
// => remove nothing
FromPos:=0;
ToPos:=0;
end;
end
else if Node.Desc=ctnVarDefinition then begin
// removing a variable definition can be tricky, because for example // removing a variable definition can be tricky, because for example
// var a,b,c: integer; // var a,b,c: integer;
if Node.FirstChild<>nil then begin if Node.FirstChild<>nil then begin
@ -2681,7 +2742,7 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
FromPos:=FindLineEndOrCodeInFrontOfPosition( FromPos:=FindLineEndOrCodeInFrontOfPosition(
GetFirstVarDefSequenceNode(Node).StartPos); GetFirstVarDefSequenceNode(Node).StartPos);
ToPos:=FindLineEndOrCodeAfterPosition( ToPos:=FindLineEndOrCodeAfterPosition(
GetLastVarDefSequenceNode(Node).EndPos); GetLastVarDefSequenceNode(Node).EndPos,true);
end else if NodeWillBeMoved(Node.PriorBrother) then begin end else if NodeWillBeMoved(Node.PriorBrother) then begin
// this is for example: var a,b,c: integer // this is for example: var a,b,c: integer
// and only b and c will be moved. The b, plus the space behind was // and only b and c will be moved. The b, plus the space behind was
@ -2691,8 +2752,7 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
MoveCursorToNodeStart(Node); MoveCursorToNodeStart(Node);
ReadNextAtom;// read identifier ReadNextAtom;// read identifier
AtomIsIdentifier(true); AtomIsIdentifier(true);
ReadNextAtom;// read colon ToPos:=FindLineEndOrCodeAfterPosition(CurPos.EndPos,true);
ToPos:=CurPos.StartPos;
end else begin end else begin
// this is for example: var a,b: integer // this is for example: var a,b: integer
// and only b will be moved. // and only b will be moved.
@ -2717,8 +2777,8 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
FromPos:=0; FromPos:=0;
ToPos:=0; ToPos:=0;
end else begin end else begin
// remove the name plus the next comma // remove the b,
FromPos:=Node.StartPos; FromPos:=FindLineEndOrCodeInFrontOfPosition(Node.StartPos);
MoveCursorToNodeStart(Node); MoveCursorToNodeStart(Node);
ReadNextAtom;// read identifier ReadNextAtom;// read identifier
AtomIsIdentifier(true); AtomIsIdentifier(true);
@ -2738,44 +2798,65 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
exit; exit;
end; end;
// find needed section type
if Node.Desc in AllIdentifierDefinitions then
NeedSection:=Node.Parent.Desc
else
NeedSection:=ctnNone;
// find insert position // find insert position
if not LastInsertAtSamePos then begin if not LastInsertAtSamePos then begin
//DebugLn(['MoveNodes LastInsertAtSamePos=false, compute destination ...']);
if (DestNode.Desc in AllIdentifierDefinitions) then begin if (DestNode.Desc in AllIdentifierDefinitions) then begin
DestNode:=GetFirstVarDefSequenceNode(DestNode); DestNode:=GetFirstVarDefSequenceNode(DestNode);
DestSection:=DestNode.Parent.Desc;
if DestNode.PriorBrother<>nil then begin if DestNode.PriorBrother<>nil then begin
// the destination is in front of a definition, but in the middle // the destination is in front of a definition, but in the middle
// of a section // of a section
// example: type a=char; | b=byte; // example: type a=char; | b=byte;
// => insert in front of destination // => insert in front of destination
DestSection:=DestNode.Parent.Desc; //DebugLn(['MoveNodes destination is middle of a section. Node in front=',GetRedefinitionNodeText(DestNode.PriorBrother)]);
end else begin end else begin
// the destination is the first node of a section // the destination is the first node of a section
// example: type | t=char; // example: type | t=char;
// => insert in front of the section if NeedSection=DestSection then begin
DestNode:=DestNode.Parent; // insertion needs the same section type
DestSection:=DestNode.Desc; // => insert in front of destination
end else begin
// insertion needs another section type
// => insert in front of the section
DestNode:=DestNode.Parent;
end;
//DebugLn(['MoveNodes destination is first node of a section ']);
end; end;
end else begin end else begin
// the destination is not in a section // the destination is not in a section
// example: in front of a type section // example: in front of a type section
// => insert in front of destination // => insert in front of destination
DestSection:=DestNode.Desc; // find the section in front
DestNodeInFront:=DestNode.PriorBrother;
while (DestNodeInFront<>nil) and NodeWillBeMoved(DestNodeInFront) do
DestNodeInFront:=DestNodeInFront.PriorBrother;
if (DestNodeInFront<>nil)
and (DestNodeInFront.Desc in AllDefinitionSections) then
DestSection:=DestNodeInFront.Desc
else
DestSection:=ctnNone;
//DebugLn(['MoveNodes destination is not in a section']);
end; end;
InsertPos:=FindLineEndOrCodeAfterPosition(DestNode.StartPos); InsertPos:=FindLineEndOrCodeAfterPosition(DestNode.StartPos);
Indent:=GetLineIndent(Src,DestNode.StartPos); Indent:=GetLineIndent(Src,DestNode.StartPos);
//DebugLn(['MoveNodes DestNode=',GetRedefinitionNodeText(DestNode),':',DestNode.DescAsString,' DestSection=',NodeDescToStr(DestSection)]);
end; end;
// start a new section if needed // start a new section if needed
if Node.Desc in AllIdentifierDefinitions then //DebugLn(['MoveNodes LastInsertAtSamePos=',LastInsertAtSamePos,' NeedSection=',NodeDescToStr(NeedSection),' LastSection=',NodeDescToStr(LastSection),' DestSection=',NodeDescToStr(DestSection)]);
NeedSection:=Node.Parent.Desc
else
NeedSection:=ctnNone;
if (LastInsertAtSamePos and (NeedSection<>LastSection)) if (LastInsertAtSamePos and (NeedSection<>LastSection))
or ((not LastInsertAtSamePos) and (NeedSection<>DestNode.Desc)) then begin or ((not LastInsertAtSamePos) and (NeedSection<>DestSection)) then begin
// start a new section // start a new section
case NeedSection of case NeedSection of
ctnVarDefinition: NewTxt:='var'; ctnVarSection: NewTxt:='var';
ctnConstDefinition: NewTxt:='const'; ctnConstSection: NewTxt:='const';
ctnResStrSection: NewTxt:='resourcestring'; ctnResStrSection: NewTxt:='resourcestring';
ctnTypeSection: NewTxt:='type'; ctnTypeSection: NewTxt:='type';
ctnLabelSection: NewTxt:='label'; ctnLabelSection: NewTxt:='label';
@ -2787,6 +2868,7 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
InsertPos,InsertPos,NewTxt) InsertPos,InsertPos,NewTxt)
then then
exit; exit;
Indent:=SourceChangeCache.BeautifyCodeOptions.Indent;
end; end;
end; end;
@ -2807,8 +2889,6 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
NewTxt:=ExtractCode(FromPos,ToPos,[phpWithComments]); NewTxt:=ExtractCode(FromPos,ToPos,[phpWithComments]);
end; end;
NewTxt:=GetIndentStr(Indent)+NewTxt; NewTxt:=GetIndentStr(Indent)+NewTxt;
if Node.Desc in AllIdentifierDefinitions then
NewTxt:=GetIndentStr(SourceChangeCache.BeautifyCodeOptions.Indent)+NewTxt;
DebugLn(['MoveNodes insert "',NewTxt,'"']); DebugLn(['MoveNodes insert "',NewTxt,'"']);
if not SourceChangeCache.Replace(gtNewLine,gtNewLine,InsertPos,InsertPos, if not SourceChangeCache.Replace(gtNewLine,gtNewLine,InsertPos,InsertPos,
NewTxt) then exit; NewTxt) then exit;
@ -2864,7 +2944,8 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
ListOfGraphNodes:=nil; ListOfGraphNodes:=nil;
NodeMoveEdges:=TAVLTree.Create(@CompareNodeMoveEdges); NodeMoveEdges:=TAVLTree.Create(@CompareNodeMoveEdges);
try try
WriteCodeGraphDebugReport(Graph); //WriteCodeGraphDebugReport(Graph);
// create a topologically sorted list // create a topologically sorted list
CircleEdge:=Graph.GetTopologicalSortedList(ListOfGraphNodes,false,true,false); CircleEdge:=Graph.GetTopologicalSortedList(ListOfGraphNodes,false,true,false);
if CircleEdge<>nil then if CircleEdge<>nil then
@ -2888,7 +2969,7 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
// init the destinations // init the destinations
for i:=0 to ListOfGraphNodes.Count-1 do begin for i:=0 to ListOfGraphNodes.Count-1 do begin
GraphNode:=TCodeGraphNode(ListOfGraphNodes[i]); GraphNode:=TCodeGraphNode(ListOfGraphNodes[i]);
DebugLn(['CheckOrder ',GetRedefinitionNodeText(GraphNode.Node)]); //DebugLn(['CheckOrder ',GetRedefinitionNodeText(GraphNode.Node)]);
GraphNode.Data:=GraphNode; GraphNode.Data:=GraphNode;
end; end;
// calculate the destinations as minimum of all dependencies // calculate the destinations as minimum of all dependencies
@ -2901,7 +2982,7 @@ function TCodeCompletionCodeTool.FixForwardDefinitions(
// for example: type TMyPointer = TMyInteger; // for example: type TMyPointer = TMyInteger;
// GraphNode.Node is TMyInteger // GraphNode.Node is TMyInteger
// UsedByGraphNode.Node is TMyPointer // UsedByGraphNode.Node is TMyPointer
DebugLn(['CheckOrder GraphNode=',GetRedefinitionNodeText(GraphNode.Node),' UsedBy=',GetRedefinitionNodeText(UsedByGraphNode.Node)]); //DebugLn(['CheckOrder GraphNode=',GetRedefinitionNodeText(GraphNode.Node),' UsedBy=',GetRedefinitionNodeText(UsedByGraphNode.Node)]);
PosGraphNode:=TCodeGraphNode(GraphNode.Data); PosGraphNode:=TCodeGraphNode(GraphNode.Data);
PosUsedByGraphNode:=TCodeGraphNode(UsedByGraphNode.Data); PosUsedByGraphNode:=TCodeGraphNode(UsedByGraphNode.Data);
if PosGraphNode.Node.StartPos>PosUsedByGraphNode.Node.StartPos then if PosGraphNode.Node.StartPos>PosUsedByGraphNode.Node.StartPos then
@ -2951,8 +3032,8 @@ begin
try try
// Workaround: // Workaround:
// move the pointer types to the same type sections // move the pointer types to the same type sections
if not MovePointerTypesToTargetSections(SourceChangeCache) then exit; //if not MovePointerTypesToTargetSections(SourceChangeCache) then exit;
exit(true); //exit(true);
if not BuildUnitDefinitionGraph(Definitions,Graph,true) or (Graph=nil) then if not BuildUnitDefinitionGraph(Definitions,Graph,true) or (Graph=nil) then
exit; exit;

View File

@ -200,7 +200,8 @@ type
ResolveComments: boolean; var SameArea: TAtomPosition); ResolveComments: boolean; var SameArea: TAtomPosition);
procedure GetLineInfo(ACleanPos: integer; procedure GetLineInfo(ACleanPos: integer;
var ALineStart, ALineEnd, AFirstAtomStart, ALastAtomEnd: integer); var ALineStart, ALineEnd, AFirstAtomStart, ALastAtomEnd: integer);
function FindLineEndOrCodeAfterPosition(StartPos: integer): integer; function FindLineEndOrCodeAfterPosition(StartPos: integer;
SkipEmptyLines: boolean = false): integer;
function FindLineEndOrCodeInFrontOfPosition(StartPos: integer): integer; function FindLineEndOrCodeInFrontOfPosition(StartPos: integer): integer;
function FindLineEndOrCodeInFrontOfPosition(StartPos: integer; function FindLineEndOrCodeInFrontOfPosition(StartPos: integer;
StopAtDirectives: boolean): integer; StopAtDirectives: boolean): integer;
@ -2240,8 +2241,8 @@ begin
end; end;
end; end;
function TCustomCodeTool.FindLineEndOrCodeAfterPosition(StartPos: integer function TCustomCodeTool.FindLineEndOrCodeAfterPosition(StartPos: integer;
): integer; SkipEmptyLines: boolean): integer;
{ Searches a nice position in the cleaned source after StartPos. { Searches a nice position in the cleaned source after StartPos.
It will skip any space or comments (not directives) till next It will skip any space or comments (not directives) till next
line end or compiler directive or code or include file end. line end or compiler directive or code or include file end.
@ -2253,7 +2254,7 @@ begin
LinkEnd:=Scanner.LinkCleanedEndPos(LinkIndex); LinkEnd:=Scanner.LinkCleanedEndPos(LinkIndex);
if LinkEnd>StartPos then if LinkEnd>StartPos then
Result:=BasicCodeTools.FindLineEndOrCodeAfterPosition(Src, Result:=BasicCodeTools.FindLineEndOrCodeAfterPosition(Src,
StartPos,LinkEnd-1,Scanner.NestedComments) StartPos,LinkEnd-1,Scanner.NestedComments,true,SkipEmptyLines)
else else
Result:=StartPos; Result:=StartPos;
end; end;

View File

@ -26,28 +26,18 @@
</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="1">
<Unit0> <Unit0>
<Filename Value="fixdefinitionorder.lpr"/> <Filename Value="fixdefinitionorder.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="FixDefinitionOrder"/> <UnitName Value="FixDefinitionOrder"/>
</Unit0> </Unit0>
<Unit1>
<Filename Value="scanexamples/simplefunctions.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="SimpleFunctions"/>
</Unit1>
<Unit2>
<Filename Value="scanexamples/wrongforwarddefinitions.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="WrongForwardDefinitions"/>
</Unit2>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -102,8 +102,18 @@ type
end; end;
{ TRemoveDoubleSemicolons -
Remove double semicolons }
TRemoveDoubleSemicolons = class(TCustomTextConverterTool)
public
class function ClassDescription: string; override;
function Execute(aText: TIDETextConverter): TModalResult; override;
end;
{ TRemoveSystemTypes - { TRemoveSystemTypes -
Remove type redefinitons like PLongint } Remove type redefinitions like PLongint }
TRemoveSystemTypes = class(TCustomTextConverterTool) TRemoveSystemTypes = class(TCustomTextConverterTool)
public public
@ -290,6 +300,7 @@ type
TPostH2PasToolsOption = ( TPostH2PasToolsOption = (
phReplaceUnitFilenameWithUnitName, // Replace "unit filename;" with "unit name;" phReplaceUnitFilenameWithUnitName, // Replace "unit filename;" with "unit name;"
phRemoveIncludeDirectives, // remove include directives phRemoveIncludeDirectives, // remove include directives
phRemoveDoubleSemicolons, // Remove double semicolons
phRemoveSystemTypes, // Remove type redefinitons like PLongint phRemoveSystemTypes, // Remove type redefinitons like PLongint
phFixH2PasMissingIFDEFsInUnit, // add missing IFDEFs for function bodies phFixH2PasMissingIFDEFsInUnit, // add missing IFDEFs for function bodies
phReduceCompilerDirectivesInUnit, // removes unneeded directives phReduceCompilerDirectivesInUnit, // removes unneeded directives
@ -2301,7 +2312,7 @@ end;
class function TRemoveSystemTypes.ClassDescription: string; class function TRemoveSystemTypes.ClassDescription: string;
begin begin
Result:='Remove type redefinitons like PLongint'; Result:='Remove type redefinitions like PLongint';
end; end;
function TRemoveSystemTypes.Execute(aText: TIDETextConverter): TModalResult; function TRemoveSystemTypes.Execute(aText: TIDETextConverter): TModalResult;
@ -2314,6 +2325,7 @@ begin
Result:=mrCancel; Result:=mrCancel;
if aText=nil then exit; if aText=nil then exit;
Source:=aText.Source; Source:=aText.Source;
Flags:=[sesoReplace,sesoReplaceAll,sesoRegExpr]; Flags:=[sesoReplace,sesoReplaceAll,sesoRegExpr];
Prompt:=false; Prompt:=false;
SearchFor:='^\s*(' SearchFor:='^\s*('
@ -2327,6 +2339,12 @@ begin
+');\s*$'; +');\s*$';
Result:=IDESearchInText('',Source,SearchFor,'',Flags,Prompt,nil); Result:=IDESearchInText('',Source,SearchFor,'',Flags,Prompt,nil);
if Result<>mrOk then exit; if Result<>mrOk then exit;
// replace NULL with nil
Flags:=[sesoReplace,sesoReplaceAll,sesoRegExpr,sesoMatchCase];
Result:=IDESearchInText('',Source,'\bNULL\b','nil',Flags,Prompt,nil);
if Result<>mrOk then exit;
aText.Source:=Source; aText.Source:=Source;
end; end;
@ -3644,6 +3662,8 @@ begin
TReplaceUnitFilenameWithUnitName,Result) then exit; TReplaceUnitFilenameWithUnitName,Result) then exit;
if not Run(phRemoveIncludeDirectives, if not Run(phRemoveIncludeDirectives,
TRemoveIncludeDirectives,Result) then exit; TRemoveIncludeDirectives,Result) then exit;
if not Run(phRemoveDoubleSemicolons,
TRemoveDoubleSemicolons,Result) then exit;
if not Run(phRemoveSystemTypes, if not Run(phRemoveSystemTypes,
TRemoveSystemTypes,Result) then exit; TRemoveSystemTypes,Result) then exit;
if not Run(phFixH2PasMissingIFDEFsInUnit, if not Run(phFixH2PasMissingIFDEFsInUnit,
@ -3843,4 +3863,70 @@ begin
Result:=mrOk; Result:=mrOk;
end; end;
{ TRemoveDoubleSemicolons }
class function TRemoveDoubleSemicolons.ClassDescription: string;
begin
Result:='Remove double semicolons';
end;
function TRemoveDoubleSemicolons.Execute(aText: TIDETextConverter
): TModalResult;
var
Position: Integer;
Source, NewSrc: String;
AtomStart: integer;
LastAtomWasSemicolon: Boolean;
SemicolonPositions: array of integer;
SemicolonCount: Integer;
i: Integer;
begin
Result:=mrCancel;
if aText=nil then exit;
Source:=aText.Source;
// find all double semicolons
Position:=1;
LastAtomWasSemicolon:=false;
Setlength(SemicolonPositions,0);
SemicolonCount:=0;
repeat
ReadRawNextPascalAtom(Source,Position,AtomStart,true);
if AtomStart>length(Source) then break;
if Source[AtomStart]=';' then begin
if LastAtomWasSemicolon then begin
if length(SemicolonPositions)<=SemicolonCount then
SetLength(SemicolonPositions,length(SemicolonPositions)*2+2);
SemicolonPositions[SemicolonCount]:=AtomStart;
inc(SemicolonCount);
end;
LastAtomWasSemicolon:=true;
end else begin
LastAtomWasSemicolon:=false;
end;
until false;
// build new source without semicolons
if SemicolonCount>0 then begin
SetLength(NewSrc,length(Source)-SemicolonCount);
AtomStart:=1;
i:=0;
while i<SemicolonCount do begin
Position:=SemicolonPositions[i];
if Position>AtomStart then
System.Move(Source[AtomStart],NewSrc[AtomStart-i],Position-AtomStart);
AtomStart:=Position+1;
inc(i);
end;
Position:=length(Source)+1;
if Position>AtomStart then
System.Move(Source[AtomStart],NewSrc[AtomStart-i],Position-AtomStart);
aText.Source:=NewSrc;
end;
// clean up
Setlength(SemicolonPositions,0);
Result:=mrOk;
end;
end. end.

View File

@ -217,6 +217,7 @@ begin
TextConverterToolClasses.RegisterClass(TConvertFunctionTypesToPointers); TextConverterToolClasses.RegisterClass(TConvertFunctionTypesToPointers);
TextConverterToolClasses.RegisterClass(TPostH2PasTools); TextConverterToolClasses.RegisterClass(TPostH2PasTools);
TextConverterToolClasses.RegisterClass(TReplaceUnitFilenameWithUnitName); TextConverterToolClasses.RegisterClass(TReplaceUnitFilenameWithUnitName);
TextConverterToolClasses.RegisterClass(TRemoveDoubleSemicolons);
TextConverterToolClasses.RegisterClass(TRemoveSystemTypes); TextConverterToolClasses.RegisterClass(TRemoveSystemTypes);
TextConverterToolClasses.RegisterClass(TRemoveRedefinedPointerTypes); TextConverterToolClasses.RegisterClass(TRemoveRedefinedPointerTypes);
TextConverterToolClasses.RegisterClass(TRemoveEmptyTypeVarConstSections); TextConverterToolClasses.RegisterClass(TRemoveEmptyTypeVarConstSections);