ident completion: added special identifiers Self and Result

git-svn-id: trunk@3784 -
This commit is contained in:
mattias 2003-01-04 13:12:00 +00:00
parent 793dcc8be5
commit cacafb6ba0
2 changed files with 203 additions and 104 deletions

View File

@ -79,6 +79,7 @@ type
FParamList: string;
FParamListValid: boolean;
function GetParamList: string;
procedure SetParamList(const AValue: string);
public
Compatibility: TIdentifierCompatibility;
HasChilds: boolean; // identifier can contain childs (class, record)
@ -87,8 +88,10 @@ type
Level: integer;
Node: TCodeTreeNode;
Tool: TFindDeclarationTool;
DefaultDesc: TCodeTreeNodeDesc;
function AsString: string;
property ParamList: string read GetParamList;
function GetDesc: TCodeTreeNodeDesc;
property ParamList: string read GetParamList write SetParamList;
end;
TIdentifierListFlag = (ilfFilteredListNeedsUpdate);
@ -101,6 +104,7 @@ type
FHistory: TIdentifierHistoryList;
FItems: TAVLTree; // tree of TIdentifierListItem (completely sorted)
FIdentView: TAVLTree; // tree of TIdentHistListItem sorted for identifiers
FIdentSearchItem: TIdentifierListItem;
FPrefix: string;
procedure SetHistory(const AValue: TIdentifierHistoryList);
procedure UpdateFilteredList;
@ -113,6 +117,7 @@ type
procedure Add(NewItem: TIdentifierListItem);
function Count: integer;
function GetFilteredCount: integer;
function HasIdentifier(Identifier: PChar; const ParamList: string): boolean;
public
property Prefix: string read FPrefix write SetPrefix;
property FilteredItems[Index: integer]: TIdentifierListItem
@ -159,7 +164,10 @@ type
CurrentIdentifierList: TIdentifierList;
function CollectAllIdentifiers(Params: TFindDeclarationParams;
const FoundContext: TFindContext): TIdentifierFoundResult;
procedure GatherPredefinedIdentifiers;
procedure GatherPredefinedIdentifiers(CleanPos: integer;
const Context: TFindContext);
procedure GatherUsefulIdentifiers(CleanPos: integer;
const Context: TFindContext);
public
function GatherIdentifiers(const CursorPos: TCodeXYPosition;
var IdentifierList: TIdentifierList): boolean;
@ -320,6 +328,7 @@ begin
FFlags:=[ilfFilteredListNeedsUpdate];
FItems:=TAVLTree.Create(@CompareIdentListItems);
FIdentView:=TAVLTree.Create(@CompareIdentListItemsForIdents);
FIdentSearchItem:=TIdentifierListItem.Create;
end;
destructor TIdentifierList.Destroy;
@ -328,6 +337,7 @@ begin
FItems.Free;
FIdentView.Free;
FFilteredList.Free;
FIdentSearchItem.Free;
inherited Destroy;
end;
@ -366,6 +376,15 @@ begin
Result:=FFilteredList.Count;
end;
function TIdentifierList.HasIdentifier(Identifier: PChar;
const ParamList: string): boolean;
begin
FIdentSearchItem.Identifier:=Identifier;
FIdentSearchItem.ParamList:='';
Result:=FIdentView.FindKey(FIdentSearchItem,
@CompareIdentListItemsForIdents)<>nil;
end;
{ TIdentCompletionTool }
function TIdentCompletionTool.CollectAllIdentifiers(
@ -437,9 +456,64 @@ begin
CurrentIdentifierList.Add(NewItem);
end;
procedure TIdentCompletionTool.GatherPredefinedIdentifiers;
procedure TIdentCompletionTool.GatherPredefinedIdentifiers(CleanPos: integer;
const Context: TFindContext);
// Add predefined identifiers
function StatementLevel: integer;
var
ANode: TCodeTreeNode;
begin
Result:=0;
ANode:=Context.Node;
while (ANode<>nil) and (not (ANode.Desc in [ctnBeginBlock,ctnAsmBlock])) do
begin
ANode:=ANode.Parent;
inc(Result);
end;
if ANode=nil then Result:=0;
end;
var
NewItem: TIdentifierListItem;
ProcNode: TCodeTreeNode;
begin
// ToDo:
if Context.Node.Desc in AllPascalStatements then begin
if Context.Tool.NodeIsInAMethod(Context.Node)
and (not CurrentIdentifierList.HasIdentifier('Self','')) then begin
// method body -> add 'Self'
NewItem:=TIdentifierListItem.Create;
NewItem.Compatibility:=icompUnknown;
NewItem.HasChilds:=true;
NewItem.Identifier:='Self';
NewItem.Level:=StatementLevel;
NewItem.Node:=nil;
NewItem.Tool:=nil;
NewItem.DefaultDesc:=ctnVarDefinition;
CurrentIdentifierList.Add(NewItem);
end;
ProcNode:=Context.Node.GetNodeOfType(ctnProcedure);
if Context.Tool.NodeIsFunction(ProcNode)
and (not CurrentIdentifierList.HasIdentifier('Result','')) then begin
// function body -> add 'Result'
NewItem:=TIdentifierListItem.Create;
NewItem.Compatibility:=icompUnknown;
NewItem.HasChilds:=false;
NewItem.Identifier:='Result';
NewItem.Level:=StatementLevel;
NewItem.Node:=nil;
NewItem.Tool:=nil;
NewItem.DefaultDesc:=ctnNone;
CurrentIdentifierList.Add(NewItem);
end;
end;
end;
procedure TIdentCompletionTool.GatherUsefulIdentifiers(CleanPos: integer;
const Context: TFindContext);
begin
GatherPredefinedIdentifiers(CleanPos,Context);
end;
function TIdentCompletionTool.GatherIdentifiers(
@ -519,11 +593,11 @@ begin
{$ENDIF}
GatherContext.Tool.FindIdentifierInContext(Params);
end;
// add predefined identifiers
// add useful identifiers without context
{$IFDEF CTDEBUG}
writeln('TIdentCompletionTool.GatherIdentifiers G');
{$ENDIF}
GatherPredefinedIdentifiers;
GatherUsefulIdentifiers(CleanCursorPos,GatherContext);
Result:=true;
finally
@ -541,15 +615,23 @@ end;
function TIdentifierListItem.GetParamList: string;
begin
if not FParamListValid then begin
if Node.Desc=ctnProcedure then
if (Node<>nil) and (Node.Desc=ctnProcedure) then
FParamList:=Tool.ExtractProcHead(Node,
[phpWithoutClassKeyword,phpWithoutClassName,
phpWithoutName,phpInUpperCase]);
phpWithoutName,phpInUpperCase])
else
FParamList:='';
FParamListValid:=true;
end;
Result:=FParamList;
end;
procedure TIdentifierListItem.SetParamList(const AValue: string);
begin
FParamList:=AValue;
FParamListValid:=true;
end;
function TIdentifierListItem.AsString: string;
begin
Result:=IdentifierCompatibilityNames[Compatibility];
@ -560,9 +642,19 @@ begin
Result:=Result+' History='+IntToStr(HistoryIndex);
Result:=Result+' Ident='+GetIdentifier(Identifier);
Result:=Result+' Lvl='+IntToStr(Level);
Result:=Result+' File='+Tool.MainFilename;
Result:=Result+' Node='+Node.DescAsString
+' "'+StringToPascalConst(copy(Tool.Src,Node.StartPos,50))+'"';
if Tool<>nil then
Result:=Result+' File='+Tool.MainFilename;
if Node<>nil then
Result:=Result+' Node='+Node.DescAsString
+' "'+StringToPascalConst(copy(Tool.Src,Node.StartPos,50))+'"';
end;
function TIdentifierListItem.GetDesc: TCodeTreeNodeDesc;
begin
if Node<>nil then
Result:=Node.Desc
else
Result:=DefaultDesc;
end;
{ TIdentifierHistoryList }
@ -628,7 +720,7 @@ begin
// create a new history item
NewHistItem:=TIdentHistListItem.Create;
NewHistItem.Identifier:=GetIdentifier(NewItem.Identifier);
NewHistItem.NodeDesc:=NewItem.Node.Desc;
NewHistItem.NodeDesc:=NewItem.GetDesc;
NewHistItem.ParamList:=NewItem.ParamList;
AdjustIndex:=0;
end;

