codetools: fix code completion after assignment in class methods. Issue #29448

git-svn-id: trunk@51392 -
This commit is contained in:
ondrej 2016-01-23 18:42:51 +00:00
parent c6d56cf204
commit 0b41165f50

View File

@ -9256,13 +9256,14 @@ function TCodeCompletionCodeTool.CompleteCode(CursorPos: TCodeXYPosition;
end; end;
function TryFirstLocalIdentOccurence(CursorNode: TCodeTreeNode; function TryFirstLocalIdentOccurence(CursorNode: TCodeTreeNode;
CleanCursorPos: Integer): boolean; OrigCleanCursorPos, CleanCursorPos: Integer): boolean;
var var
AtomContextNode, StatementNode: TCodeTreeNode; AtomContextNode, StatementNode: TCodeTreeNode;
IdentAtom, LastCurPos: TAtomPosition; IdentAtom, LastCurPos: TAtomPosition;
UpIdentifier: string; UpIdentifier: string;
LastAtomIsDot: Boolean; LastAtomIsDot: Boolean;
Params: TFindDeclarationParams; Params: TFindDeclarationParams;
OldCodePos: TCodePosition;
begin begin
Result := false; Result := false;
@ -9312,7 +9313,10 @@ function TCodeCompletionCodeTool.CompleteCode(CursorPos: TCodeXYPosition;
begin begin
FCompletingCursorNode:=CursorNode; FCompletingCursorNode:=CursorNode;
try try
if not CleanPosToCodePos(OrigCleanCursorPos,OldCodePos) then
RaiseException('TCodeCompletionCodeTool.TryFirstLocalIdentOccurence CleanPosToCodePos');
CompleteCode:=TryCompleteLocalVar(LastCurPos.StartPos,AtomContextNode); CompleteCode:=TryCompleteLocalVar(LastCurPos.StartPos,AtomContextNode);
AdjustCursor(OldCodePos,OldTopLine,NewPos,NewTopLine);
exit(true); exit(true);
finally finally
FCompletingCursorNode:=nil; FCompletingCursorNode:=nil;
@ -9337,7 +9341,10 @@ function TCodeCompletionCodeTool.CompleteCode(CursorPos: TCodeXYPosition;
RaiseExceptionInstance(TempE); RaiseExceptionInstance(TempE);
end; end;
function TryAssignment(CleanCursorPos: Integer; CursorNode: TCodeTreeNode): Boolean; function TryAssignment(CursorNode: TCodeTreeNode;
OrigCleanCursorPos, CleanCursorPos: Integer): Boolean;
var
OldCodePos: TCodePosition;
begin begin
// Search only within the current instruction - stop on semicolon or else // Search only within the current instruction - stop on semicolon or else
// (else isn't prepended by a semicolon in contrast to other keywords). // (else isn't prepended by a semicolon in contrast to other keywords).
@ -9352,9 +9359,19 @@ function TCodeCompletionCodeTool.CompleteCode(CursorPos: TCodeXYPosition;
begin begin
// OK FOUND! // OK FOUND!
ReadPriorAtom; ReadPriorAtom;
if TryComplete(CursorNode, CurPos.StartPos) then FCompletingCursorNode:=CursorNode;
exit(true); try
break; if TryComplete(CursorNode, CurPos.StartPos) then
begin
if not CleanPosToCodePos(OrigCleanCursorPos,OldCodePos) then
RaiseException('TCodeCompletionCodeTool.CompleteCode CleanPosToCodePos');
AdjustCursor(OldCodePos,OldTopLine,NewPos,NewTopLine);
exit(true);
end;
break;
finally
FCompletingCursorNode:=nil;
end;
end; end;
cafWord: cafWord:
if UpAtomIs('ELSE') then // stop on else if UpAtomIs('ELSE') then // stop on else
@ -9368,7 +9385,6 @@ function TCodeCompletionCodeTool.CompleteCode(CursorPos: TCodeXYPosition;
var var
CleanCursorPos, OrigCleanCursorPos: integer; CleanCursorPos, OrigCleanCursorPos: integer;
CursorNode: TCodeTreeNode; CursorNode: TCodeTreeNode;
OldCodePos: TCodePosition;
LastCodeToolsErrorCleanPos: Integer; LastCodeToolsErrorCleanPos: Integer;
LastCodeToolsError: ECodeToolError; LastCodeToolsError: ECodeToolError;
begin begin
@ -9401,20 +9417,15 @@ begin
CodeCompleteSrcChgCache:=SourceChangeCache; CodeCompleteSrcChgCache:=SourceChangeCache;
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true); CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true);
LastCodeToolsError := nil;
try try
LastCodeToolsError := nil;
try try
if TryComplete(CursorNode, CleanCursorPos) then if TryComplete(CursorNode, CleanCursorPos) then
exit(true); exit(true);
{ Find the first occurence of the (local) identifier at cursor in current { Find the first occurence of the (local) identifier at cursor in current
procedure body and try again. } procedure body and try again. }
if TryFirstLocalIdentOccurence(CursorNode,CleanCursorPos) then if TryFirstLocalIdentOccurence(CursorNode,OrigCleanCursorPos,CleanCursorPos) then
exit(true);
if CompleteMethodByBody(OrigCleanCursorPos,OldTopLine,CursorNode,
NewPos,NewTopLine,SourceChangeCache)
then
exit(true); exit(true);
except except
on E: ECodeToolError do on E: ECodeToolError do
@ -9427,21 +9438,20 @@ begin
end; end;
// find first assignment before current. // find first assignment before current.
if TryAssignment(CleanCursorPos, CursorNode) then if TryAssignment(CursorNode, OrigCleanCursorPos, CleanCursorPos) then
Exit(true); Exit(true);
if LastCodeToolsError<>nil then // no assignment found, reraise if LastCodeToolsError<>nil then // no assignment found, reraise
ClearAndRaise(LastCodeToolsError, LastCodeToolsErrorCleanPos); ClearAndRaise(LastCodeToolsError, LastCodeToolsErrorCleanPos);
finally finally
LastCodeToolsError.Free; LastCodeToolsError.Free;
if Result then
begin
if not CleanPosToCodePos(OrigCleanCursorPos,OldCodePos) then
RaiseException('TCodeCompletionCodeTool.CompleteCode CleanPosToCodePos');
AdjustCursor(OldCodePos,OldTopLine,NewPos,NewTopLine);
end;
end; end;
if CompleteMethodByBody(OrigCleanCursorPos,OldTopLine,CursorNode,
NewPos,NewTopLine,SourceChangeCache)
then
exit(true);
{$IFDEF CTDEBUG} {$IFDEF CTDEBUG}
DebugLn('TCodeCompletionCodeTool.CompleteCode nothing to complete ... '); DebugLn('TCodeCompletionCodeTool.CompleteCode nothing to complete ... ');
{$ENDIF} {$ENDIF}