mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-15 20:59:06 +02:00
codetools: class completion: insert first method body behind/in front of neighbour class
This commit is contained in:
parent
d3a9a217b2
commit
fda255ba15
@ -190,6 +190,11 @@ type
|
|||||||
const FoundContext: TFindContext): TIdentifierFoundResult;
|
const FoundContext: TFindContext): TIdentifierFoundResult;
|
||||||
procedure RemoveNewMainUsesSectionUnit(p: PChar);
|
procedure RemoveNewMainUsesSectionUnit(p: PChar);
|
||||||
protected
|
protected
|
||||||
|
const
|
||||||
|
CreateMethodBodies_ProcAttrBodyDef = [phpWithStart,
|
||||||
|
phpAddClassname,phpWithVarModifiers,
|
||||||
|
phpWithParameterNames,phpWithResultType,
|
||||||
|
phpWithCallingSpecs,phpWithAssembler];
|
||||||
procedure CheckWholeUnitParsed(var Node1, Node2: TCodeTreeNode;
|
procedure CheckWholeUnitParsed(var Node1, Node2: TCodeTreeNode;
|
||||||
Range: TLinkScannerRange = lsrEnd);
|
Range: TLinkScannerRange = lsrEnd);
|
||||||
procedure FreeClassInsertionList;
|
procedure FreeClassInsertionList;
|
||||||
@ -202,6 +207,12 @@ type
|
|||||||
out CommentStart, CommentEnd: integer): boolean;
|
out CommentStart, CommentEnd: integer): boolean;
|
||||||
function FindProcAndClassNode(CursorNode: TCodeTreeNode; out ProcNode,
|
function FindProcAndClassNode(CursorNode: TCodeTreeNode; out ProcNode,
|
||||||
AClassNode: TCodeTreeNode): boolean;
|
AClassNode: TCodeTreeNode): boolean;
|
||||||
|
procedure CreateMethodBodies_Insert(const TheClassName: string;
|
||||||
|
ANodeExt: TCodeTreeNodeExtension; InsertPos, Indent: integer);
|
||||||
|
procedure CreateMethodBodies_CreateCode(TheNodeExt: TCodeTreeNodeExtension; Indent: integer);
|
||||||
|
function CreateMethodBodies_FindNeighbourClass(SearchUp: boolean; StartImpl: TCodeTreeNode): TCodeTreeNode;
|
||||||
|
procedure CreateMethodBodies_FindInsertPointForNewClass(
|
||||||
|
out InsertPos, Indent: LongInt);
|
||||||
function CreateMissingClassProcBodies(UpdateSignatures: boolean): boolean;
|
function CreateMissingClassProcBodies(UpdateSignatures: boolean): boolean;
|
||||||
function ApplyChangesAndJumpToFirstNewProc(CleanPos: integer;
|
function ApplyChangesAndJumpToFirstNewProc(CleanPos: integer;
|
||||||
OldTopLine: integer; AddMissingProcBodies: boolean;
|
OldTopLine: integer; AddMissingProcBodies: boolean;
|
||||||
@ -8757,71 +8768,255 @@ begin
|
|||||||
ExtractClassName(ClassNode,true,true,false));
|
ExtractClassName(ClassNode,true,true,false));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCodeCompletionCodeTool.CreateMissingClassProcBodies(
|
procedure TCodeCompletionCodeTool.CreateMethodBodies_Insert(const TheClassName: string;
|
||||||
UpdateSignatures: boolean): boolean;
|
ANodeExt: TCodeTreeNodeExtension; InsertPos, Indent: integer);
|
||||||
const
|
|
||||||
ProcAttrDefToBody = [phpWithStart,
|
|
||||||
phpAddClassname,phpWithVarModifiers,
|
|
||||||
phpWithParameterNames,phpWithResultType,
|
|
||||||
phpWithCallingSpecs,phpWithAssembler];
|
|
||||||
var
|
var
|
||||||
TheClassName: string;
|
|
||||||
Beauty: TBeautifyCodeOptions;
|
Beauty: TBeautifyCodeOptions;
|
||||||
|
ProcCode: string;
|
||||||
procedure InsertProcBody(ANodeExt: TCodeTreeNodeExtension;
|
begin
|
||||||
InsertPos, Indent: integer);
|
Beauty:=FSourceChangeCache.BeautifyCodeOptions;
|
||||||
var ProcCode: string;
|
if ANodeExt.ExtTxt3<>'' then
|
||||||
begin
|
ProcCode:=ANodeExt.ExtTxt3
|
||||||
if ANodeExt.ExtTxt3<>'' then
|
else
|
||||||
ProcCode:=ANodeExt.ExtTxt3
|
ProcCode:=ANodeExt.ExtTxt1;
|
||||||
else
|
ProcCode:=Beauty.AddClassAndNameToProc(ProcCode,TheClassName,'');
|
||||||
ProcCode:=ANodeExt.ExtTxt1;
|
{$IFDEF CTDEBUG}
|
||||||
ProcCode:=Beauty.AddClassAndNameToProc(ProcCode,TheClassName,'');
|
DebugLn('CreateMethodBodies_Insert ',TheClassName,' "',ProcCode,'"');
|
||||||
|
{$ENDIF}
|
||||||
|
ProcCode:=Beauty.BeautifyProc(ProcCode,Indent,ANodeExt.ExtTxt3='');
|
||||||
|
FSourceChangeCache.Replace(gtEmptyLine,gtEmptyLine,InsertPos,InsertPos,ProcCode);
|
||||||
|
if FJumpToProcHead.Name='' then begin
|
||||||
|
// remember one proc body to jump to after the completion
|
||||||
|
FJumpToProcHead.Name:=ANodeExt.Txt;
|
||||||
|
FJumpToProcHead.Group:=TPascalMethodGroup(ANodeExt.Flags);
|
||||||
|
FJumpToProcHead.ResultType:=ANodeExt.ExtTxt4;
|
||||||
|
if System.Pos('.',FJumpToProcHead.Name)<1 then
|
||||||
|
FJumpToProcHead.Name:=TheClassName+'.'+FJumpToProcHead.Name;
|
||||||
|
if FJumpToProcHead.Name[length(FJumpToProcHead.Name)]<>';' then
|
||||||
|
FJumpToProcHead.Name:=FJumpToProcHead.Name+';';
|
||||||
{$IFDEF CTDEBUG}
|
{$IFDEF CTDEBUG}
|
||||||
DebugLn('CreateMissingClassProcBodies InsertProcBody ',TheClassName,' "',ProcCode,'"');
|
DebugLn('CreateMethodBodies_Insert FJumpToProcHead.Name="',FJumpToProcHead.Name,'"');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
ProcCode:=Beauty.BeautifyProc(ProcCode,Indent,ANodeExt.ExtTxt3='');
|
end;
|
||||||
FSourceChangeCache.Replace(gtEmptyLine,gtEmptyLine,InsertPos,InsertPos,ProcCode);
|
end;
|
||||||
if FJumpToProcHead.Name='' then begin
|
|
||||||
// remember one proc body to jump to after the completion
|
procedure TCodeCompletionCodeTool.CreateMethodBodies_CreateCode(
|
||||||
FJumpToProcHead.Name:=ANodeExt.Txt;
|
TheNodeExt: TCodeTreeNodeExtension; Indent: integer);
|
||||||
FJumpToProcHead.Group:=TPascalMethodGroup(ANodeExt.Flags);
|
var
|
||||||
FJumpToProcHead.ResultType:=ANodeExt.ExtTxt4;
|
Beauty: TBeautifyCodeOptions;
|
||||||
if System.Pos('.',FJumpToProcHead.Name)<1 then
|
ANode: TCodeTreeNode;
|
||||||
FJumpToProcHead.Name:=TheClassName+'.'+FJumpToProcHead.Name;
|
ProcCode: string;
|
||||||
if FJumpToProcHead.Name[length(FJumpToProcHead.Name)]<>';' then
|
begin
|
||||||
FJumpToProcHead.Name:=FJumpToProcHead.Name+';';
|
Beauty:=FSourceChangeCache.BeautifyCodeOptions;
|
||||||
{$IFDEF CTDEBUG}
|
CheckForOverrideAndAddInheritedCode(TheNodeExt,Indent);
|
||||||
DebugLn('CreateMissingClassProcBodies FJumpToProcHead.Name="',FJumpToProcHead.Name,'"');
|
if (TheNodeExt.ExtTxt1='') and (TheNodeExt.ExtTxt3='') then begin
|
||||||
{$ENDIF}
|
ANode:=TheNodeExt.Node;
|
||||||
|
if (ANode<>nil) and (ANode.Desc=ctnProcedure) then begin
|
||||||
|
ProcCode:=ExtractProcHead(ANode,CreateMethodBodies_ProcAttrBodyDef+[phpWithEmptyParamList]);
|
||||||
|
//debugln(['CreateCodeForMissingProcBody Definition="',ProcCode,'"']);
|
||||||
|
TheNodeExt.ExtTxt3:=Beauty.BeautifyProc(ProcCode,Indent,true);
|
||||||
|
//debugln(['CreateCodeForMissingProcBody Beautified="',TheNodeExt.ExtTxt3,'"']);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure CreateCodeForMissingProcBody(TheNodeExt: TCodeTreeNodeExtension;
|
function TCodeCompletionCodeTool.CreateMethodBodies_FindNeighbourClass(
|
||||||
Indent: integer);
|
SearchUp: boolean; StartImpl: TCodeTreeNode): TCodeTreeNode;
|
||||||
var
|
// If SearchUp=true(false) then search the nearest class declaration
|
||||||
ANode: TCodeTreeNode;
|
// in front of (behind) CodeCompleteClassNode with a method body.
|
||||||
ProcCode: string;
|
// Return the last (first) such method body.
|
||||||
|
var
|
||||||
|
Node, ImplNode, MethodNode: TCodeTreeNode;
|
||||||
|
NeighbourClassName, MethodClassName: String;
|
||||||
|
begin
|
||||||
|
Result:=nil;
|
||||||
|
Node:=CodeCompleteClassNode;
|
||||||
|
repeat
|
||||||
|
if SearchUp then
|
||||||
|
Node:=Node.Prior
|
||||||
|
else
|
||||||
|
Node:=Node.Next;
|
||||||
|
if Node=nil then
|
||||||
|
exit;
|
||||||
|
if Node.Desc in AllClassObjects then begin
|
||||||
|
// a class in front (behind) -> check if it has a method body
|
||||||
|
NeighbourClassName:=ExtractClassName(Node,true,true,false);
|
||||||
|
ImplNode:=StartImpl;
|
||||||
|
MethodNode:=nil;
|
||||||
|
while (ImplNode<>nil) and (ImplNode.Desc<>ctnBeginBlock) do begin
|
||||||
|
if NodeIsMethodBody(ImplNode) then begin
|
||||||
|
MethodClassName:=ExtractClassNameOfProcNode(ImplNode,true);
|
||||||
|
if CompareText(MethodClassName,NeighbourClassName)=0 then
|
||||||
|
begin
|
||||||
|
// neighbour class has a method body
|
||||||
|
// -> get last (first)
|
||||||
|
if (MethodNode=nil)
|
||||||
|
or (SearchUp and (MethodNode.StartPos<ImplNode.StartPos))
|
||||||
|
or ((not SearchUp) and (MethodNode.StartPos>ImplNode.StartPos))
|
||||||
|
then
|
||||||
|
MethodNode:=ImplNode;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
ImplNode:=ImplNode.NextBrother;
|
||||||
|
end;
|
||||||
|
if MethodNode<>nil then
|
||||||
|
exit(MethodNode);
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCodeCompletionCodeTool.CreateMethodBodies_FindInsertPointForNewClass(
|
||||||
|
out InsertPos, Indent: LongInt);
|
||||||
|
// find a nice insert position for the first method body of the current class
|
||||||
|
var
|
||||||
|
Beauty: TBeautifyCodeOptions;
|
||||||
|
|
||||||
|
procedure SetIndentAndInsertPos(Node: TCodeTreeNode; Behind: boolean);
|
||||||
begin
|
begin
|
||||||
CheckForOverrideAndAddInheritedCode(TheNodeExt,Indent);
|
Indent:=Beauty.GetLineIndent(Src,Node.StartPos);
|
||||||
if (TheNodeExt.ExtTxt1='') and (TheNodeExt.ExtTxt3='') then begin
|
if Behind then
|
||||||
ANode:=TheNodeExt.Node;
|
InsertPos:=FindLineEndOrCodeAfterPosition(Node.EndPos)
|
||||||
if (ANode<>nil) and (ANode.Desc=ctnProcedure) then begin
|
else
|
||||||
ProcCode:=ExtractProcHead(ANode,ProcAttrDefToBody+[phpWithEmptyParamList]);
|
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Node.StartPos);
|
||||||
//debugln(['CreateCodeForMissingProcBody Definition="',ProcCode,'"']);
|
end;
|
||||||
TheNodeExt.ExtTxt3:=Beauty.BeautifyProc(ProcCode,Indent,true);
|
|
||||||
//debugln(['CreateCodeForMissingProcBody Beautified="',TheNodeExt.ExtTxt3,'"']);
|
procedure SetInsertPosBehindProc(ProcNode: TCodeTreeNode);
|
||||||
|
begin
|
||||||
|
SetIndentAndInsertPos(ProcNode,true);
|
||||||
|
InsertPos:=SkipResourceDirective(InsertPos);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure SetInsertPosInFrontOfProc(ProcNode: TCodeTreeNode);
|
||||||
|
begin
|
||||||
|
// the comments in front of the method probably belong to the class
|
||||||
|
// Therefore insert behind the node in front of the first method
|
||||||
|
Indent:=Beauty.GetLineIndent(Src,ProcNode.StartPos);
|
||||||
|
if ProcNode.PriorBrother<>nil then begin
|
||||||
|
InsertPos:=FindLineEndOrCodeAfterPosition(ProcNode.PriorBrother.EndPos);
|
||||||
|
end else begin
|
||||||
|
InsertPos:=ProcNode.Parent.StartPos;
|
||||||
|
while (InsertPos<=ProcNode.StartPos)
|
||||||
|
and (not IsSpaceChar[Src[InsertPos]]) do
|
||||||
|
inc(InsertPos);
|
||||||
|
end;
|
||||||
|
InsertPos:=SkipResourceDirective(InsertPos);
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
StartSearchProc, NearestProcNode, UnitInterfaceNode, ImplementationNode: TCodeTreeNode;
|
||||||
|
begin
|
||||||
|
Beauty:=FSourceChangeCache.BeautifyCodeOptions;
|
||||||
|
InsertPos:=0;
|
||||||
|
Indent:=0;
|
||||||
|
ImplementationNode:=FindImplementationNode;
|
||||||
|
StartSearchProc:=nil;
|
||||||
|
UnitInterfaceNode:=FindInterfaceNode;
|
||||||
|
if (UnitInterfaceNode<>nil)
|
||||||
|
and CodeCompleteClassNode.HasAsParent(UnitInterfaceNode) then begin
|
||||||
|
// class is in interface section
|
||||||
|
// -> insert at the end of the implementation section
|
||||||
|
if ImplementationNode=nil then begin
|
||||||
|
// there is no implementation section -> create it
|
||||||
|
InsertPos:=UnitInterfaceNode.EndPos;
|
||||||
|
Indent:=Beauty.GetLineIndent(Src,UnitInterfaceNode.StartPos);
|
||||||
|
if not CodeCompleteSrcChgCache.Replace(gtNewLine,gtNewLine,InsertPos,InsertPos,
|
||||||
|
CodeCompleteSrcChgCache.BeautifyCodeOptions.BeautifyKeyWord('implementation'))
|
||||||
|
then begin
|
||||||
|
MoveCursorToCleanPos(InsertPos);
|
||||||
|
RaiseException(20170421201812,'unable to insert implementation section (read only?)');
|
||||||
|
end;
|
||||||
|
exit;
|
||||||
|
end else if (ImplementationNode.FirstChild=nil)
|
||||||
|
or (ImplementationNode.FirstChild.Desc=ctnBeginBlock) then begin
|
||||||
|
// implementation section is empty
|
||||||
|
Indent:=Beauty.GetLineIndent(Src,ImplementationNode.StartPos);
|
||||||
|
if ImplementationNode.FirstChild<>nil then
|
||||||
|
InsertPos:=ImplementationNode.FirstChild.StartPos
|
||||||
|
else
|
||||||
|
InsertPos:=ImplementationNode.EndPos;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// search neighbour class in front and insert behind its method bodies
|
||||||
|
NearestProcNode:=CreateMethodBodies_FindNeighbourClass(true,ImplementationNode.FirstChild);
|
||||||
|
if NearestProcNode<>nil then begin
|
||||||
|
SetInsertPosBehindProc(NearestProcNode);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
// search neighbour class behind and insert in front of its method bodies
|
||||||
|
NearestProcNode:=CreateMethodBodies_FindNeighbourClass(false,ImplementationNode.FirstChild);
|
||||||
|
if NearestProcNode<>nil then begin
|
||||||
|
SetInsertPosInFrontOfProc(NearestProcNode);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
StartSearchProc:=ImplementationNode.FirstChild;
|
||||||
|
end else begin
|
||||||
|
// class is not in interface section
|
||||||
|
StartSearchProc:=CodeCompleteClassNode.GetTopMostNodeOfType(ctnTypeSection);
|
||||||
|
end;
|
||||||
|
case Beauty.ForwardProcBodyInsertPolicy of
|
||||||
|
fpipInFrontOfMethods:
|
||||||
|
begin
|
||||||
|
// Try to insert new proc in front of existing methods
|
||||||
|
|
||||||
|
// find first method
|
||||||
|
NearestProcNode:=StartSearchProc;
|
||||||
|
while (NearestProcNode<>nil) and (NearestProcNode.Desc<>ctnBeginBlock)
|
||||||
|
and (not NodeIsMethodBody(NearestProcNode)) do
|
||||||
|
NearestProcNode:=NearestProcNode.NextBrother;
|
||||||
|
if NearestProcNode<>nil then begin
|
||||||
|
SetInsertPosInFrontOfProc(NearestProcNode);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
fpipBehindMethods:
|
||||||
|
begin
|
||||||
|
// Try to insert new proc behind existing methods
|
||||||
|
|
||||||
|
// find last method (go to last brother and search backwards)
|
||||||
|
if (StartSearchProc<>nil) and (StartSearchProc.Parent<>nil) then
|
||||||
|
NearestProcNode:=StartSearchProc.Parent.LastChild
|
||||||
|
else
|
||||||
|
NearestProcNode:=nil;
|
||||||
|
while (NearestProcNode<>nil) and (not NodeIsMethodBody(NearestProcNode)) do
|
||||||
|
NearestProcNode:=NearestProcNode.PriorBrother;
|
||||||
|
if NearestProcNode<>nil then begin
|
||||||
|
SetInsertPosBehindProc(NearestProcNode);
|
||||||
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Default position: Insert behind last node
|
||||||
|
if (StartSearchProc<>nil)
|
||||||
|
and (StartSearchProc.Parent<>nil) then begin
|
||||||
|
NearestProcNode:=StartSearchProc.Parent.LastChild;
|
||||||
|
if NearestProcNode.Desc=ctnBeginBlock then
|
||||||
|
NearestProcNode:=NearestProcNode.PriorBrother;
|
||||||
|
end;
|
||||||
|
if NearestProcNode<>nil then begin
|
||||||
|
Indent:=0;
|
||||||
|
SetIndentAndInsertPos(NearestProcNode,true);
|
||||||
|
InsertPos:=SkipResourceDirective(InsertPos);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
RaiseException(20170421201815,'TCodeCompletionCodeTool.CreateMissingClassProcBodies.FindInsertPointForNewClass '
|
||||||
|
+' Internal Error: no insert position found');
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TCodeCompletionCodeTool.CreateMissingClassProcBodies(
|
||||||
|
UpdateSignatures: boolean): boolean;
|
||||||
var
|
var
|
||||||
|
TheClassName: string;
|
||||||
|
Beauty: TBeautifyCodeOptions;
|
||||||
ProcBodyNodes, ClassProcs: TAVLTree;
|
ProcBodyNodes, ClassProcs: TAVLTree;
|
||||||
ANodeExt, ANodeExt2: TCodeTreeNodeExtension;
|
ANodeExt, ANodeExt2: TCodeTreeNodeExtension;
|
||||||
ExistingNode, MissingNode, AnAVLNode, NextAVLNode,
|
ExistingNode, MissingNode, AnAVLNode, NextAVLNode,
|
||||||
NearestAVLNode: TAVLTreeNode;
|
NearestAVLNode: TAVLTreeNode;
|
||||||
cmp, MissingNodePosition: integer;
|
cmp, MissingNodePosition: integer;
|
||||||
FirstExistingProcBody, LastExistingProcBody, ImplementationNode,
|
FirstExistingProcBody, LastExistingProcBody,
|
||||||
ANode, ANode2: TCodeTreeNode;
|
ANode, ANode2: TCodeTreeNode;
|
||||||
ClassStartComment, s: string;
|
ClassStartComment, s: string;
|
||||||
Caret1, Caret2: TCodeXYPosition;
|
Caret1, Caret2: TCodeXYPosition;
|
||||||
@ -8829,6 +9024,8 @@ var
|
|||||||
NearestNodeValid: boolean;
|
NearestNodeValid: boolean;
|
||||||
|
|
||||||
procedure FindTopMostAndBottomMostProcBodies;
|
procedure FindTopMostAndBottomMostProcBodies;
|
||||||
|
var
|
||||||
|
ANode: TCodeTreeNode;
|
||||||
begin
|
begin
|
||||||
ExistingNode:=ProcBodyNodes.FindLowest;
|
ExistingNode:=ProcBodyNodes.FindLowest;
|
||||||
if ExistingNode<>nil then
|
if ExistingNode<>nil then
|
||||||
@ -8881,120 +9078,6 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure FindInsertPointForNewClass(out InsertPos, Indent: LongInt);
|
|
||||||
|
|
||||||
procedure SetIndentAndInsertPos(Node: TCodeTreeNode; Behind: boolean);
|
|
||||||
begin
|
|
||||||
Indent:=Beauty.GetLineIndent(Src,Node.StartPos);
|
|
||||||
if Behind then
|
|
||||||
InsertPos:=FindLineEndOrCodeAfterPosition(Node.EndPos)
|
|
||||||
else
|
|
||||||
InsertPos:=FindLineEndOrCodeInFrontOfPosition(Node.StartPos);
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
StartSearchProc: TCodeTreeNode;
|
|
||||||
NearestProcNode: TCodeTreeNode;
|
|
||||||
UnitInterfaceNode: TCodeTreeNode;
|
|
||||||
begin
|
|
||||||
InsertPos:=0;
|
|
||||||
Indent:=0;
|
|
||||||
ImplementationNode:=FindImplementationNode;
|
|
||||||
StartSearchProc:=nil;
|
|
||||||
UnitInterfaceNode:=FindInterfaceNode;
|
|
||||||
if (UnitInterfaceNode<>nil)
|
|
||||||
and CodeCompleteClassNode.HasAsParent(UnitInterfaceNode) then begin
|
|
||||||
// class is in interface section
|
|
||||||
// -> insert at the end of the implementation section
|
|
||||||
if ImplementationNode=nil then begin
|
|
||||||
// create implementation section
|
|
||||||
InsertPos:=UnitInterfaceNode.EndPos;
|
|
||||||
Indent:=Beauty.GetLineIndent(Src,UnitInterfaceNode.StartPos);
|
|
||||||
if not CodeCompleteSrcChgCache.Replace(gtNewLine,gtNewLine,InsertPos,InsertPos,
|
|
||||||
CodeCompleteSrcChgCache.BeautifyCodeOptions.BeautifyKeyWord('implementation'))
|
|
||||||
then begin
|
|
||||||
MoveCursorToCleanPos(InsertPos);
|
|
||||||
RaiseException(20170421201812,'unable to insert implementation section (read only?)');
|
|
||||||
end;
|
|
||||||
exit;
|
|
||||||
end else if (ImplementationNode.FirstChild=nil)
|
|
||||||
or (ImplementationNode.FirstChild.Desc=ctnBeginBlock) then begin
|
|
||||||
// implementation is empty
|
|
||||||
Indent:=Beauty.GetLineIndent(Src,ImplementationNode.StartPos);
|
|
||||||
if ImplementationNode.FirstChild<>nil then
|
|
||||||
InsertPos:=ImplementationNode.FirstChild.StartPos
|
|
||||||
else
|
|
||||||
InsertPos:=ImplementationNode.EndPos;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
StartSearchProc:=ImplementationNode.FirstChild;
|
|
||||||
end else begin
|
|
||||||
// class is not in interface section
|
|
||||||
StartSearchProc:=CodeCompleteClassNode.GetTopMostNodeOfType(ctnTypeSection);
|
|
||||||
end;
|
|
||||||
case Beauty.ForwardProcBodyInsertPolicy of
|
|
||||||
fpipInFrontOfMethods:
|
|
||||||
begin
|
|
||||||
// Try to insert new proc in front of existing methods
|
|
||||||
|
|
||||||
// find first method
|
|
||||||
NearestProcNode:=StartSearchProc;
|
|
||||||
while (NearestProcNode<>nil) and (NearestProcNode.Desc<>ctnBeginBlock)
|
|
||||||
and (not NodeIsMethodBody(NearestProcNode)) do
|
|
||||||
NearestProcNode:=NearestProcNode.NextBrother;
|
|
||||||
if NearestProcNode<>nil then begin
|
|
||||||
// the comments in front of the first method probably belong to the class
|
|
||||||
// Therefore insert behind the node in front of the first method
|
|
||||||
Indent:=Beauty.GetLineIndent(Src,NearestProcNode.StartPos);
|
|
||||||
if NearestProcNode.PriorBrother<>nil then begin
|
|
||||||
InsertPos:=FindLineEndOrCodeAfterPosition(NearestProcNode.PriorBrother.EndPos);
|
|
||||||
end else begin
|
|
||||||
InsertPos:=NearestProcNode.Parent.StartPos;
|
|
||||||
while (InsertPos<=NearestProcNode.StartPos)
|
|
||||||
and (not IsSpaceChar[Src[InsertPos]]) do
|
|
||||||
inc(InsertPos);
|
|
||||||
end;
|
|
||||||
InsertPos:=SkipResourceDirective(InsertPos);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
fpipBehindMethods:
|
|
||||||
begin
|
|
||||||
// Try to insert new proc behind existing methods
|
|
||||||
|
|
||||||
// find last method (go to last brother and search backwards)
|
|
||||||
if (StartSearchProc<>nil) and (StartSearchProc.Parent<>nil) then
|
|
||||||
NearestProcNode:=StartSearchProc.Parent.LastChild
|
|
||||||
else
|
|
||||||
NearestProcNode:=nil;
|
|
||||||
while (NearestProcNode<>nil) and (not NodeIsMethodBody(NearestProcNode)) do
|
|
||||||
NearestProcNode:=NearestProcNode.PriorBrother;
|
|
||||||
if NearestProcNode<>nil then begin
|
|
||||||
SetIndentAndInsertPos(NearestProcNode,NearestProcNode.Desc<>ctnBeginBlock);
|
|
||||||
InsertPos:=SkipResourceDirective(InsertPos);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Default position: Insert behind last node
|
|
||||||
if (StartSearchProc<>nil)
|
|
||||||
and (StartSearchProc.Parent<>nil) then begin
|
|
||||||
NearestProcNode:=StartSearchProc.Parent.LastChild;
|
|
||||||
if NearestProcNode.Desc=ctnBeginBlock then
|
|
||||||
NearestProcNode:=NearestProcNode.PriorBrother;
|
|
||||||
end;
|
|
||||||
if NearestProcNode<>nil then begin
|
|
||||||
Indent:=0;
|
|
||||||
SetIndentAndInsertPos(NearestProcNode,true);
|
|
||||||
InsertPos:=SkipResourceDirective(InsertPos);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
|
|
||||||
RaiseException(20170421201815,'TCodeCompletionCodeTool.CreateMissingClassProcBodies.FindInsertPointForNewClass '
|
|
||||||
+' Internal Error: no insert position found');
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure InsertClassMethodsComment(InsertPos, Indent: integer);
|
procedure InsertClassMethodsComment(InsertPos, Indent: integer);
|
||||||
var
|
var
|
||||||
CommentStartPos: integer;
|
CommentStartPos: integer;
|
||||||
@ -9093,7 +9176,7 @@ begin
|
|||||||
{$IFDEF VerboseCreateMissingClassProcBodies}
|
{$IFDEF VerboseCreateMissingClassProcBodies}
|
||||||
debugln(['TCodeCompletionCodeTool.CreateMissingClassProcBodies Beauty.UpdateAllMethodSignatures=',Beauty.UpdateAllMethodSignatures,' ',OnlyNode<>nil]);
|
debugln(['TCodeCompletionCodeTool.CreateMissingClassProcBodies Beauty.UpdateAllMethodSignatures=',Beauty.UpdateAllMethodSignatures,' ',OnlyNode<>nil]);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if not UpdateProcBodySignatures(ClassProcs,ProcBodyNodes,ProcAttrDefToBody,
|
if not UpdateProcBodySignatures(ClassProcs,ProcBodyNodes,CreateMethodBodies_ProcAttrBodyDef,
|
||||||
ProcsCopied,OnlyNode)
|
ProcsCopied,OnlyNode)
|
||||||
then exit;
|
then exit;
|
||||||
end;
|
end;
|
||||||
@ -9160,7 +9243,7 @@ begin
|
|||||||
{$IF defined(CTDEBUG) or defined(VerboseCreateMissingClassProcBodies)}
|
{$IF defined(CTDEBUG) or defined(VerboseCreateMissingClassProcBodies)}
|
||||||
DebugLn('TCodeCompletionCodeTool.CreateMissingClassProcBodies Starting class in implementation ');
|
DebugLn('TCodeCompletionCodeTool.CreateMissingClassProcBodies Starting class in implementation ');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
FindInsertPointForNewClass(InsertPos,Indent);
|
CreateMethodBodies_FindInsertPointForNewClass(InsertPos,Indent);
|
||||||
{$IFDEF VerboseCreateMissingClassProcBodies}
|
{$IFDEF VerboseCreateMissingClassProcBodies}
|
||||||
debugln(['TCodeCompletionCodeTool.CreateMissingClassProcBodies Indent=',Indent,' InsertPos=',dbgstr(copy(Src,InsertPos-10,10)),'|',dbgstr(copy(Src,InsertPos,10))]);
|
debugln(['TCodeCompletionCodeTool.CreateMissingClassProcBodies Indent=',Indent,' InsertPos=',dbgstr(copy(Src,InsertPos-10,10)),'|',dbgstr(copy(Src,InsertPos,10))]);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -9172,8 +9255,8 @@ begin
|
|||||||
ANodeExt:=TCodeTreeNodeExtension(MissingNode.Data);
|
ANodeExt:=TCodeTreeNodeExtension(MissingNode.Data);
|
||||||
MissingNode:=ClassProcs.FindPrecessor(MissingNode);
|
MissingNode:=ClassProcs.FindPrecessor(MissingNode);
|
||||||
if ProcNodeHasSpecifier(ANodeExt.Node,psEXTERNAL) then continue;
|
if ProcNodeHasSpecifier(ANodeExt.Node,psEXTERNAL) then continue;
|
||||||
CreateCodeForMissingProcBody(ANodeExt,Indent);
|
CreateMethodBodies_CreateCode(ANodeExt,Indent);
|
||||||
InsertProcBody(ANodeExt,InsertPos,Indent);
|
CreateMethodBodies_Insert(TheClassName,ANodeExt,InsertPos,Indent);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end else begin
|
end else begin
|
||||||
@ -9268,8 +9351,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
CreateCodeForMissingProcBody(ANodeExt,Indent);
|
CreateMethodBodies_CreateCode(ANodeExt,Indent);
|
||||||
InsertProcBody(ANodeExt,InsertPos,0);
|
CreateMethodBodies_Insert(TheClassName,ANodeExt,InsertPos,0);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user