mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-07 07:29:23 +01:00
codetools: added compiler procedure length to identifier completion
git-svn-id: trunk@9582 -
This commit is contained in:
parent
619b2afae0
commit
e28e38295b
@ -212,6 +212,8 @@ type
|
|||||||
function ConsistencyCheck: integer; // 0 = ok
|
function ConsistencyCheck: integer; // 0 = ok
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TCodeTree }
|
||||||
|
|
||||||
TCodeTree = class
|
TCodeTree = class
|
||||||
private
|
private
|
||||||
FNodeCount: integer;
|
FNodeCount: integer;
|
||||||
@ -221,6 +223,7 @@ type
|
|||||||
procedure DeleteNode(ANode: TCodeTreeNode);
|
procedure DeleteNode(ANode: TCodeTreeNode);
|
||||||
procedure AddNodeAsLastChild(ParentNode, ANode: TCodeTreeNode);
|
procedure AddNodeAsLastChild(ParentNode, ANode: TCodeTreeNode);
|
||||||
function FindLastPosition: integer;
|
function FindLastPosition: integer;
|
||||||
|
function ContainsNode(ANode: TCodeTreeNode): boolean;
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
constructor Create;
|
constructor Create;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -678,6 +681,14 @@ begin
|
|||||||
Result:=ANode.EndPos;
|
Result:=ANode.EndPos;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCodeTree.ContainsNode(ANode: TCodeTreeNode): boolean;
|
||||||
|
begin
|
||||||
|
if ANode=nil then exit(false);
|
||||||
|
while ANode.Parent<>nil do ANode:=ANode.Parent;
|
||||||
|
while ANode.PriorBrother<>nil do ANode:=ANode.PriorBrother;
|
||||||
|
Result:=ANode=Root;
|
||||||
|
end;
|
||||||
|
|
||||||
function TCodeTree.ConsistencyCheck: integer;
|
function TCodeTree.ConsistencyCheck: integer;
|
||||||
// 0 = ok
|
// 0 = ok
|
||||||
var RealNodeCount: integer;
|
var RealNodeCount: integer;
|
||||||
|
|||||||
@ -82,14 +82,14 @@ type
|
|||||||
Identifier+Range -> Source Position
|
Identifier+Range -> Source Position
|
||||||
and can be interpreted as:
|
and can be interpreted as:
|
||||||
Identifier is a PChar to the beginning of an identifier string.
|
Identifier is a PChar to the beginning of an identifier string.
|
||||||
Range is a clenaed source range (CleanStartPos-CleanEndPos).
|
Range is a cleaned source range (CleanStartPos-CleanEndPos).
|
||||||
Source position is a tuple of NewTool, NewNode, NewCleanPos.
|
Source position is a tuple of NewTool, NewNode, NewCleanPos.
|
||||||
If the current context node is a child of a caching node and it is in the
|
If the current context node is a child of a caching node and it is in the
|
||||||
range, then the result is valid. If NewNode=nil then there is no such
|
range, then the result is valid. If NewNode=nil then there is no such
|
||||||
identifier valid at the context node.
|
identifier valid at the context node.
|
||||||
|
|
||||||
Every node that define local identifiers contains a node cache.
|
Every node that defines local identifiers contains a node cache.
|
||||||
These are: class, proc, record, withstatement
|
These are: class, interface, proc, record, withstatement
|
||||||
|
|
||||||
Because node caches can store information of used units, the cache must be
|
Because node caches can store information of used units, the cache must be
|
||||||
deleted every time a used unit is changed. Currently all node caches are
|
deleted every time a used unit is changed. Currently all node caches are
|
||||||
@ -704,8 +704,16 @@ var
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
OldEntry:=nil;
|
OldEntry:=nil;
|
||||||
|
// consistency checks
|
||||||
if CleanStartPos>=CleanEndPos then
|
if CleanStartPos>=CleanEndPos then
|
||||||
RaiseConflictException('CleanStartPos>=CleanEndPos');
|
RaiseConflictException('CleanStartPos>=CleanEndPos');
|
||||||
|
if (NewNode<>nil) then begin
|
||||||
|
if NewTool=nil then
|
||||||
|
RaiseConflictException('NewNode<>nil and NewTool=nil');
|
||||||
|
if not NewTool.Tree.ContainsNode(NewNode) then
|
||||||
|
RaiseConflictException('NewNode is not a node of NewTool');
|
||||||
|
end;
|
||||||
|
|
||||||
{if GetIdentifier(Identifier)='TDefineAction' then begin
|
{if GetIdentifier(Identifier)='TDefineAction' then begin
|
||||||
DebugLn('[[[[======================================================');
|
DebugLn('[[[[======================================================');
|
||||||
DebugLn('[TCodeTreeNodeCache.Add] Ident=',GetIdentifier(Identifier),
|
DebugLn('[TCodeTreeNodeCache.Add] Ident=',GetIdentifier(Identifier),
|
||||||
|
|||||||
@ -74,7 +74,10 @@ type
|
|||||||
|
|
||||||
TIdentListItemFlag = (
|
TIdentListItemFlag = (
|
||||||
iliHasChilds,
|
iliHasChilds,
|
||||||
iliBaseExprTypeValid
|
iliBaseExprTypeValid,
|
||||||
|
iliIsFunction,
|
||||||
|
iliIsFunctionValid,
|
||||||
|
iliParamListValid
|
||||||
);
|
);
|
||||||
TIdentListItemFlags = set of TIdentListItemFlag;
|
TIdentListItemFlags = set of TIdentListItemFlag;
|
||||||
|
|
||||||
@ -84,7 +87,6 @@ type
|
|||||||
private
|
private
|
||||||
FNext: TIdentifierListItem;
|
FNext: TIdentifierListItem;
|
||||||
FParamList: string;
|
FParamList: string;
|
||||||
FParamListValid: boolean;
|
|
||||||
function GetParamList: string;
|
function GetParamList: string;
|
||||||
procedure SetParamList(const AValue: string);
|
procedure SetParamList(const AValue: string);
|
||||||
public
|
public
|
||||||
@ -110,6 +112,7 @@ type
|
|||||||
function CanBeAssigned: boolean;
|
function CanBeAssigned: boolean;
|
||||||
procedure UpdateBaseContext;
|
procedure UpdateBaseContext;
|
||||||
function HasChilds: boolean;
|
function HasChilds: boolean;
|
||||||
|
function IsFunction: boolean;
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
function CompareParamList(CompareItem: TIdentifierListItem): integer;
|
function CompareParamList(CompareItem: TIdentifierListItem): integer;
|
||||||
public
|
public
|
||||||
@ -854,86 +857,58 @@ const
|
|||||||
if ANode=nil then Result:=0;
|
if ANode=nil then Result:=0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure AddCompilerProcedure(const AProcName, AParameterList: PChar);
|
||||||
|
var
|
||||||
|
NewItem: TIdentifierListItem;
|
||||||
|
begin
|
||||||
|
NewItem:=TIdentifierListItem.Create(
|
||||||
|
icompUnknown,
|
||||||
|
false,
|
||||||
|
CompilerFuncHistoryIndex,
|
||||||
|
AProcName,
|
||||||
|
CompilerFuncLevel,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
ctnProcedure);
|
||||||
|
NewItem.ParamList:=AParameterList;
|
||||||
|
CurrentIdentifierList.Add(NewItem);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure AddCompilerFunction(const AProcName, AParameterList,
|
||||||
|
AResultType: PChar);
|
||||||
|
var
|
||||||
|
NewItem: TIdentifierListItem;
|
||||||
|
begin
|
||||||
|
NewItem:=TIdentifierListItem.Create(
|
||||||
|
icompUnknown,
|
||||||
|
false,
|
||||||
|
CompilerFuncHistoryIndex,
|
||||||
|
AProcName,
|
||||||
|
CompilerFuncLevel,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
ctnProcedure);
|
||||||
|
NewItem.ParamList:=AParameterList;
|
||||||
|
NewItem.Flags:=NewItem.Flags+[iliIsFunction,iliIsFunctionValid];
|
||||||
|
CurrentIdentifierList.Add(NewItem);
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
NewItem: TIdentifierListItem;
|
NewItem: TIdentifierListItem;
|
||||||
ProcNode: TCodeTreeNode;
|
ProcNode: TCodeTreeNode;
|
||||||
begin
|
begin
|
||||||
if Context.Node.Desc in AllPascalStatements then begin
|
if Context.Node.Desc in AllPascalStatements then begin
|
||||||
// begin..end -> add 'SetLength'
|
AddCompilerProcedure('SetLength','array of type; NewLength: integer');
|
||||||
NewItem:=TIdentifierListItem.Create(
|
AddCompilerProcedure('Copy','const s: string; FromPosition, ToPosition: integer');
|
||||||
icompUnknown,
|
AddCompilerProcedure('Write','Args : Arguments');
|
||||||
false,
|
AddCompilerProcedure('WriteLn','Args : Arguments');
|
||||||
CompilerFuncHistoryIndex,
|
AddCompilerProcedure('Read','');
|
||||||
'SetLength',
|
AddCompilerProcedure('ReadLn','');
|
||||||
CompilerFuncLevel,
|
AddCompilerFunction('Length','array of type','ordinal');
|
||||||
nil,
|
AddCompilerFunction('High','Argument','ordinal');
|
||||||
nil,
|
AddCompilerFunction('Low','Argument','ordinal');
|
||||||
ctnProcedure);
|
AddCompilerProcedure('Include','set of enum; enum');
|
||||||
NewItem.ParamList:='array of type; NewLength: integer';
|
AddCompilerProcedure('Exclude','set of enum; enum');
|
||||||
CurrentIdentifierList.Add(NewItem);
|
|
||||||
|
|
||||||
// begin..end -> add 'copy'
|
|
||||||
NewItem:=TIdentifierListItem.Create(
|
|
||||||
icompUnknown,
|
|
||||||
false,
|
|
||||||
CompilerFuncHistoryIndex,
|
|
||||||
'Copy',
|
|
||||||
CompilerFuncLevel,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
ctnProcedure);
|
|
||||||
NewItem.ParamList:='const s: string; FromPosition, ToPosition: integer';
|
|
||||||
CurrentIdentifierList.Add(NewItem);
|
|
||||||
|
|
||||||
// begin..end -> add 'write'
|
|
||||||
NewItem:=TIdentifierListItem.Create(
|
|
||||||
icompUnknown,
|
|
||||||
false,
|
|
||||||
CompilerFuncHistoryIndex,
|
|
||||||
'Write',
|
|
||||||
CompilerFuncLevel,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
ctnProcedure);
|
|
||||||
NewItem.ParamList:='Args : Arguments';
|
|
||||||
CurrentIdentifierList.Add(NewItem);
|
|
||||||
|
|
||||||
// begin..end -> add 'writeln'
|
|
||||||
NewItem:=TIdentifierListItem.Create(
|
|
||||||
icompUnknown,
|
|
||||||
false,
|
|
||||||
CompilerFuncHistoryIndex,
|
|
||||||
'WriteLn',
|
|
||||||
CompilerFuncLevel,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
ctnProcedure);
|
|
||||||
NewItem.ParamList:='Args : Arguments';
|
|
||||||
CurrentIdentifierList.Add(NewItem);
|
|
||||||
|
|
||||||
// begin..end -> add 'read'
|
|
||||||
NewItem:=TIdentifierListItem.Create(
|
|
||||||
icompUnknown,
|
|
||||||
false,
|
|
||||||
CompilerFuncHistoryIndex,
|
|
||||||
'Read',
|
|
||||||
CompilerFuncLevel,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
ctnProcedure);
|
|
||||||
CurrentIdentifierList.Add(NewItem);
|
|
||||||
|
|
||||||
// begin..end -> add 'readln'
|
|
||||||
NewItem:=TIdentifierListItem.Create(
|
|
||||||
icompUnknown,
|
|
||||||
false,
|
|
||||||
CompilerFuncHistoryIndex,
|
|
||||||
'ReadLn',
|
|
||||||
CompilerFuncLevel,
|
|
||||||
nil,
|
|
||||||
nil,
|
|
||||||
ctnProcedure);
|
|
||||||
CurrentIdentifierList.Add(NewItem);
|
|
||||||
|
|
||||||
if Context.Tool.NodeIsInAMethod(Context.Node)
|
if Context.Tool.NodeIsInAMethod(Context.Node)
|
||||||
and (not CurrentIdentifierList.HasIdentifier('Self','')) then begin
|
and (not CurrentIdentifierList.HasIdentifier('Self','')) then begin
|
||||||
@ -1411,7 +1386,6 @@ var
|
|||||||
|
|
||||||
function CheckContextIsParameter(var Ok: boolean): boolean;
|
function CheckContextIsParameter(var Ok: boolean): boolean;
|
||||||
// returns true, on error or context is parameter
|
// returns true, on error or context is parameter
|
||||||
// returns false, if no error and context is not parameter
|
|
||||||
var
|
var
|
||||||
VarNameAtom, ProcNameAtom: TAtomPosition;
|
VarNameAtom, ProcNameAtom: TAtomPosition;
|
||||||
ParameterIndex: integer;
|
ParameterIndex: integer;
|
||||||
@ -1420,15 +1394,17 @@ var
|
|||||||
StartInSubContext: Boolean;
|
StartInSubContext: Boolean;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
|
// check if in a begin..end block
|
||||||
if (CursorNode.Desc<>ctnBeginBlock)
|
if (CursorNode.Desc<>ctnBeginBlock)
|
||||||
and (not CursorNode.HasParentOfType(ctnBeginBlock)) then exit;
|
and (not CursorNode.HasParentOfType(ctnBeginBlock)) then exit;
|
||||||
//DebugLn('CheckContextIsParameter ');
|
// check is cursor is in a parameter list behind an identifier
|
||||||
if not CheckParameterSyntax(CursorNode, CleanCursorPos,
|
if not CheckParameterSyntax(CursorNode, CleanCursorPos,
|
||||||
VarNameAtom, ProcNameAtom, ParameterIndex) then exit;
|
VarNameAtom, ProcNameAtom, ParameterIndex)
|
||||||
|
then exit;
|
||||||
if VarNameAtom.StartPos<1 then exit;
|
if VarNameAtom.StartPos<1 then exit;
|
||||||
//DebugLn('CheckContextIsParameter Variable=',GetAtom(VarNameAtom),' Proc=',GetAtom(ProcNameAtom),' ParameterIndex=',dbgs(ParameterIndex));
|
//DebugLn('CheckContextIsParameter Variable=',GetAtom(VarNameAtom),' Proc=',GetAtom(ProcNameAtom),' ParameterIndex=',dbgs(ParameterIndex));
|
||||||
|
|
||||||
// it is a parameter -> save ParameterIndex
|
// it is a parameter -> create context
|
||||||
Result:=true;
|
Result:=true;
|
||||||
if CurrentContexts=nil then
|
if CurrentContexts=nil then
|
||||||
CurrentContexts:=TCodeContextInfo.Create;
|
CurrentContexts:=TCodeContextInfo.Create;
|
||||||
@ -1448,7 +1424,7 @@ var
|
|||||||
FindCollectionContext(Params,ProcNameAtom.StartPos,CursorNode,
|
FindCollectionContext(Params,ProcNameAtom.StartPos,CursorNode,
|
||||||
GatherContext,ContextExprStartPos,StartInSubContext);
|
GatherContext,ContextExprStartPos,StartInSubContext);
|
||||||
|
|
||||||
// gather declarations of parameter lists
|
// gather declarations of all parameter lists
|
||||||
Params.ContextNode:=GatherContext.Node;
|
Params.ContextNode:=GatherContext.Node;
|
||||||
Params.SetIdentifier(Self,@Src[ProcNameAtom.StartPos],@CollectAllContexts);
|
Params.SetIdentifier(Self,@Src[ProcNameAtom.StartPos],@CollectAllContexts);
|
||||||
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable];
|
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable];
|
||||||
@ -1515,7 +1491,7 @@ end;
|
|||||||
|
|
||||||
function TIdentifierListItem.GetParamList: string;
|
function TIdentifierListItem.GetParamList: string;
|
||||||
begin
|
begin
|
||||||
if not FParamListValid then begin
|
if not (iliParamListValid in Flags) then begin
|
||||||
// Note: if you implement param lists for other than ctnProcedure, check
|
// Note: if you implement param lists for other than ctnProcedure, check
|
||||||
// CompareParamList
|
// CompareParamList
|
||||||
if (Node<>nil) and (Node.Desc=ctnProcedure) then begin
|
if (Node<>nil) and (Node.Desc=ctnProcedure) then begin
|
||||||
@ -1525,7 +1501,7 @@ begin
|
|||||||
//debugln('TIdentifierListItem.GetParamList A ',GetIdentifier(Identifier),' ',Tool.MainFilename,' ',dbgs(Node.StartPos));
|
//debugln('TIdentifierListItem.GetParamList A ',GetIdentifier(Identifier),' ',Tool.MainFilename,' ',dbgs(Node.StartPos));
|
||||||
end else
|
end else
|
||||||
FParamList:='';
|
FParamList:='';
|
||||||
FParamListValid:=true;
|
Include(Flags,iliParamListValid);
|
||||||
end;
|
end;
|
||||||
Result:=FParamList;
|
Result:=FParamList;
|
||||||
end;
|
end;
|
||||||
@ -1533,7 +1509,7 @@ end;
|
|||||||
procedure TIdentifierListItem.SetParamList(const AValue: string);
|
procedure TIdentifierListItem.SetParamList(const AValue: string);
|
||||||
begin
|
begin
|
||||||
FParamList:=AValue;
|
FParamList:=AValue;
|
||||||
FParamListValid:=true;
|
Include(Flags,iliParamListValid);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TIdentifierListItem.AsString: string;
|
function TIdentifierListItem.AsString: string;
|
||||||
@ -1641,10 +1617,20 @@ begin
|
|||||||
Result:=iliHasChilds in Flags;
|
Result:=iliHasChilds in Flags;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TIdentifierListItem.IsFunction: boolean;
|
||||||
|
begin
|
||||||
|
if not (iliIsFunctionValid in Flags) then begin
|
||||||
|
if (Node<>nil)
|
||||||
|
and Tool.NodeIsFunction(Node) then
|
||||||
|
Include(Flags,iliIsFunction);
|
||||||
|
Include(Flags,iliIsFunctionValid);
|
||||||
|
end;
|
||||||
|
Result:=iliIsFunction in Flags;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TIdentifierListItem.Clear;
|
procedure TIdentifierListItem.Clear;
|
||||||
begin
|
begin
|
||||||
FParamList:='';
|
FParamList:='';
|
||||||
FParamListValid:=false;
|
|
||||||
Compatibility:=icompUnknown;
|
Compatibility:=icompUnknown;
|
||||||
HistoryIndex:=0;
|
HistoryIndex:=0;
|
||||||
Identifier:=nil;
|
Identifier:=nil;
|
||||||
|
|||||||
@ -166,8 +166,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
ctnProcedure:
|
ctnProcedure:
|
||||||
if (IdentItem.Node<>nil)
|
if IdentItem.IsFunction then begin
|
||||||
and IdentItem.Tool.NodeIsFunction(IdentItem.Node) then begin
|
|
||||||
AColor:=clTeal;
|
AColor:=clTeal;
|
||||||
s:='function';
|
s:='function';
|
||||||
end else begin
|
end else begin
|
||||||
@ -210,13 +209,15 @@ begin
|
|||||||
ACanvas.Font.Style:=ACanvas.Font.Style+[fsBold];
|
ACanvas.Font.Style:=ACanvas.Font.Style+[fsBold];
|
||||||
s:=GetIdentifier(IdentItem.Identifier);
|
s:=GetIdentifier(IdentItem.Identifier);
|
||||||
if MeasureOnly then
|
if MeasureOnly then
|
||||||
Inc(Result.X, ACanvas.TextWidth(s))
|
Inc(Result.X, 1+ACanvas.TextWidth(s))
|
||||||
else
|
else begin
|
||||||
ACanvas.TextOut(x+1,y,s);
|
ACanvas.TextOut(x+1,y,s);
|
||||||
inc(x,ACanvas.TextWidth(s));
|
inc(x,ACanvas.TextWidth(s));
|
||||||
if x>MaxX then exit;
|
if x>MaxX then exit;
|
||||||
|
end;
|
||||||
ACanvas.Font.Style:=ACanvas.Font.Style-[fsBold];
|
ACanvas.Font.Style:=ACanvas.Font.Style-[fsBold];
|
||||||
|
|
||||||
|
s:='';
|
||||||
if IdentItem.Node<>nil then begin
|
if IdentItem.Node<>nil then begin
|
||||||
case IdentItem.Node.Desc of
|
case IdentItem.Node.Desc of
|
||||||
|
|
||||||
@ -259,20 +260,27 @@ begin
|
|||||||
s:=copy(s,1,50);
|
s:=copy(s,1,50);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
else
|
|
||||||
exit;
|
|
||||||
|
|
||||||
end;
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
// IdentItem.Node=nil
|
// IdentItem.Node=nil
|
||||||
exit;
|
case IdentItem.GetDesc of
|
||||||
|
ctnProcedure:
|
||||||
|
begin
|
||||||
|
s:=IdentItem.ParamList;
|
||||||
|
if s<>'' then
|
||||||
|
s:='('+s+')';
|
||||||
|
s:=s+';'
|
||||||
|
end;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
if s<>'' then begin
|
||||||
SetFontColor(clBlack);
|
SetFontColor(clBlack);
|
||||||
if MeasureOnly then
|
if MeasureOnly then
|
||||||
Inc(Result.X, ACanvas.TextWidth(s))
|
Inc(Result.X, ACanvas.TextWidth(s))
|
||||||
else
|
else
|
||||||
ACanvas.TextOut(x+1,y,s);
|
ACanvas.TextOut(x+1,y,s);
|
||||||
|
end;
|
||||||
|
|
||||||
end else begin
|
end else begin
|
||||||
// parse AKey for text and style
|
// parse AKey for text and style
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user