codetools: code completion: implemented adding methog declaration for method body at cursor

git-svn-id: trunk@10386 -
This commit is contained in:
mattias 2007-01-06 13:00:36 +00:00
parent 8c34006c95
commit 735b70957a
4 changed files with 102 additions and 38 deletions

View File

@ -172,6 +172,10 @@ type
OldTopLine: integer; CursorNode: TCodeTreeNode; OldTopLine: integer; CursorNode: TCodeTreeNode;
var NewPos: TCodeXYPosition; var NewTopLine: integer; var NewPos: TCodeXYPosition; var NewTopLine: integer;
SourceChangeCache: TSourceChangeCache): boolean; SourceChangeCache: TSourceChangeCache): boolean;
function CompleteMethod(CleanCursorPos, OldTopLine: integer;
CursorNode: TCodeTreeNode;
var NewPos: TCodeXYPosition; var NewTopLine: integer;
SourceChangeCache: TSourceChangeCache): boolean;
protected protected
property CodeCompleteClassNode: TCodeTreeNode property CodeCompleteClassNode: TCodeTreeNode
read FCodeCompleteClassNode write SetCodeCompleteClassNode; read FCodeCompleteClassNode write SetCodeCompleteClassNode;
@ -325,7 +329,7 @@ procedure TCodeCompletionCodeTool.AddClassInsertion(
var NewInsert, InsertPos, LastInsertPos: TCodeTreeNodeExtension; var NewInsert, InsertPos, LastInsertPos: TCodeTreeNodeExtension;
begin begin
{$IFDEF CTDEBUG} {$IFDEF CTDEBUG}
DebugLn('[TCodeCompletionCodeTool.AddClassInsertion] ',CleanDef,',',Def,',',Identifiername); DebugLn('[TCodeCompletionCodeTool.AddClassInsertion] CleanDef="',CleanDef,'" Def="',Def,'" Identifiername="',Identifiername,'" Body="',Body,'"');
{$ENDIF} {$ENDIF}
NewInsert:=NodeExtMemManager.NewNode; NewInsert:=NodeExtMemManager.NewNode;
with NewInsert do begin with NewInsert do begin
@ -991,6 +995,72 @@ begin
NewType,NewPos,NewTopLine,SourceChangeCache); NewType,NewPos,NewTopLine,SourceChangeCache);
end; end;
function TCodeCompletionCodeTool.CompleteMethod(
CleanCursorPos, OldTopLine: integer;
CursorNode: TCodeTreeNode;
var NewPos: TCodeXYPosition; var NewTopLine: integer;
SourceChangeCache: TSourceChangeCache): boolean;
var
CurClassName: String;
ProcNode: TCodeTreeNode;
CleanProcCode: String;
ProcCode: String;
ProcName: String;
OldCodePos: TCodePosition;
begin
Result:=false;
// check if cursor in a method
ProcNode:=CursorNode.GetNodeOfType(ctnProcedure);
if (ProcNode=nil) and (CursorNode.Desc=ctnProcedure) then
ProcNode:=CursorNode;
if (ProcNode=nil) or (ProcNode.Desc<>ctnProcedure)
or ((ProcNode.SubDesc and ctnsForwardDeclaration)<>0)
or (not NodeIsMethodBody(ProcNode)) then begin
exit;
end;
// find corresponding class declaration
CurClassName:=ExtractClassNameOfProcNode(ProcNode);
if CurClassName='' then begin
DebugLn(['CompleteMethod ExtractClassNameOfProcNode failed']);
exit;
end;
//DebugLn(['CompleteMethod CurClassName=',CurClassName]);
CodeCompleteClassNode:=FindClassNodeInUnit(CurClassName,true,false,false,true);
// check if method declaration already exists
ProcName:=ExtractProcName(ProcNode,[phpWithoutClassName]);
CleanProcCode:=ExtractProcHead(ProcNode,
[phpWithoutClassKeyword,phpWithoutClassName,phpInUpperCase]);
if ProcExistsInCodeCompleteClass(CleanProcCode) then begin
// proc exists already
MoveCursorToCleanPos(CleanCursorPos);
RaiseExceptionFmt(ctsIdentifierAlreadyDefined,[ProcName]);
end;
// store old cursor position
if not CleanPosToCodePos(CleanCursorPos,OldCodePos) then begin
RaiseException('TCodeCompletionCodeTool.AddLocalVariable Internal Error: '
+'CleanPosToCodePos');
end;
CodeCompleteSrcChgCache:=SourceChangeCache;
// add method declaration
ProcCode:=ExtractProcHead(ProcNode,
[phpWithStart,phpWithoutClassName,phpWithVarModifiers,phpWithParameterNames,
phpWithDefaultValues,phpWithResultType,phpWithCallingSpecs]);
AddClassInsertion(CleanProcCode,ProcCode,ProcName,ncpPrivateProcs);
// apply changes
Result:=ApplyClassCompletion;
// adjust cursor position
AdjustCursor(OldCodePos,OldTopLine,NewPos,NewTopLine);
//DebugLn(['TCodeCompletionCodeTool.CompleteMethod END OldCodePos.P=',OldCodePos.P,' OldTopLine=',OldTopLine,' NewPos=',DbgsCXY(NewPos),' NewTopLine=',NewTopLine]);
end;
function TCodeCompletionCodeTool.AddPublishedVariable(const UpperClassName, function TCodeCompletionCodeTool.AddPublishedVariable(const UpperClassName,
VarName, VarType: string; SourceChangeCache: TSourceChangeCache): boolean; VarName, VarType: string; SourceChangeCache: TSourceChangeCache): boolean;
begin begin
@ -1004,7 +1074,7 @@ begin
CodeCompleteClassNode:=FindClassNodeInInterface(UpperClassName,true,false,true); CodeCompleteClassNode:=FindClassNodeInInterface(UpperClassName,true,false,true);
CodeCompleteSrcChgCache:=SourceChangeCache; CodeCompleteSrcChgCache:=SourceChangeCache;
// check if variable already exists // check if variable already exists
if VarExistsInCodeCompleteClass(UpperCaseStr(VarName)) then begin if not VarExistsInCodeCompleteClass(UpperCaseStr(VarName)) then begin
end else begin end else begin
AddClassInsertion(UpperCaseStr(VarName), AddClassInsertion(UpperCaseStr(VarName),
@ -1028,7 +1098,7 @@ begin
BuildTree(false); BuildTree(false);
if not EndOfSourceFound then exit; if not EndOfSourceFound then exit;
if (SourceChangeCache=nil) or (Scanner=nil) then exit; if (SourceChangeCache=nil) or (Scanner=nil) then exit;
ClassNode:=FindClassNodeInInterface(UpperClassName,true,false,true); ClassNode:=FindClassNodeInUnit(UpperClassName,true,false,false,true);
if (ClassNode=nil) then exit; if (ClassNode=nil) then exit;
CodeCompleteClassNode:=ClassNode; CodeCompleteClassNode:=ClassNode;
CodeCompleteSrcChgCache:=SourceChangeCache; CodeCompleteSrcChgCache:=SourceChangeCache;
@ -2554,7 +2624,7 @@ function TCodeCompletionCodeTool.CompleteCode(CursorPos: TCodeXYPosition;
var CleanCursorPos, Indent, insertPos: integer; var CleanCursorPos, Indent, insertPos: integer;
CursorNode, ProcNode, ImplementationNode, SectionNode, AClassNode, CursorNode, ProcNode, ImplementationNode, SectionNode, AClassNode,
ANode: TCodeTreeNode; ANode: TCodeTreeNode;
ProcCode: string; OldCleanCursorPos: LongInt;
procedure CompleteClass; procedure CompleteClass;
var var
@ -2663,11 +2733,6 @@ var CleanCursorPos, Indent, insertPos: integer;
end; end;
end; end;
procedure CompleteMethod;
begin
// ToDo
end;
procedure CompleteForwardProcs; procedure CompleteForwardProcs;
// add proc bodies for forward procs // add proc bodies for forward procs
var var
@ -2676,6 +2741,7 @@ var CleanCursorPos, Indent, insertPos: integer;
StartProcNode: TCodeTreeNode; StartProcNode: TCodeTreeNode;
CurProcNode: TCodeTreeNode; CurProcNode: TCodeTreeNode;
EndProcNode: TCodeTreeNode; EndProcNode: TCodeTreeNode;
ProcCode: String;
begin begin
{$IFDEF CTDEBUG} {$IFDEF CTDEBUG}
DebugLn('TCodeCompletionCodeTool.CompleteCode in a forward procedure ... '); DebugLn('TCodeCompletionCodeTool.CompleteCode in a forward procedure ... ');
@ -3079,10 +3145,13 @@ var CleanCursorPos, Indent, insertPos: integer;
// var NewPos: TCodeXYPosition; var NewTopLine: integer; // var NewPos: TCodeXYPosition; var NewTopLine: integer;
// SourceChangeCache: TSourceChangeCache): boolean; // SourceChangeCache: TSourceChangeCache): boolean;
begin begin
//DebugLn(['TCodeCompletionCodeTool.CompleteCode CursorPos=',DbgsCXY(CursorPos),' OldTopLine=',OldTopLine]);
Result:=false; Result:=false;
if (SourceChangeCache=nil) then if (SourceChangeCache=nil) then
RaiseException('need a SourceChangeCache'); RaiseException('need a SourceChangeCache');
BuildTreeAndGetCleanPos(trAll,CursorPos, CleanCursorPos,[]); BuildTreeAndGetCleanPos(trAll,CursorPos, CleanCursorPos,[]);
OldCleanCursorPos:=CleanCursorPos;
NewPos:=CleanCodeXYPosition; NewPos:=CleanCodeXYPosition;
NewTopLine:=0; NewTopLine:=0;
@ -3136,25 +3205,19 @@ begin
if Result then exit; if Result then exit;
// test if Local variable assignment // test if Local variable assignment
Result:=CompleteLocalVariableAssignment(CleanCursorPos,OldTopLine,CursorNode, Result:=CompleteLocalVariableAssignment(CleanCursorPos,OldTopLine,
NewPos,NewTopLine,SourceChangeCache); CursorNode,NewPos,NewTopLine,SourceChangeCache);
if Result then exit; if Result then exit;
// test if undeclared local variable as parameter // test if undeclared local variable as parameter
Result:=CompleteLocalVariableAsParameter(CleanCursorPos,OldTopLine,CursorNode, Result:=CompleteLocalVariableAsParameter(CleanCursorPos,OldTopLine,
NewPos,NewTopLine,SourceChangeCache); CursorNode,NewPos,NewTopLine,SourceChangeCache);
if Result then exit; if Result then exit;
// test if method body // test if method body
ProcNode:=CursorNode.GetNodeOfType(ctnProcedure); Result:=CompleteMethod(OldCleanCursorPos,OldTopLine,CursorNode,
if (ProcNode=nil) and (CursorNode.Desc=ctnProcedure) then NewPos,NewTopLine,SourceChangeCache);
ProcNode:=CursorNode; if Result then exit;
if (ProcNode<>nil) and (ProcNode.Desc=ctnProcedure)
and ((ProcNode.SubDesc and ctnsForwardDeclaration)=0)
and NodeIsMethodBody(ProcNode) then begin
CompleteMethod;
exit;
end;
{$IFDEF CTDEBUG} {$IFDEF CTDEBUG}
DebugLn('TCodeCompletionCodeTool.CompleteCode nothing to complete ... '); DebugLn('TCodeCompletionCodeTool.CompleteCode nothing to complete ... ');

View File

@ -4466,29 +4466,25 @@ begin
Result:=FindIdentifierInContext(Params); Result:=FindIdentifierInContext(Params);
Params.Load(OldInput); Params.Load(OldInput);
if (Params.NewCodeTool<>Self) then Result:=false;
// save result in cache // save result in cache
if Params.Flags*[fdfCollect,fdfDoNotCache]=[] then begin if Params.Flags*[fdfCollect,fdfDoNotCache]=[] then begin
if FInterfaceIdentifierCache=nil then if FInterfaceIdentifierCache=nil then
FInterfaceIdentifierCache:=TInterfaceIdentifierCache.Create(Self); FInterfaceIdentifierCache:=TInterfaceIdentifierCache.Create(Self);
if Result and (Params.NewCodeTool=Self) then begin if Result then begin
// identifier exists in interface // identifier exists in interface
if ([fdfDoNotCache,fdfCollect]*Params.Flags=[]) if (Params.NewNode<>nil) and (Params.NewNode.Desc=ctnProcedure) then begin
and ([fodDoNotCache]*Params.NewFlags=[]) then begin //DebugLn('NOTE: TFindDeclarationTool.FindIdentifierInInterface Node is proc');
if (Params.NewNode<>nil) and (Params.NewNode.Desc=ctnProcedure) then begin // ToDo: add param list to cache
//DebugLn('NOTE: TFindDeclarationTool.FindIdentifierInInterface Node is proc'); // -> do not cache
// ToDo: add param list to cache
// -> do not cache
Result:=false;
end else
FInterfaceIdentifierCache.Add(OldInput.Identifier,Params.NewNode,
Params.NewCleanPos);
end else begin end else begin
// do not save proc identifiers or collection results FInterfaceIdentifierCache.Add(OldInput.Identifier,Params.NewNode,
Params.NewCleanPos);
end; end;
end else begin end else begin
// identifier does not exist in this interface // identifier does not exist in this interface
FInterfaceIdentifierCache.Add(OldInput.Identifier,nil,-1); FInterfaceIdentifierCache.Add(OldInput.Identifier,nil,-1);
Result:=false;
end; end;
end; end;
end; end;

View File

@ -3684,8 +3684,7 @@ begin
else else
ExtractMemStream.Write(Src[LastAtomEndPos], ExtractMemStream.Write(Src[LastAtomEndPos],
CurPos.StartPos-LastAtomEndPos); CurPos.StartPos-LastAtomEndPos);
end else if (CurPos.StartPos>LastAtomEndPos) end else if (ExtractMemStream.Position>0) then
and (ExtractMemStream.Position>0) then
begin begin
// some code was skipped // some code was skipped
// -> check if a space must be inserted // -> check if a space must be inserted

View File

@ -10530,6 +10530,12 @@ var
NewUnitInfo: TUnitInfo; NewUnitInfo: TUnitInfo;
begin begin
Result:=mrCancel; Result:=mrCancel;
if NewSource=nil then begin
DebugLn(['TMainIDE.DoJumpToCodePos ERROR: missing NewSource']);
DumpStack;
exit;
end;
if (ActiveSrcEdit=nil) or (ActiveUnitInfo=nil) then if (ActiveSrcEdit=nil) or (ActiveUnitInfo=nil) then
GetCurrentUnit(ActiveSrcEdit,ActiveUnitInfo); GetCurrentUnit(ActiveSrcEdit,ActiveUnitInfo);
if AddJumpPoint then begin if AddJumpPoint then begin
@ -10554,7 +10560,7 @@ begin
if NewY<1 then NewY:=1; if NewY<1 then NewY:=1;
if NewTopLine<1 then if NewTopLine<1 then
NewTopLine:=Max(1,NewY-(NewSrcEdit.EditorComponent.LinesInWindow div 2)); NewTopLine:=Max(1,NewY-(NewSrcEdit.EditorComponent.LinesInWindow div 2));
//writeln('[TMainIDE.DoJumpToCodePos] ',NewX,',',NewY,',',NewTopLine); //debugln(['[TMainIDE.DoJumpToCodePos] ',NewX,',',NewY,',',NewTopLine]);
with NewSrcEdit.EditorComponent do begin with NewSrcEdit.EditorComponent do begin
MoveLogicalCaretIgnoreEOL(Point(NewX,NewY)); MoveLogicalCaretIgnoreEOL(Point(NewX,NewY));
BlockBegin:=LogicalCaretXY; BlockBegin:=LogicalCaretXY;