simple identifier completion implemented

git-svn-id: trunk@3761 -
This commit is contained in:
mattias 2002-12-29 22:24:53 +00:00
parent a05b3421e5
commit 7268e228ed
4 changed files with 233 additions and 10 deletions

View File

@ -42,6 +42,8 @@ interface
// verbosity
{$DEFINE CTDEBUG}
{ $DEFINE ShowFoundIdents}
{ $DEFINE ShowFilteredIdents}
// new features
{ $DEFINE IgnoreErrorAfterCursor}
@ -187,19 +189,22 @@ var
begin
if not (ilfFilteredListNeedsUpdate in FFlags) then exit;
if FFilteredList=nil then FFilteredList:=TList.Create;
if Prefix='' then exit;
FFilteredList.Clear;
AnAVLNode:=FItems.FindLowest;
while AnAVLNode<>nil do begin
CurItem:=TIdentifierListItem(AnAVLNode.Data);
if (CurItem.Identifier<>nil)
and ComparePrefixIdent(PChar(Prefix),CurItem.Identifier) then begin
{$IFDEF CTDEBUG}
{$IFDEF ShowFilteredIdents}
writeln('::: FILTERED ITEM ',FFilteredList.Count,' ',GetIdentifier(CurItem.Identifier));
{$ENDIF}
FFilteredList.Add(CurItem);
end;
AnAVLNode:=FItems.FindSuccessor(AnAVLNode);
end;
{$IFDEF CTDEBUG}
writeln('TIdentifierList.UpdateFilteredList ',FFilteredList.Count,' of ',FItems.Count);
{$ENDIF}
Exclude(FFlags,ilfFilteredListNeedsUpdate);
end;
@ -261,9 +266,11 @@ begin
// proceed searching ...
Result:=ifrProceedSearch;
{$IFDEF ShowFoundIdents}
writeln('::: COLLECT IDENT ',FoundContext.Node.DescAsString,
' "',StringToPascalConst(copy(FoundContext.Tool.Src,FoundContext.Node.StartPos,50)),'"'
,' ',fdfIgnoreUsedUnits in Params.Flags);
{$ENDIF}
if LastGatheredIdentParent<>FoundContext.Node.Parent then begin
// new context level
@ -291,6 +298,9 @@ begin
ctnProcedure,ctnProcedureHead:
Ident:=FoundContext.Tool.GetProcNameIdentifier(FoundContext.Node);
ctnProperty:
Ident:=FoundContext.Tool.GetPropertyNameIdentifier(FoundContext.Node);
end;
if Ident=nil then exit;
@ -303,7 +313,9 @@ begin
NewItem.Node:=FoundContext.Node;
NewItem.Tool:=FoundContext.Tool;
{$IFDEF ShowFoundIdents}
writeln(' IDENT COLLECTED: ',NewItem.AsString);
{$ENDIF}
CurrentIdentifierList.Add(NewItem);
end;

View File