View File

@ -81,69 +81,70 @@ var
AColor: TColor;
ANode: TCodeTreeNode;
begin
with ACanvas do begin
if CurrentCompletionType=ctIdentCompletion then begin
// draw
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[Index];
if IdentItem=nil then begin
TextOut(x+1, y, 'PaintCompletionItem: BUG in codetools');
exit;
if CurrentCompletionType=ctIdentCompletion then begin
// draw
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[Index];
if IdentItem=nil then begin
ACanvas.TextOut(x+1, y, 'PaintCompletionItem: BUG in codetools');
exit;
end;
// first write the type
// var, procedure, property, function, type, const
case IdentItem.GetDesc of
ctnVarDefinition:
begin
AColor:=clMaroon;
s:='var';
end;
// first write the type
// var, procedure, property, function, type, const
case IdentItem.Node.Desc of
ctnVarDefinition:
begin
AColor:=clMaroon;
s:='var';
end;
ctnTypeDefinition:
begin
AColor:=clDkGray;
s:='type';
end;
ctnTypeDefinition:
begin
AColor:=clDkGray;
s:='type';
end;
ctnConstDefinition:
begin
AColor:=clOlive;
s:='const';
end;
ctnConstDefinition:
begin
AColor:=clOlive;
s:='const';
end;
ctnProcedure:
if IdentItem.Tool.NodeIsFunction(IdentItem.Node) then begin
AColor:=clTeal;
s:='function';
end else begin
AColor:=clNavy;
s:='procedure';
end;
ctnProperty:
begin
AColor:=clPurple;
s:='property';
end;
else
AColor:=clGray;
s:='';
ctnProcedure:
if (IdentItem.Node<>nil)
and IdentItem.Tool.NodeIsFunction(IdentItem.Node) then begin
AColor:=clTeal;
s:='function';
end else begin
AColor:=clNavy;
s:='procedure';
end;
SetFontColor(AColor);
TextOut(x+1,y,s);
inc(x,TextWidth('procedure '));
ctnProperty:
begin
AColor:=clPurple;
s:='property';
end;
SetFontColor(clBlack);
Font.Style:=Font.Style+[fsBold];
s:=GetIdentifier(IdentItem.Identifier);
TextOut(x+1,y,s);
inc(x,TextWidth(s));
Font.Style:=Font.Style-[fsBold];
else
AColor:=clGray;
s:='';
end;
SetFontColor(AColor);
ACanvas.TextOut(x+1,y,s);
inc(x,ACanvas.TextWidth('procedure '));
SetFontColor(clBlack);
ACanvas.Font.Style:=ACanvas.Font.Style+[fsBold];
s:=GetIdentifier(IdentItem.Identifier);
ACanvas.TextOut(x+1,y,s);
inc(x,ACanvas.TextWidth(s));
ACanvas.Font.Style:=ACanvas.Font.Style-[fsBold];
if IdentItem.Node<>nil then begin
case IdentItem.Node.Desc of
ctnProcedure:
begin
s:=IdentItem.Tool.ExtractProcHead(IdentItem.Node,
@ -151,14 +152,14 @@ begin
phpWithParameterNames,phpWithDefaultValues,phpWithResultType,
phpWithOfObject]);
end;
ctnProperty:
begin
s:=IdentItem.Tool.ExtractProperty(IdentItem.Node,
[phpWithoutName,phpWithVarModifiers,
phpWithParameterNames,phpWithDefaultValues,phpWithResultType]);
end;
ctnVarDefinition:
begin
ANode:=IdentItem.Tool.FindTypeNodeOfDefinition(IdentItem.Node);
@ -179,42 +180,46 @@ begin
else
exit;
end;
SetFontColor(clBlack);
TextOut(x+1,y,s);
end;
end else begin
// parse AKey for text and style
i := 1;
while i <= Length(AKey) do begin
case AKey[i] of
#1, #2:
begin
// set color
Font.Color := (Ord(AKey[i + 3]) shl 8 + Ord(AKey[i + 2])) shl 8
+ Ord(AKey[i + 1]);
inc(i, 4);
end;
#3:
begin
// set style
case AKey[i + 1] of
'B': Font.Style := Font.Style + [fsBold];
'b': Font.Style := Font.Style - [fsBold];
'U': Font.Style := Font.Style + [fsUnderline];
'u': Font.Style := Font.Style - [fsUnderline];
'I': Font.Style := Font.Style + [fsItalic];
'i': Font.Style := Font.Style - [fsItalic];
end;
inc(i, 2);
end;
else
TextOut(x+1, y, AKey[i]);
x := x + TextWidth(AKey[i]);
inc(i);
// IdentItem.Node=nil
exit;
end;
SetFontColor(clBlack);
ACanvas.TextOut(x+1,y,s);
end else begin
// parse AKey for text and style
i := 1;
while i <= Length(AKey) do begin
case AKey[i] of
#1, #2:
begin
// set color
ACanvas.Font.Color := (Ord(AKey[i + 3]) shl 8
+ Ord(AKey[i + 2])) shl 8
+ Ord(AKey[i + 1]);
inc(i, 4);
end;
#3:
begin
// set style
case AKey[i + 1] of
'B': ACanvas.Font.Style := ACanvas.Font.Style + [fsBold];
'b': ACanvas.Font.Style := ACanvas.Font.Style - [fsBold];
'U': ACanvas.Font.Style := ACanvas.Font.Style + [fsUnderline];
'u': ACanvas.Font.Style := ACanvas.Font.Style - [fsUnderline];
'I': ACanvas.Font.Style := ACanvas.Font.Style + [fsItalic];
'i': ACanvas.Font.Style := ACanvas.Font.Style - [fsItalic];
end;
inc(i, 2);
end;
else
ACanvas.TextOut(x+1, y, AKey[i]);
x := x + ACanvas.TextWidth(AKey[i]);
inc(i);
end;
end;
end;
@ -231,14 +236,16 @@ begin
ValueType:=icvIdentifier;
if IdentItem<>nil then begin
Result:=GetIdentifier(IdentItem.Identifier);
case IdentItem.Node.Desc of
case IdentItem.GetDesc of
ctnProcedure:
if IdentItem.Tool.ProcNodeHasParamList(IdentItem.Node) then
if (IdentItem.Node<>nil)
and IdentItem.Tool.ProcNodeHasParamList(IdentItem.Node) then
ValueType:=icvProcWithParams;
ctnProperty:
if IdentItem.Tool.PropertyNodeHasParamList(IdentItem.Node) then
if (IdentItem.Node<>nil)
and IdentItem.Tool.PropertyNodeHasParamList(IdentItem.Node) then
ValueType:=icvIndexedProp;
end;