mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-11-03 15:39:26 +01:00
simple identifier completion implemented
git-svn-id: trunk@3761 -
This commit is contained in:
parent
a05b3421e5
commit
7268e228ed
@ -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;
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user