mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-13 05:29:51 +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;
|
NewMethodName: string; ATypeInfo: PTypeInfo): boolean;
|
||||||
|
|
||||||
// code completion = auto class completion, auto forward proc completion
|
// 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 NewCode: TCodeBuffer;
|
||||||
var NewX, NewY, NewTopLine: integer): boolean;
|
var NewX, NewY, NewTopLine: integer): boolean;
|
||||||
|
|
||||||
@ -946,7 +946,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
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 NewCode: TCodeBuffer; var NewX, NewY, NewTopLine: integer): boolean;
|
||||||
var
|
var
|
||||||
CursorPos: TCodeXYPosition;
|
CursorPos: TCodeXYPosition;
|
||||||
@ -961,7 +961,8 @@ begin
|
|||||||
CursorPos.Y:=Y;
|
CursorPos.Y:=Y;
|
||||||
CursorPos.Code:=Code;
|
CursorPos.Code:=Code;
|
||||||
try
|
try
|
||||||
Result:=FCurCodeTool.CompleteCode(CursorPos,NewPos,NewTopLine,SourceChangeCache);
|
Result:=FCurCodeTool.CompleteCode(CursorPos,TopLine,
|
||||||
|
NewPos,NewTopLine,SourceChangeCache);
|
||||||
if Result then begin
|
if Result then begin
|
||||||
NewX:=NewPos.X;
|
NewX:=NewPos.X;
|
||||||
NewY:=NewPos.Y;
|
NewY:=NewPos.Y;
|
||||||
|
@ -135,6 +135,8 @@ ResourceString
|
|||||||
ctsEndOfSourceNotFound = 'End of source not found';
|
ctsEndOfSourceNotFound = 'End of source not found';
|
||||||
ctsCursorPosOutsideOfCode = 'cursor pos outside of code';
|
ctsCursorPosOutsideOfCode = 'cursor pos outside of code';
|
||||||
ctsNewProcBodyNotFound = 'new proc body not found';
|
ctsNewProcBodyNotFound = 'new proc body not found';
|
||||||
|
ctsIdentifierAlreadyDefined = 'Identifier %s already defined';
|
||||||
|
ctsTermNotSimple = 'Term has no simple type';
|
||||||
|
|
||||||
// codetoolsmanager
|
// codetoolsmanager
|
||||||
ctsNoScannerFound = 'No scanner found for "%s".'
|
ctsNoScannerFound = 'No scanner found for "%s".'
|
||||||
|
@ -118,6 +118,8 @@ type
|
|||||||
//-1=CursorPos was skipped, CleanPos between two links
|
//-1=CursorPos was skipped, CleanPos between two links
|
||||||
// 1=CursorPos beyond scanned code
|
// 1=CursorPos beyond scanned code
|
||||||
//-2=X,Y beyond source
|
//-2=X,Y beyond source
|
||||||
|
function CleanPosToCodePos(CleanPos: integer;
|
||||||
|
var CodePos:TCodePosition): boolean; // true=ok, false=invalid CleanPos
|
||||||
function CleanPosToCaret(CleanPos: integer;
|
function CleanPosToCaret(CleanPos: integer;
|
||||||
var Caret:TCodeXYPosition): boolean; // true=ok, false=invalid CleanPos
|
var Caret:TCodeXYPosition): boolean; // true=ok, false=invalid CleanPos
|
||||||
function CleanPosToCaretAndTopLine(CleanPos: integer;
|
function CleanPosToCaretAndTopLine(CleanPos: integer;
|
||||||
@ -1724,6 +1726,15 @@ begin
|
|||||||
//writeln('TCustomCodeTool.CaretToCleanPos C CleanPos=',CleanPos,' Result=',Result);
|
//writeln('TCustomCodeTool.CaretToCleanPos C CleanPos=',CleanPos,' Result=',Result);
|
||||||
end;
|
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;
|
function TCustomCodeTool.CleanPosToCaret(CleanPos: integer;
|
||||||
var Caret:TCodeXYPosition): boolean; // true=ok, false=invalid CleanPos
|
var Caret:TCodeXYPosition): boolean; // true=ok, false=invalid CleanPos
|
||||||
var p: integer;
|
var p: integer;
|
||||||
|
@ -241,7 +241,7 @@ type
|
|||||||
TExpressionTypeDescs = set of TExpressionTypeDesc;
|
TExpressionTypeDescs = set of TExpressionTypeDesc;
|
||||||
|
|
||||||
const
|
const
|
||||||
ExpressionTypeDescNames : array[TExpressionTypeDesc] of string = (
|
ExpressionTypeDescNames: array[TExpressionTypeDesc] of string = (
|
||||||
'None', 'Context', 'Char', 'Real', 'Single', 'Double',
|
'None', 'Context', 'Char', 'Real', 'Single', 'Double',
|
||||||
'Extended', 'Currency', 'Comp', 'Int64', 'Cardinal', 'QWord', 'Boolean',
|
'Extended', 'Currency', 'Comp', 'Int64', 'Cardinal', 'QWord', 'Boolean',
|
||||||
'ByteBool', 'LongBool', 'String', 'AnsiString', 'ShortString', 'WideString',
|
'ByteBool', 'LongBool', 'String', 'AnsiString', 'ShortString', 'WideString',
|
||||||
@ -464,6 +464,7 @@ type
|
|||||||
function FindStartOfVariable(EndPos: integer): integer;
|
function FindStartOfVariable(EndPos: integer): integer;
|
||||||
function FindExpressionTypeOfVariable(StartPos, EndPos: integer;
|
function FindExpressionTypeOfVariable(StartPos, EndPos: integer;
|
||||||
Params: TFindDeclarationParams): TExpressionType;
|
Params: TFindDeclarationParams): TExpressionType;
|
||||||
|
function FindEndOfExpression(StartPos: integer): integer;
|
||||||
function ConvertNodeToExpressionType(Node: TCodeTreeNode;
|
function ConvertNodeToExpressionType(Node: TCodeTreeNode;
|
||||||
Params: TFindDeclarationParams): TExpressionType;
|
Params: TFindDeclarationParams): TExpressionType;
|
||||||
function ReadOperandTypeAtCursor(
|
function ReadOperandTypeAtCursor(
|
||||||
@ -475,9 +476,13 @@ type
|
|||||||
function GetFirstParameterNode(Node: TCodeTreeNode): TCodeTreeNode;
|
function GetFirstParameterNode(Node: TCodeTreeNode): TCodeTreeNode;
|
||||||
function GetExpressionTypeOfTypeIdentifier(
|
function GetExpressionTypeOfTypeIdentifier(
|
||||||
Params: TFindDeclarationParams): TExpressionType;
|
Params: TFindDeclarationParams): TExpressionType;
|
||||||
|
function FindTermTypeAsString(TermAtom: TAtomPosition;
|
||||||
|
CursorNode: TCodeTreeNode; Params: TFindDeclarationParams): string;
|
||||||
protected
|
protected
|
||||||
function FindDeclarationOfIdentAtCursor(
|
function FindDeclarationOfIdentAtCursor(
|
||||||
Params: TFindDeclarationParams): boolean;
|
Params: TFindDeclarationParams): boolean;
|
||||||
|
function IdentifierIsDefined(IdentAtom: TAtomPosition;
|
||||||
|
ContextNode: TCodeTreeNode; Params: TFindDeclarationParams): boolean;
|
||||||
function FindContextNodeAtCursor(
|
function FindContextNodeAtCursor(
|
||||||
Params: TFindDeclarationParams): TFindContext;
|
Params: TFindDeclarationParams): TFindContext;
|
||||||
function FindIdentifierInContext(Params: TFindDeclarationParams): boolean;
|
function FindIdentifierInContext(Params: TFindDeclarationParams): boolean;
|
||||||
@ -1182,6 +1187,18 @@ begin
|
|||||||
Result:=true;
|
Result:=true;
|
||||||
end;
|
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(
|
function TFindDeclarationTool.FindIdentifierInContext(
|
||||||
Params: TFindDeclarationParams): boolean;
|
Params: TFindDeclarationParams): boolean;
|
||||||
{ searches an identifier in context node
|
{ searches an identifier in context node
|
||||||
@ -3746,6 +3763,28 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
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;
|
function TFindDeclarationTool.ConvertNodeToExpressionType(Node: TCodeTreeNode;
|
||||||
Params: TFindDeclarationParams): TExpressionType;
|
Params: TFindDeclarationParams): TExpressionType;
|
||||||
|
|
||||||
@ -5116,6 +5155,107 @@ begin
|
|||||||
end;
|
end;
|
||||||
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 }
|
{ TFindDeclarationParams }
|
||||||
|
|
||||||
|
@ -610,6 +610,7 @@ begin
|
|||||||
Add('LOW',{$ifdef FPC}@{$endif}AllwaysTrue);
|
Add('LOW',{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
Add('HIGH',{$ifdef FPC}@{$endif}AllwaysTrue);
|
Add('HIGH',{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
Add('ORD',{$ifdef FPC}@{$endif}AllwaysTrue);
|
Add('ORD',{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
|
Add('AS',{$ifdef FPC}@{$endif}AllwaysTrue);
|
||||||
end;
|
end;
|
||||||
WordIsKeyWord:=TKeyWordFunctionList.Create;
|
WordIsKeyWord:=TKeyWordFunctionList.Create;
|
||||||
KeyWordLists.Add(WordIsKeyWord);
|
KeyWordLists.Add(WordIsKeyWord);
|
||||||
|
@ -2233,6 +2233,9 @@ function TPascalParserTool.KeyWordFuncBeginEnd: boolean;
|
|||||||
var
|
var
|
||||||
ChildNodeCreated: boolean;
|
ChildNodeCreated: boolean;
|
||||||
begin
|
begin
|
||||||
|
if (CurNode<>nil)
|
||||||
|
and (not (CurNode.Desc in [ctnProcedure,ctnProgram,ctnImplementation])) then
|
||||||
|
RaiseStringExpectedButAtomFound('end');
|
||||||
ChildNodeCreated:=(CurPos.Flag=cafBEGIN) or UpAtomIs('ASM');
|
ChildNodeCreated:=(CurPos.Flag=cafBEGIN) or UpAtomIs('ASM');
|
||||||
if ChildNodeCreated then begin
|
if ChildNodeCreated then begin
|
||||||
CreateChildNode;
|
CreateChildNode;
|
||||||
|
Loading…
Reference in New Issue
Block a user