@ -198,6 +198,9 @@ type
function DoAtom: boolean; override;
function ExtractNode(ANode: TCodeTreeNode;
Attr: TProcHeadAttributes): string;
function ExtractPropName(PropNode: TCodeTreeNode;
InUpperCase: boolean): string;
function ExtractPropType(PropNode: TCodeTreeNode;
@ -219,6 +222,8 @@ type
ProcSpec: TProcedureSpecifier): boolean;
function GetProcNameIdentifier(ProcNode: TCodeTreeNode): PChar;
function GetPropertyNameIdentifier(PropNode: TCodeTreeNode): PChar;
function FindVarNode(StartNode: TCodeTreeNode;
const UpperVarName: string): TCodeTreeNode;
function FindTypeNodeOfDefinition(
@ -249,7 +254,9 @@ type
function NodeIsConstructor(ProcNode: TCodeTreeNode): boolean;
function NodeIsPartOfTypeDefinition(ANode: TCodeTreeNode): boolean;
function PropertyIsDefault(PropertyNode: TCodeTreeNode): boolean;
function PropertyNodeHasParamList(PropNode: TCodeTreeNode): boolean;
function ProcNodeHasParamList(ProcNode: TCodeTreeNode): boolean;
procedure MoveCursorToUsesEnd(UsesNode: TCodeTreeNode);
procedure ReadPriorUsedUnit(var UnitNameAtom, InAtom: TAtomPosition);
@ -1655,6 +1662,22 @@ begin
Result:=false;
end;
function TPascalParserTool.ExtractNode(ANode: TCodeTreeNode;
Attr: TProcHeadAttributes): string;
begin
Result:='';
ExtractProcHeadPos:=phepNone;
if (ANode=nil) or (ANode.StartPos<1) then exit;
InitExtraction;
// reparse the clean source
MoveCursorToNodeStart(ANode);
while (ANode.EndPos>CurPos.StartPos)
and (CurPos.StartPos<=SrcLen) do
ExtractNextAtom(true,Attr);
// copy memorystream to Result string
Result:=GetExtraction;
end;
function TPascalParserTool.KeyWordFuncSection: boolean;
// parse section keywords (program, unit, interface, implementation, ...)
@ -3932,6 +3955,39 @@ begin
Result:=UpAtomIs('DEFAULT');
end;
function TPascalParserTool.PropertyNodeHasParamList(PropNode: TCodeTreeNode
): boolean;
begin
// ToDo: ppu, ppw, dcu
Result:=false;
MoveCursorToNodeStart(PropNode);
ReadNextAtom; // read 'property'
ReadNextAtom; // read name
ReadNextAtom;
Result:=AtomIsChar('[');
end;
function TPascalParserTool.ProcNodeHasParamList(ProcNode: TCodeTreeNode
): boolean;
begin
// ToDo: ppu, ppw, dcu
Result:=false;
if ProcNode.Desc=ctnProcedure then
ProcNode:=ProcNode.FirstChild;
MoveCursorToNodeStart(ProcNode);
ReadNextAtom; // read name
ReadNextAtom;
if AtomIsChar('.') then begin
ReadNextAtom;
ReadNextAtom;
end;
Result:=AtomIsChar('(');
end;
procedure TPascalParserTool.MoveCursorToUsesEnd(UsesNode: TCodeTreeNode);
begin
if (UsesNode=nil) or (UsesNode.Desc<>ctnUsesSection) then
@ -4051,7 +4107,28 @@ begin
ProcNode:=ProcNode.FirstChild;
if ProcNode=nil then exit;
end;
Result:=@Src[ProcNode.StartPos];
MoveCursorToNodeStart(ProcNode);
ReadNextAtom;
if not AtomIsIdentifier(false) then exit;
Result:=@Src[CurPos.StartPos];
ReadNextAtom;
if not AtomIsChar('.') then exit;
ReadNextAtom;
Result:=@Src[CurPos.StartPos];
end;
function TPascalParserTool.GetPropertyNameIdentifier(PropNode: TCodeTreeNode
): PChar;
begin
// ToDo: ppu, ppw, dcu
Result:=nil;
if PropNode=nil then exit;
MoveCursorToNodeStart(PropNode);
ReadNextAtom; // read 'propery'
ReadNextAtom; // read name
Result:=@Src[CurPos.StartPos];
end;
function TPascalParserTool.ClassSectionNodeStartsWithWord(

View File

@ -309,7 +309,7 @@ begin
FTextSelectedColor:=clWhite;
{$ENDIF}
Visible := false;
FFontHeight := Canvas.TextHeight('Cyrille de Brebisson');
FFontHeight := Canvas.TextHeight('Cyrille de Brebisson')+2;
Color := clWindow;
ClSelect := clHighlight;
TStringList(FItemList).OnChange := {$IFDEF FPC}@{$ENDIF}StringListChange;
@ -441,7 +441,7 @@ begin
if i + Scroll.Position = Position then begin
Canvas.Brush.Color := clSelect;
Canvas.Pen.Color := clSelect;
Canvas.Rectangle(0, FFontHeight * i, width, FFontHeight * (i + 1));
Canvas.Rectangle(0, (FFontHeight * i)+1, width, (FFontHeight * (i + 1))+1);
Canvas.Pen.Color := clBlack;
{$IFDEF SYN_LAZARUS}
Canvas.Font.Color := TextSelectedColor;
@ -455,7 +455,7 @@ begin
Canvas.Brush.Color := Color;
{$IFDEF SYN_LAZARUS}
Canvas.Font.Color := TextColor;
Canvas.FillRect(Rect(0, FFontHeight * i, width, FFontHeight * (i + 1)));
Canvas.FillRect(Rect(0, (FFontHeight * i)+1, width, (FFontHeight * (i + 1))+1));
{$ELSE}
Canvas.Font.Color := clBlack;
{$ENDIF}
@ -479,7 +479,7 @@ begin
// paint the rest of the background
if NbLinesInWindow > ItemList.Count then begin
canvas.brush.color := color;
i:=FFontHeight * ItemList.Count;
i:=(FFontHeight * ItemList.Count)+1;
canvas.FillRect(Rect(0, i, Width, Height));
end;
{$ENDIF}

View File

@ -35,26 +35,51 @@ interface
uses
Classes, SysUtils, BasicCodeTools, CodeTree, CodeToolManager,
IdentCompletionTool, GraphType, Graphics, EditorOptions,
PascalParserTool, IdentCompletionTool, GraphType, Graphics, EditorOptions,
SynEdit, SynCompletion;
type
TCompletionType = (
ctNone, ctWordCompletion, ctTemplateCompletion, ctIdentCompletion);
TIdentComplValue = (
icvIdentifier, icvProcWithParams, icvIndexedProp);
procedure PaintCompletionItem(const AKey: string; ACanvas: TCanvas;
X, Y: integer; ItemSelected: boolean; Index: integer;
aCompletion : TSynCompletion; CurrentCompletionType: TCompletionType);
function GetIdentCompletionValue(aCompletion : TSynCompletion;
var ValueType: TIdentComplValue): string;
implementation
procedure PaintCompletionItem(const AKey: string; ACanvas: TCanvas;
X, Y: integer; ItemSelected: boolean; Index: integer;
aCompletion : TSynCompletion; CurrentCompletionType: TCompletionType);
function InvertColor(AColor: TColor): TColor;
var Red, Green, Blue: integer;
begin
Result:=clWhite;
Red:=(AColor shr 16) and $ff;
Green:=(AColor shr 8) and $ff;
Blue:=AColor and $ff;
if Red+Green+Blue>$180 then
Result:=clBlack;
end;
procedure SetFontColor(NewColor: TColor);
begin
if ItemSelected then NewColor:=InvertColor(NewColor);
ACanvas.Font.Color:=NewColor;
end;
var
i: Integer;
s: string;
IdentItem: TIdentifierListItem;
AColor: TColor;
ANode: TCodeTreeNode;
begin
with ACanvas do begin
if CurrentCompletionType=ctIdentCompletion then begin
@ -65,10 +90,93 @@ begin
exit;
end;
// first write the type
// var, procedure, property,
// 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;
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:='';
end;
SetFontColor(AColor);
TextOut(x+1,y,s);
inc(x,TextWidth('procedure '));
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];
case IdentItem.Node.Desc of
ctnProcedure:
begin
s:=IdentItem.Tool.ExtractProcHead(IdentItem.Node,
[phpWithoutClassName,phpWithoutName,phpWithVarModifiers,
phpWithParameterNames,phpWithDefaultValues,phpWithResultType,
phpWithOfObject]);
end;
ctnVarDefinition:
begin
ANode:=IdentItem.Tool.FindTypeNodeOfDefinition(IdentItem.Node);
s:=' : '+IdentItem.Tool.ExtractNode(ANode,[]);
end;
ctnTypeDefinition:
begin
ANode:=IdentItem.Tool.FindTypeNodeOfDefinition(IdentItem.Node);
s:=' = '+IdentItem.Tool.ExtractNode(ANode,[]);
end;
ctnConstDefinition:
begin
ANode:=IdentItem.Tool.FindTypeNodeOfDefinition(IdentItem.Node);
s:=' = '+IdentItem.Tool.ExtractNode(ANode,[]);
end;
else
exit;
end;
SetFontColor(clBlack);
TextOut(x+1,y,s);
end else begin
// parse AKey for text and style
@ -105,5 +213,31 @@ begin
end;
end;
function GetIdentCompletionValue(aCompletion : TSynCompletion;
var ValueType: TIdentComplValue): string;
var
Index: Integer;
IdentItem: TIdentifierListItem;
begin
Index:=aCompletion.Position;
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[Index];
ValueType:=icvIdentifier;
if IdentItem<>nil then begin
Result:=GetIdentifier(IdentItem.Identifier);
case IdentItem.Node.Desc of
ctnProcedure:
if IdentItem.Tool.ProcNodeHasParamList(IdentItem.Node) then
ValueType:=icvProcWithParams;
ctnProperty:
if IdentItem.Tool.PropertyNodeHasParamList(IdentItem.Node) then
ValueType:=icvIndexedProp;
end;
end else
Result:='';
end;
end.