MG: code completion: added local variable completion

git-svn-id: trunk@3503 -
This commit is contained in:
lazarus 2002-10-13 21:23:45 +00:00
parent f64fd91acf
commit 23a85fff62
6 changed files with 162 additions and 4 deletions

View File

@ -229,7 +229,7 @@ type
NewMethodName: string; ATypeInfo: PTypeInfo): boolean;
// code completion = auto class completion, auto forward proc completion
function CompleteCode(Code: TCodeBuffer; X,Y: integer;
function CompleteCode(Code: TCodeBuffer; X,Y,TopLine: integer;
var NewCode: TCodeBuffer;
var NewX, NewY, NewTopLine: integer): boolean;
@ -946,7 +946,7 @@ begin
end;
end;
function TCodeToolManager.CompleteCode(Code: TCodeBuffer; X,Y: integer;
function TCodeToolManager.CompleteCode(Code: TCodeBuffer; X,Y,TopLine: integer;
var NewCode: TCodeBuffer; var NewX, NewY, NewTopLine: integer): boolean;
var
CursorPos: TCodeXYPosition;
@ -961,7 +961,8 @@ begin
CursorPos.Y:=Y;
CursorPos.Code:=Code;
try
Result:=FCurCodeTool.CompleteCode(CursorPos,NewPos,NewTopLine,SourceChangeCache);
Result:=FCurCodeTool.CompleteCode(CursorPos,TopLine,
NewPos,NewTopLine,SourceChangeCache);
if Result then begin
NewX:=NewPos.X;
NewY:=NewPos.Y;

View File

@ -135,6 +135,8 @@ ResourceString
ctsEndOfSourceNotFound = 'End of source not found';
ctsCursorPosOutsideOfCode = 'cursor pos outside of code';
ctsNewProcBodyNotFound = 'new proc body not found';
ctsIdentifierAlreadyDefined = 'Identifier %s already defined';
ctsTermNotSimple = 'Term has no simple type';
// codetoolsmanager
ctsNoScannerFound = 'No scanner found for "%s".'

View File

@ -118,6 +118,8 @@ type
//-1=CursorPos was skipped, CleanPos between two links
// 1=CursorPos beyond scanned code
//-2=X,Y beyond source
function CleanPosToCodePos(CleanPos: integer;
var CodePos:TCodePosition): boolean; // true=ok, false=invalid CleanPos
function CleanPosToCaret(CleanPos: integer;
var Caret:TCodeXYPosition): boolean; // true=ok, false=invalid CleanPos
function CleanPosToCaretAndTopLine(CleanPos: integer;
@ -1724,6 +1726,15 @@ begin
//writeln('TCustomCodeTool.CaretToCleanPos C CleanPos=',CleanPos,' Result=',Result);
end;
function TCustomCodeTool.CleanPosToCodePos(CleanPos: integer;
var CodePos: TCodePosition): boolean;
var
ACode: pointer;
begin
Result:=Scanner.CleanedPosToCursor(CleanPos,CodePos.p,ACode);
CodePos.Code:=TCodeBuffer(ACode);
end;
function TCustomCodeTool.CleanPosToCaret(CleanPos: integer;
var Caret:TCodeXYPosition): boolean; // true=ok, false=invalid CleanPos
var p: integer;

View File

@ -241,7 +241,7 @@ type
TExpressionTypeDescs = set of TExpressionTypeDesc;
const
ExpressionTypeDescNames : array[TExpressionTypeDesc] of string = (
ExpressionTypeDescNames: array[TExpressionTypeDesc] of string = (
'None', 'Context', 'Char', 'Real', 'Single', 'Double',
'Extended', 'Currency', 'Comp', 'Int64', 'Cardinal', 'QWord', 'Boolean',
'ByteBool', 'LongBool', 'String', 'AnsiString', 'ShortString', 'WideString',
@ -464,6 +464,7 @@ type
function FindStartOfVariable(EndPos: integer): integer;
function FindExpressionTypeOfVariable(StartPos, EndPos: integer;
Params: TFindDeclarationParams): TExpressionType;
function FindEndOfExpression(StartPos: integer): integer;
function ConvertNodeToExpressionType(Node: TCodeTreeNode;
Params: TFindDeclarationParams): TExpressionType;
function ReadOperandTypeAtCursor(
@ -475,9 +476,13 @@ type
function GetFirstParameterNode(Node: TCodeTreeNode): TCodeTreeNode;
function GetExpressionTypeOfTypeIdentifier(
Params: TFindDeclarationParams): TExpressionType;
function FindTermTypeAsString(TermAtom: TAtomPosition;
CursorNode: TCodeTreeNode; Params: TFindDeclarationParams): string;
protected
function FindDeclarationOfIdentAtCursor(
Params: TFindDeclarationParams): boolean;
function IdentifierIsDefined(IdentAtom: TAtomPosition;
ContextNode: TCodeTreeNode; Params: TFindDeclarationParams): boolean;
function FindContextNodeAtCursor(
Params: TFindDeclarationParams): TFindContext;
function FindIdentifierInContext(Params: TFindDeclarationParams): boolean;
@ -1182,6 +1187,18 @@ begin
Result:=true;
end;
function TFindDeclarationTool.IdentifierIsDefined(IdentAtom: TAtomPosition;
ContextNode: TCodeTreeNode; Params: TFindDeclarationParams): boolean;
begin
// find declaration of identifier
Params.ContextNode:=ContextNode;
Params.SetIdentifier(Self,@Src[IdentAtom.StartPos],nil);
Params.Flags:=[fdfSearchInParentNodes,fdfSearchInAncestors,
fdfTopLvlResolving,fdfFindVariable,fdfIgnoreCurContextNode]
+fdfAllClassVisibilities;
Result:=FindIdentifierInContext(Params);
end;
function TFindDeclarationTool.FindIdentifierInContext(
Params: TFindDeclarationParams): boolean;
{ searches an identifier in context node
@ -3746,6 +3763,28 @@ begin
{$ENDIF}
end;
function TFindDeclarationTool.FindEndOfExpression(StartPos: integer): integer;
begin
MoveCursorToCleanPos(StartPos);
Result:=CurPos.StartPos;
repeat
ReadNextAtom;
// read till statement end
if (CurPos.Flag in [cafSemicolon,cafComma,cafEnd,cafNone,
cafRoundBracketClose,cafEdgedBracketClose])
or (AtomIsKeyWord
and not IsKeyWordInConstAllowed.DoItUpperCase(UpperSrc,
CurPos.StartPos,CurPos.EndPos-CurPos.StartPos))
then begin
break;
end
else if CurPos.Flag in [cafRoundBracketOpen,cafEdgedBracketOpen] then begin
ReadTilBracketClose(true);
end;
Result:=CurPos.EndPos;
until false;
end;
function TFindDeclarationTool.ConvertNodeToExpressionType(Node: TCodeTreeNode;
Params: TFindDeclarationParams): TExpressionType;
@ -5116,6 +5155,107 @@ begin
end;
end;
function TFindDeclarationTool.FindTermTypeAsString(TermAtom: TAtomPosition;
CursorNode: TCodeTreeNode; Params: TFindDeclarationParams): string;
procedure RaiseTermNotSimple;
begin
MoveCursorToCleanPos(TermAtom.StartPos);
RaiseException(ctsTermNotSimple);
end;
var
ExprType: TExpressionType;
FindContext: TFindContext;
ANode: TCodeTreeNode;
begin
Result:='';
Params.ContextNode:=CursorNode;
Params.Flags:=[fdfSearchInParentNodes,fdfSearchInAncestors,
fdfTopLvlResolving,fdfFindVariable]
+fdfAllClassVisibilities;
ExprType:=FindExpressionResultType(Params,TermAtom.StartPos,TermAtom.EndPos);
{$IFDEF CTDEBUG}
writeln('TCodeCompletionCodeTool.FindTermTypeAsString ExprTypeToString=',
ExprTypeToString(ExprType));
{$ENDIF}
case ExprType.Desc of
xtNone:
RaiseTermNotSimple;
xtContext:
begin
FindContext:=ExprType.Context;
// ToDo: PPU, PPW, DCU
case FindContext.Node.Desc of
ctnTypeDefinition:
Result:=GetIdentifier(
@FindContext.Tool.Src[FindContext.Node.StartPos]);
ctnVarDefinition,ctnConstDefinition:
begin
ANode:=FindContext.Tool.FindTypeNodeOfDefinition(FindContext.Node);
if (ANode=nil) or (ANode.Desc<>ctnIdentifier) then
RaiseTermNotSimple;
Result:=GetIdentifier(@FindContext.Tool.Src[ANode.StartPos]);
end;
else
RaiseTermNotSimple;
end;
end;
xtChar,
xtReal,
xtSingle,
xtDouble,
xtExtended,
xtCurrency,
xtComp,
xtInt64,
xtCardinal,
xtQWord,
xtPChar,
xtPointer,
xtFile,
xtText,
xtLongint,
xtWord:
Result:=ExpressionTypeDescNames[ExprType.Desc];
xtBoolean,
xtByteBool,
xtLongBool:
Result:=ExpressionTypeDescNames[xtBoolean];
xtString,
xtAnsiString,
xtShortString:
Result:=ExpressionTypeDescNames[xtString];
xtWideString:
Result:=ExpressionTypeDescNames[ExprType.Desc];
xtConstOrdInteger:
Result:='Integer';
xtConstString:
Result:=ExpressionTypeDescNames[xtString];
xtConstReal:
Result:=ExpressionTypeDescNames[xtExtended];
xtConstSet:
RaiseTermNotSimple;
xtConstBoolean:
Result:=ExpressionTypeDescNames[xtBoolean];
xtNil:
RaiseTermNotSimple;
else
RaiseTermNotSimple;
end;
end;
{ TFindDeclarationParams }

View File

@ -610,6 +610,7 @@ begin
Add('LOW',{$ifdef FPC}@{$endif}AllwaysTrue);
Add('HIGH',{$ifdef FPC}@{$endif}AllwaysTrue);
Add('ORD',{$ifdef FPC}@{$endif}AllwaysTrue);
Add('AS',{$ifdef FPC}@{$endif}AllwaysTrue);
end;
WordIsKeyWord:=TKeyWordFunctionList.Create;
KeyWordLists.Add(WordIsKeyWord);

View File

@ -2233,6 +2233,9 @@ function TPascalParserTool.KeyWordFuncBeginEnd: boolean;
var
ChildNodeCreated: boolean;
begin
if (CurNode<>nil)
and (not (CurNode.Desc in [ctnProcedure,ctnProgram,ctnImplementation])) then
RaiseStringExpectedButAtomFound('end');
ChildNodeCreated:=(CurPos.Flag=cafBEGIN) or UpAtomIs('ASM');
if ChildNodeCreated then begin
CreateChildNode;