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;
function FindLineEndOrCodeAfterPosition(const Source: string;
Position, MaxPosition: integer; NestedComments: boolean;
StopAtDirectives: boolean = true): integer;
StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false): integer;
function FindFirstLineEndInFrontOfInCode(const Source: string;
Position, MinPosition: integer; NestedComments: boolean): integer;
function FindFirstLineEndAfterInCode(const Source: string;
@ -1752,10 +1752,32 @@ end;
function FindLineEndOrCodeAfterPosition(const Source: string;
Position, MaxPosition: integer; NestedComments: boolean;
StopAtDirectives: boolean): integer;
StopAtDirectives: boolean; SkipEmptyLines: boolean): integer;
{ search forward for a line end or code
ignore line ends in comments
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;
@ -1809,6 +1831,27 @@ var SrcLen: integer;
end;
Result:=true;
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
SrcLen:=length(Source);
@ -1820,7 +1863,10 @@ begin
'{','(','/':
if not ReadComment(Result) then exit;
#10,#13:
exit;
begin
if SkipEmptyLines then DoSkipEmptyLines(Result);
exit;
end;
#9,' ',';':
inc(Result);
else

View File

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

View File

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

View File

@ -26,28 +26,18 @@
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="LCL"/>
<PackageName Value="CodeTools"/>
</Item1>
<Item2>
<PackageName Value="CodeTools"/>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="3">
<Units Count="1">
<Unit0>
<Filename Value="fixdefinitionorder.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="FixDefinitionOrder"/>
</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>
</ProjectOptions>
<CompilerOptions>

View File

@ -102,8 +102,18 @@ type
end;
{ TRemoveDoubleSemicolons -
Remove double semicolons }
TRemoveDoubleSemicolons = class(TCustomTextConverterTool)
public
class function ClassDescription: string; override;
function Execute(aText: TIDETextConverter): TModalResult; override;
end;
{ TRemoveSystemTypes -
Remove type redefinitons like PLongint }
Remove type redefinitions like PLongint }
TRemoveSystemTypes = class(TCustomTextConverterTool)
public
@ -290,6 +300,7 @@ type
TPostH2PasToolsOption = (
phReplaceUnitFilenameWithUnitName, // Replace "unit filename;" with "unit name;"
phRemoveIncludeDirectives, // remove include directives
phRemoveDoubleSemicolons, // Remove double semicolons
phRemoveSystemTypes, // Remove type redefinitons like PLongint
phFixH2PasMissingIFDEFsInUnit, // add missing IFDEFs for function bodies
phReduceCompilerDirectivesInUnit, // removes unneeded directives
@ -2301,7 +2312,7 @@ end;
class function TRemoveSystemTypes.ClassDescription: string;
begin
Result:='Remove type redefinitons like PLongint';
Result:='Remove type redefinitions like PLongint';
end;
function TRemoveSystemTypes.Execute(aText: TIDETextConverter): TModalResult;
@ -2314,6 +2325,7 @@ begin
Result:=mrCancel;
if aText=nil then exit;
Source:=aText.Source;
Flags:=[sesoReplace,sesoReplaceAll,sesoRegExpr];
Prompt:=false;
SearchFor:='^\s*('
@ -2327,6 +2339,12 @@ begin
+');\s*$';
Result:=IDESearchInText('',Source,SearchFor,'',Flags,Prompt,nil);
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;
end;
@ -3644,6 +3662,8 @@ begin
TReplaceUnitFilenameWithUnitName,Result) then exit;
if not Run(phRemoveIncludeDirectives,
TRemoveIncludeDirectives,Result) then exit;
if not Run(phRemoveDoubleSemicolons,
TRemoveDoubleSemicolons,Result) then exit;
if not Run(phRemoveSystemTypes,
TRemoveSystemTypes,Result) then exit;
if not Run(phFixH2PasMissingIFDEFsInUnit,
@ -3843,4 +3863,70 @@ begin
Result:=mrOk;
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.

View File

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