codetools: class completion: update method bodies if all signatures fit

git-svn-id: trunk@30942 -
This commit is contained in:
mattias 2011-05-27 21:13:15 +00:00
parent 6768f3f5a9
commit 0642328271

View File

@ -7053,6 +7053,10 @@ begin
end; end;
function TCodeCompletionCodeTool.CreateMissingProcBodies: boolean; function TCodeCompletionCodeTool.CreateMissingProcBodies: boolean;
const
ProcAttrDefToBody = [phpWithStart,
phpAddClassname,phpWithVarModifiers,
phpWithParameterNames,phpWithResultType,phpWithCallingSpecs];
var var
TheClassName: string; TheClassName: string;
@ -7096,9 +7100,7 @@ var
if (TheNodeExt.ExtTxt1='') and (TheNodeExt.ExtTxt3='') then begin if (TheNodeExt.ExtTxt1='') and (TheNodeExt.ExtTxt3='') then begin
ANode:=TheNodeExt.Node; ANode:=TheNodeExt.Node;
if (ANode<>nil) and (ANode.Desc=ctnProcedure) then begin if (ANode<>nil) and (ANode.Desc=ctnProcedure) then begin
ProcCode:=ExtractProcHead(ANode,[phpWithStart, ProcCode:=ExtractProcHead(ANode,ProcAttrDefToBody);
phpAddClassname,phpWithVarModifiers,
phpWithParameterNames,phpWithResultType,phpWithCallingSpecs]);
TheNodeExt.ExtTxt3:=ASourceChangeCache.BeautifyCodeOptions.BeautifyProc( TheNodeExt.ExtTxt3:=ASourceChangeCache.BeautifyCodeOptions.BeautifyProc(
ProcCode,Indent,true); ProcCode,Indent,true);
end; end;
@ -7177,12 +7179,21 @@ var
end; end;
end; end;
procedure AddNodeExtToTree(var TreeOfNodeExt: TAVLTree;
DefNodeExt: TCodeTreeNodeExtension);
begin
if TreeOfNodeExt=nil then
TreeOfNodeExt:=TAVLTree.Create(@CompareCodeTreeNodeExt);
TreeOfNodeExt.Add(DefNodeExt);
end;
function CheckForChangedProcs(out ProcsCopied: boolean): boolean; function CheckForChangedProcs(out ProcsCopied: boolean): boolean;
var var
BodyAVLNode: TAVLTreeNode; BodyAVLNode: TAVLTreeNode;
BodyNodeExt: TCodeTreeNodeExtension; BodyNodeExt: TCodeTreeNodeExtension;
BodiesWithoutDefs: TAVLTree; BodiesWithoutDefs: TAVLTree;
DefsWithoutBodies: TAVLTree; DefsWithoutBodies: TAVLTree;
UpdateDefsToBodies: TAVLTree;
DefAVLNode: TAVLTreeNode; DefAVLNode: TAVLTreeNode;
DefNodeExt: TCodeTreeNodeExtension; DefNodeExt: TCodeTreeNodeExtension;
InsertPos: LongInt; InsertPos: LongInt;
@ -7190,6 +7201,7 @@ var
BodyProcHeadNode: TCodeTreeNode; BodyProcHeadNode: TCodeTreeNode;
InsertEndPos: LongInt; InsertEndPos: LongInt;
ProcCode: String; ProcCode: String;
NewProcCode: String;
begin begin
Result:=true; Result:=true;
ProcsCopied:=false; ProcsCopied:=false;
@ -7197,51 +7209,77 @@ var
BodiesWithoutDefs:=nil; BodiesWithoutDefs:=nil;
DefsWithoutBodies:=nil; DefsWithoutBodies:=nil;
UpdateDefsToBodies:=nil;
try try
// collect all bodies without a definition // collect all bodies without a definition
BodyAVLNode:=ProcBodyNodes.FindLowest; BodyAVLNode:=ProcBodyNodes.FindLowest;
while BodyAVLNode<>nil do begin while BodyAVLNode<>nil do begin
BodyNodeExt:=TCodeTreeNodeExtension(BodyAVLNode.Data); BodyNodeExt:=TCodeTreeNodeExtension(BodyAVLNode.Data);
if ClassProcs.Find(BodyNodeExt)=nil then begin if ClassProcs.Find(BodyNodeExt)=nil then begin
if BodiesWithoutDefs=nil then AddNodeExtToTree(BodiesWithoutDefs,BodyNodeExt);
BodiesWithoutDefs:=TAVLTree.Create(@CompareCodeTreeNodeExt);
BodiesWithoutDefs.Add(BodyNodeExt);
end; end;
BodyAVLNode:=ProcBodyNodes.FindSuccessor(BodyAVLNode); BodyAVLNode:=ProcBodyNodes.FindSuccessor(BodyAVLNode);
end; end;
if BodiesWithoutDefs=nil then exit;
// collect all definitions without a body // collect all definitions without a body
DefAVLNode:=ClassProcs.FindLowest; DefAVLNode:=ClassProcs.FindLowest;
while DefAVLNode<>nil do begin while DefAVLNode<>nil do begin
DefNodeExt:=TCodeTreeNodeExtension(DefAVLNode.Data); DefNodeExt:=TCodeTreeNodeExtension(DefAVLNode.Data);
DefAVLNode:=ClassProcs.FindSuccessor(DefAVLNode);
if (ProcBodyNodes.Find(DefNodeExt)=nil) if (ProcBodyNodes.Find(DefNodeExt)=nil)
and (not ProcNodeHasSpecifier(DefNodeExt.Node,psABSTRACT)) then begin and (not ProcNodeHasSpecifier(DefNodeExt.Node,psABSTRACT)) then begin
// move proc definition from ClassProcs to DefsWithoutBodies // this proc def has no body
if DefsWithoutBodies=nil then AddNodeExtToTree(DefsWithoutBodies,DefNodeExt);
DefsWithoutBodies:=TAVLTree.Create(@CompareCodeTreeNodeExt);
DefsWithoutBodies.Add(DefNodeExt);
end; end;
DefAVLNode:=ClassProcs.FindSuccessor(DefAVLNode);
end; end;
if DefsWithoutBodies=nil then exit; if (DefsWithoutBodies<>nil) and (BodiesWithoutDefs<>nil)
if BodiesWithoutDefs.Count<>DefsWithoutBodies.Count then exit; and (BodiesWithoutDefs.Count=DefsWithoutBodies.Count) then begin
// there is the same amount of bodies without a def and defs without bodies // there is the same amount of bodies without a def and defs without bodies
// => try to create a mapping from defs to bodies // => try to create a mapping from defs to bodies
if DefsWithoutBodies.Count=1 then begin if DefsWithoutBodies.Count=1 then begin
// only one method def changed // only one method def changed
BodyNodeExt:=TCodeTreeNodeExtension(BodiesWithoutDefs.FindLowest.Data); BodyNodeExt:=TCodeTreeNodeExtension(BodiesWithoutDefs.FindLowest.Data);
DefNodeExt:=TCodeTreeNodeExtension(DefsWithoutBodies.FindLowest.Data); DefNodeExt:=TCodeTreeNodeExtension(DefsWithoutBodies.FindLowest.Data);
DefNodeExt.Data:=BodyNodeExt; DefNodeExt.Data:=BodyNodeExt;
end else begin AddNodeExtToTree(UpdateDefsToBodies,DefNodeExt);
// no mapping found end else begin
debugln(CleanPosToStr(ANode.FirstChild.StartPos)+' warning: procedure has no definition in the class'); // no mapping found
exit; debugln(CleanPosToStr(ANode.FirstChild.StartPos)+' warning: procedure has no definition in the class');
exit;
end;
end else if (DefsWithoutBodies=nil) and (BodiesWithoutDefs=nil) then begin
// all defs match 1:1 to bodies
// check if secondary attributes (proc type, param names) need update
DefAVLNode:=ClassProcs.FindLowest;
while DefAVLNode<>nil do begin
DefNodeExt:=TCodeTreeNodeExtension(DefAVLNode.Data);
if (DefNodeExt.Data=nil)
and (not ProcNodeHasSpecifier(DefNodeExt.Node,psABSTRACT)) then begin
BodyAVLNode:=ProcBodyNodes.Find(DefNodeExt);
if (BodyAVLNode<>nil) then begin
BodyNodeExt:=TCodeTreeNodeExtension(BodyAVLNode.Data);
NewProcCode:=ExtractProcHead(DefNodeExt.Node,ProcAttrDefToBody);
ProcCode:=ExtractProcHead(BodyNodeExt.Node,ProcAttrDefToBody);
//debugln(['CheckForChangedProcs Def="',NewProcCode,'"']);
//debugln(['CheckForChangedProcs Body="',ProcCode,'"']);
if CompareTextIgnoringSpace(ProcCode,NewProcCode,true)<>0 then
begin
{$IFDEF CTDEBUG}
debugln(['CheckForChangedProcs Update Def="',NewProcCode,'"']);
{$ENDIF}
DefNodeExt.Data:=BodyNodeExt;
BodyNodeExt.Data:=DefNodeExt;
AddNodeExtToTree(UpdateDefsToBodies,DefNodeExt);
end;
end;
end;
DefAVLNode:=ClassProcs.FindSuccessor(DefAVLNode);
end;
end; end;
// replace body proc head(s) with class proc head(s) // replace body proc head(s) with class proc head(s)
DefAVLNode:=DefsWithoutBodies.FindLowest; DefAVLNode:=UpdateDefsToBodies.FindLowest;
while DefAVLNode<>nil do begin while DefAVLNode<>nil do begin
DefNodeExt:=TCodeTreeNodeExtension(DefAVLNode.Data); DefNodeExt:=TCodeTreeNodeExtension(DefAVLNode.Data);
BodyNodeExt:=TCodeTreeNodeExtension(DefNodeExt.Data); BodyNodeExt:=TCodeTreeNodeExtension(DefNodeExt.Data);
@ -7250,9 +7288,7 @@ var
InsertPos:=BodyNodeExt.Node.StartPos; InsertPos:=BodyNodeExt.Node.StartPos;
InsertEndPos:=BodyProcHeadNode.EndPos; InsertEndPos:=BodyProcHeadNode.EndPos;
Indent:=GetLineIndent(Src,InsertPos); Indent:=GetLineIndent(Src,InsertPos);
ProcCode:=ExtractProcHead(DefNodeExt.Node,[phpWithStart, ProcCode:=ExtractProcHead(DefNodeExt.Node,ProcAttrDefToBody);
phpAddClassname,phpWithVarModifiers,
phpWithParameterNames,phpWithResultType,phpWithCallingSpecs]);
ProcCode:=ASourceChangeCache.BeautifyCodeOptions.BeautifyProc( ProcCode:=ASourceChangeCache.BeautifyCodeOptions.BeautifyProc(
ProcCode,Indent,false); ProcCode,Indent,false);
{$IFDEF CTDEBUG} {$IFDEF CTDEBUG}
@ -7261,9 +7297,10 @@ var
ProcsCopied:=true; ProcsCopied:=true;
if not ASourceChangeCache.Replace(gtNone,gtNone,InsertPos,InsertEndPos,ProcCode) then if not ASourceChangeCache.Replace(gtNone,gtNone,InsertPos,InsertEndPos,ProcCode) then
exit(false); exit(false);
DefAVLNode:=DefsWithoutBodies.FindSuccessor(DefAVLNode); DefAVLNode:=UpdateDefsToBodies.FindSuccessor(DefAVLNode);
end; end;
finally finally
UpdateDefsToBodies.Free;
BodiesWithoutDefs.Free; BodiesWithoutDefs.Free;
DefsWithoutBodies.Free; DefsWithoutBodies.Free;
end; end;