mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-05 07:58:16 +02:00
MG: code completion: added local variable completion
git-svn-id: trunk@3503 -
This commit is contained in:
parent
f64fd91acf
commit
23a85fff62
@ -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;
|
||||
|
@ -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".'
|
||||
|
@ -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;
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user