mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-13 05:49:15 +02:00
h2pas: added tool to remove double semicolons
git-svn-id: trunk@12115 -
This commit is contained in:
parent
63185c68cf
commit
3a2a355c95
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user