codetools: class completion: copy one method changes to body

git-svn-id: trunk@18045 -
This commit is contained in:
mattias 2009-01-02 13:25:00 +00:00
parent ff31b3a753
commit ad86924500

View File

@ -5478,10 +5478,10 @@ end;
function TCodeCompletionCodeTool.CreateMissingProcBodies: boolean;
var
Indent, InsertPos: integer;
TheClassName: string;
procedure InsertProcBody(ANodeExt: TCodeTreeNodeExtension);
procedure InsertProcBody(ANodeExt: TCodeTreeNodeExtension;
InsertPos, Indent: integer);
var ProcCode: string;
begin
if ANodeExt.ExtTxt3<>'' then
@ -5508,7 +5508,8 @@ var
end;
end;
procedure CreateCodeForMissingProcBody(TheNodeExt: TCodeTreeNodeExtension);
procedure CreateCodeForMissingProcBody(TheNodeExt: TCodeTreeNodeExtension;
Indent: integer);
var
ANode: TCodeTreeNode;
ProcCode: string;
@ -5597,7 +5598,7 @@ var
end;
end;
procedure CheckForChangedProcs;
function CheckForChangedProcs: boolean;
var
BodyAVLNode: TAVLTreeNode;
BodyNodeExt: TCodeTreeNodeExtension;
@ -5605,7 +5606,13 @@ var
DefsWithoutBodies: TAVLTree;
DefAVLNode: TAVLTreeNode;
DefNodeExt: TCodeTreeNodeExtension;
InsertPos: LongInt;
Indent: LongInt;
BodyProcHeadNode: TCodeTreeNode;
InsertEndPos: LongInt;
ProcCode: String;
begin
Result:=false;
BodiesWithoutDefs:=nil;
DefsWithoutBodies:=nil;
try
@ -5624,24 +5631,57 @@ var
DefAVLNode:=ClassProcs.FindLowest;
while DefAVLNode<>nil do begin
DefNodeExt:=TCodeTreeNodeExtension(DefAVLNode.Data);
DefAVLNode:=ClassProcs.FindSuccessor(DefAVLNode);
if ProcBodyNodes.Find(DefNodeExt)=nil then begin
// move proc definition from ClassProcs to DefsWithoutBodies
DefsWithoutBodies:=TAVLTree.Create(@CompareCodeTreeNodeExt);
DefsWithoutBodies.Add(DefNodeExt);
end;
DefAVLNode:=ClassProcs.FindSuccessor(DefAVLNode);
end;
if DefsWithoutBodies=nil then exit;
if BodiesWithoutDefs.Count<>DefsWithoutBodies.Count then exit;
// there is the same amount of bodies without a def and defs without bodies
// => try to create a mapping
// => try to create a mapping from defs to bodies
if DefsWithoutBodies.Count=1 then begin
// only one method def changed
BodyNodeExt:=TCodeTreeNodeExtension(BodiesWithoutDefs.FindLowest.Data);
DefNodeExt:=TCodeTreeNodeExtension(DefsWithoutBodies.FindLowest.Data);
DefNodeExt.Data:=BodyNodeExt;
end else begin
// no mapping found
// => warn user
ANode:=TCodeTreeNodeExtension(BodiesWithoutDefs.FindLowest.Data).Node;
MoveCursorToNodeStart(ANode.FirstChild);
RaiseException('procedure has no definition in the class');
end;
// replace body proc head(s) with class proc head(s)
DefAVLNode:=DefsWithoutBodies.FindLowest;
while DefAVLNode<>nil do begin
DefNodeExt:=TCodeTreeNodeExtension(DefAVLNode.Data);
BodyNodeExt:=TCodeTreeNodeExtension(DefNodeExt.Data);
BodyNodeExt.Txt:=DefNodeExt.Txt;
BodyProcHeadNode:=BodyNodeExt.Node.FirstChild;
InsertPos:=BodyNodeExt.Node.StartPos;
InsertEndPos:=BodyProcHeadNode.EndPos;
Indent:=GetLineIndent(Src,InsertPos);
ProcCode:=ExtractProcHead(DefNodeExt.Node,[phpWithStart,
phpAddClassname,phpWithVarModifiers,
phpWithParameterNames,phpWithResultType,phpWithCallingSpecs,
phpWithoutSemicolon]);
ProcCode:=ASourceChangeCache.BeautifyCodeOptions.BeautifyProc(
ProcCode,Indent,false);
//debugln(['CheckForChangedProcs OLD=',copy(Src,InsertPos,InsertEndPos-InsertPos),' New=',ProcCode]);
if not ASourceChangeCache.Replace(gtNone,gtNone,InsertPos,InsertEndPos,ProcCode) then
exit;
DefAVLNode:=DefsWithoutBodies.FindSuccessor(DefAVLNode);
end;
finally
BodiesWithoutDefs.Free;
DefsWithoutBodies.Free;
end;
Result:=true;
end;
procedure RemoveAbstractMethods;
@ -5660,8 +5700,10 @@ var
end;
end;
procedure FindInsertPointForNewClass;
procedure FindInsertPointForNewClass(out InsertPos, Indent: LongInt);
begin
InsertPos:=0;
Indent:=0;
if NodeHasParentOfType(FCodeCompleteClassNode,ctnInterface) then begin
// class is in interface section
// -> insert at the end of the implementation section
@ -5692,7 +5734,7 @@ var
end;
end;
procedure InsertClassMethodsComment;
procedure InsertClassMethodsComment(InsertPos, Indent: integer);
var
CommentStart, CommentEnd: TCodeXYPosition;
begin
@ -5713,6 +5755,9 @@ var
ClassStartComment);
end;
var
InsertPos: integer;
Indent: integer;
begin
{$IFDEF CTDEBUG}
DebugLn('TCodeCompletionCodeTool.CreateMissingProcBodies Gather existing method bodies ... ');
@ -5744,7 +5789,7 @@ begin
CheckForDoubleDefinedMethods;
// check for changed procs (existing proc bodies without definitions in the class)
CheckForChangedProcs;
if not CheckForChangedProcs then exit;
// remove abstract methods
RemoveAbstractMethods;
@ -5806,15 +5851,15 @@ begin
{$IFDEF CTDEBUG}
DebugLn('TCodeCompletionCodeTool.CreateMissingProcBodies Starting class in implementation ');
{$ENDIF}
FindInsertPointForNewClass;
InsertClassMethodsComment;
FindInsertPointForNewClass(InsertPos,Indent);
InsertClassMethodsComment(InsertPos,Indent);
// insert all proc bodies
MissingNode:=ClassProcs.FindHighest;
while (MissingNode<>nil) do begin
ANodeExt:=TCodeTreeNodeExtension(MissingNode.Data);
CreateCodeForMissingProcBody(ANodeExt);
InsertProcBody(ANodeExt);
CreateCodeForMissingProcBody(ANodeExt,Indent);
InsertProcBody(ANodeExt,InsertPos,Indent);
MissingNode:=ClassProcs.FindPrecessor(MissingNode);
end;
@ -5838,6 +5883,7 @@ begin
ExistingNode:=ProcBodyNodes.Find(MissingNode.Data);
//DebugLn(['TCodeCompletionCodeTool.CreateMissingProcBodies ANodeExt.Txt=',ANodeExt.Txt,' ExistingNode=',ExistingNode<>nil]);
if ExistingNode=nil then begin
//DebugLn(['TCodeCompletionCodeTool.CreateMissingProcBodies ANodeExt.Txt=',ANodeExt.Txt,' ExistingNode=',TCodeTreeNodeExtension(ExistingNode.Data).Txt]);
// MissingNode does not have a body -> insert proc body
case MethodInsertPolicy of
mipAlphabetically:
@ -5902,8 +5948,8 @@ begin
end;
end;
end;
CreateCodeForMissingProcBody(ANodeExt);
InsertProcBody(ANodeExt);
CreateCodeForMissingProcBody(ANodeExt,Indent);
InsertProcBody(ANodeExt,InsertPos,Indent);
end;
MissingNode:=ClassProcs.FindPrecessor(MissingNode);
end;