IDE: word identifier completion: gather words on filter - and search in all units

git-svn-id: trunk@58167 -
This commit is contained in:
ondrej 2018-06-07 14:02:43 +00:00
parent 899548c919
commit 8b29af0724
4 changed files with 89 additions and 49 deletions

View File

@ -222,12 +222,16 @@ type
ilcfDontAllowProcedures// context doesn't allow procedures (e.g. in function parameter, after other operator, in if codition etc. - Delphi mode supports assignment of procedures!)
);
TIdentifierListContextFlags = set of TIdentifierListContextFlag;
TOnGatherUserIdentifiersToFilteredList = procedure(Sender: TIdentifierList;
FilteredList: TFPList; PriorityCount: Integer) of object;
TIdentifierList = class
private
FContext: TFindContext;
FNewMemberVisibility: TCodeTreeNodeDesc;
FContextFlags: TIdentifierListContextFlags;
FOnGatherUserIdentifiersToFilteredList: TOnGatherUserIdentifiersToFilteredList;
FSortForHistory: boolean;
FSortForScope: boolean;
FStartAtom: TAtomPosition;
@ -263,6 +267,7 @@ type
function HasIdentifier(Identifier: PChar; const ParamList: string): boolean;
function FindIdentifier(Identifier: PChar; const ParamList: string): TIdentifierListItem;
function FindIdentifier(Identifier: PChar; PreferProc: boolean): TIdentifierListItem;
function FindIdentifier(Identifier: PChar): TIdentifierListItem;
function FindCreatedIdentifier(const Ident: string): integer;
function CreateIdentifier(const Ident: string): PChar;
function StartUpAtomInFrontIs(const s: string): boolean;
@ -290,6 +295,8 @@ type
property StartContextPos: TCodeXYPosition
read FStartContextPos write FStartContextPos;
property ContainsFilter: Boolean read FContainsFilter write FContainsFilter;
property OnGatherUserIdentifiersToFilteredList: TOnGatherUserIdentifiersToFilteredList
read FOnGatherUserIdentifiersToFilteredList write FOnGatherUserIdentifiersToFilteredList;
end;
//----------------------------------------------------------------------------
@ -667,6 +674,8 @@ begin
end;
AnAVLNode:=FItems.FindSuccessor(AnAVLNode);
end;
if Assigned(FOnGatherUserIdentifiersToFilteredList) then
FOnGatherUserIdentifiersToFilteredList(Self, FFilteredList, cPriorityCount);
{$IFDEF CTDEBUG}
DebugLn(['TIdentifierList.UpdateFilteredList ',dbgs(FFilteredList.Count),' of ',dbgs(FItems.Count)]);
{$ENDIF}
@ -866,6 +875,19 @@ begin
end;
end;
function TIdentifierList.FindIdentifier(Identifier: PChar): TIdentifierListItem;
var
Node: TAVLTreeNode;
begin
FIdentSearchItem.Identifier:=Identifier;
// ignore ParamList
Node:=FIdentView.FindKey(FIdentSearchItem,@CompareIdentListSearchWithItemsWithoutParams);
if Assigned(Node) then
Result := TIdentifierListItem(Node.Data)
else
Result := nil;
end;
function TIdentifierList.CreateIdentifier(const Ident: string): PChar;
var
i: Integer;

View File

@ -619,6 +619,8 @@ type
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
procedure CodeToolBossGatherUserIdentifiers(Sender: TIdentCompletionTool;
const ContextFlags: TIdentifierListContextFlags);
procedure CodeToolBossGatherUserIdentifiersToFilteredList(
Sender: TIdentifierList; FilteredList: TFPList; PriorityCount: Integer);
function CTMacroFunctionProject(Data: Pointer): boolean;
procedure CompilerParseStampIncHandler;
@ -653,7 +655,7 @@ type
OIChangedTimer: TIdleTimer;
FIdentifierWordCompletionWordList: TStringList;
FIdentifierWordCompletion: TWordCompletion;
FIdentifierWordCompletionEnabled: Boolean;
procedure DoDropFilesAsync(Data: PtrInt);
procedure RenameInheritedMethods(AnUnitInfo: TUnitInfo; List: TStrings);
@ -661,7 +663,8 @@ type
procedure IdentifierWordCompletionGetSource(var Source: TStrings;
var SourceTopLine,SourceBottomLine: integer;
var IgnoreWordEndPos: TPoint; SourceIndex: integer);
procedure DoAddWordsToIdentCompletion;
procedure DoAddWordsToIdentCompletion(Sender: TIdentifierList;
FilteredList: TFPList; PriorityCount: Integer);
// form editor and designer
procedure DoBringToFrontFormOrUnit;
procedure DoBringToFrontFormOrInspector(ForceInspector: boolean);
@ -1675,7 +1678,6 @@ begin
FreeThenNil(ObjectInspector1);
FreeThenNil(SourceEditorManagerIntf);
FreeAndNil(FIdentifierWordCompletionWordList);
FreeAndNil(FIdentifierWordCompletion);
// disconnect handlers
Application.RemoveAllHandlersOfObject(Self);
@ -2032,8 +2034,14 @@ procedure TMainIDE.CodeToolBossGatherUserIdentifiers(
Sender: TIdentCompletionTool; const ContextFlags: TIdentifierListContextFlags
);
begin
if not (ilcfStartIsSubIdent in ContextFlags) then
DoAddWordsToIdentCompletion;
FIdentifierWordCompletionEnabled := not (ilcfStartIsSubIdent in ContextFlags);
end;
procedure TMainIDE.CodeToolBossGatherUserIdentifiersToFilteredList(
Sender: TIdentifierList; FilteredList: TFPList; PriorityCount: Integer);
begin
if FIdentifierWordCompletionEnabled then
DoAddWordsToIdentCompletion(Sender, FilteredList, PriorityCount);
end;
{------------------------------------------------------------------------------}
@ -6473,27 +6481,29 @@ begin
Result := SourceFileMgr.AddUnitToProject(AEditor);
end;
procedure TMainIDE.DoAddWordsToIdentCompletion;
procedure TMainIDE.DoAddWordsToIdentCompletion(Sender: TIdentifierList;
FilteredList: TFPList; PriorityCount: Integer);
var
New: TIdentifierListItem;
I: Integer;
begin
if FIdentifierWordCompletionWordList=nil then
FIdentifierWordCompletionWordList:=TStringList.Create
else
FIdentifierWordCompletionWordList.Clear;
if FIdentifierWordCompletion=nil then
begin
FIdentifierWordCompletion := TWordCompletion.Create;
FIdentifierWordCompletion.OnGetSource := @IdentifierWordCompletionGetSource;
end;
FIdentifierWordCompletionWordList:=TStringList.Create;
FIdentifierWordCompletionWordList.OwnsObjects := True;
end else
FIdentifierWordCompletionWordList.Clear;
FIdentifierWordCompletion.GetWordList(FIdentifierWordCompletionWordList, '', False, 1000); // do not get words with prefix because the identifier list isn't reloaded when prefix changes
AWordCompletion.GetWordList(FIdentifierWordCompletionWordList, Sender.Prefix, Sender.ContainsFilter, False, 100);
for I := FIdentifierWordCompletionWordList.Count-1 downto 0 do
begin
New := CIdentifierListItem.Create(WordCompatibility, False, WordHistoryIndex,
PChar(FIdentifierWordCompletionWordList[I]), WordLevel, nil, nil, ctnWord);
CodeToolBoss.IdentifierList.Add(New);
if Sender.FindIdentifier(PChar(FIdentifierWordCompletionWordList[I]))=nil then
begin
New := CIdentifierListItem.Create(WordCompatibility, False, WordHistoryIndex,
PChar(FIdentifierWordCompletionWordList[I]), WordLevel, nil, nil, ctnWord);
FIdentifierWordCompletionWordList.Objects[I] := New;
FilteredList.Add(New);
end;
end;
end;
@ -9284,6 +9294,7 @@ begin
CodeToolBoss.DefineTree.OnGetVirtualDirectoryDefines:=
@CodeToolBossGetVirtualDirectoryDefines;
CodeToolBoss.DefineTree.OnPrepareTree:=@CodeToolBossPrepareTree;
CodeToolBoss.IdentifierList.OnGatherUserIdentifiersToFilteredList := @CodeToolBossGatherUserIdentifiersToFilteredList;
CodeToolBoss.DefineTree.MacroFunctions.AddExtended(
'PROJECT',nil,@CTMacroFunctionProject);

View File

@ -1404,6 +1404,9 @@ var
EnglishModifiedLGPLNotice: string;
EnglishMITNotice: string;
var
AWordCompletion: TWordCompletion = nil;
implementation
{$R *.lfm}
@ -1423,7 +1426,6 @@ const
SoftCenterMaximum = 8;
var
AWordCompletion: TWordCompletion = nil;
AutoStartCompletionBoxTimer: TIdleTimer = nil;
SourceCompletionCaretXY: TPoint;
PasBeautifier: TSynBeautifierPascal;
@ -2532,7 +2534,7 @@ begin
CurStr:=CurrentString;
SL:=TStringList.Create;
try
aWordCompletion.GetWordList(SL, CurStr, false, 100);
aWordCompletion.GetWordList(SL, CurStr, CodeToolBoss.IdentifierList.ContainsFilter, false, 100);
ItemList:=SL;
finally
SL.Free;
@ -2577,7 +2579,7 @@ begin
if CurrentCompletionType=ctWordCompletion then begin
SL:=TStringList.Create;
try
aWordCompletion.GetWordList(SL, NewPrefix, false, 100);
aWordCompletion.GetWordList(SL, NewPrefix, CodeToolBoss.IdentifierList.ContainsFilter, false, 100);
ItemList:=SL;
finally
SL.Free;

View File

@ -40,8 +40,8 @@ type
procedure AddWord(const AWord:string);
property WordBufferCapacity:integer
read GetWordBufferCapacity write SetWordBufferCapacity;
procedure GetWordList(AWordList:TStrings; const Prefix:String;
CaseSensitive:boolean; MaxResults:integer);
procedure GetWordList(AWordList:TStrings; const Filter: String;
ContainsFilter, CaseSensitive:boolean; MaxResults:integer);
procedure CompletePrefix(const Prefix: string; var CompletedPrefix: string;
CaseSensitive:boolean);
public
@ -72,9 +72,10 @@ end;
{ TWordCompletion }
procedure TWordCompletion.GetWordList(AWordList: TStrings;
const Prefix: String; CaseSensitive: boolean; MaxResults: integer);
var i, j, Line, x, PrefixLen, MaxHash, LineLen: integer;
UpPrefix, LineText, UpLineText, NewWord: string;
const Filter: String; ContainsFilter, CaseSensitive: boolean;
MaxResults: integer);
var i, j, Line, x, FilterLen, MaxHash, LineLen: integer;
UpFilter, LineText, UpLineText, NewWord: string;
SourceText: TStringList;
HashList: ^integer;// index list. Every entry points to a word in the AWordList
SourceTextIndex, SourceTopLine, SourceBottomLine:integer;
@ -110,6 +111,28 @@ var i, j, Line, x, PrefixLen, MaxHash, LineLen: integer;
end;
end;
procedure AddIfMatch(const AWord:string);
begin
if CaseSensitive then begin
if ContainsFilter then
begin
if pos(Filter, AWord)>0 then
Add(NewWord);
end else
if copy(AWord,1,FilterLen)=Filter then
Add(NewWord);
end else
begin
if ContainsFilter then
begin
if pos(UpFilter, UpperCase(AWord))>0 then
Add(AWord);
end else
if CompareText(copy(NewWord,1,FilterLen),UpFilter)=0 then
Add(NewWord)
end;
end;
// TWordCompletion.GetWordList
begin
AWordList.Clear;
@ -118,19 +141,13 @@ begin
GetMem(HashList,MaxHash*SizeOf(Integer));
try
for i:=0 to MaxHash-1 do HashList[i]:=-1;
PrefixLen:=length(Prefix);
FilterLen:=length(Filter);
AWordList.Capacity:=MaxResults;
UpPrefix:=uppercase(Prefix);
UpFilter:=uppercase(Filter);
// first add all recently used words
i:=FWordBuffer.Count-1;
while (i>=0) and (AWordList.Count<MaxResults) do begin
NewWord:=FWordBuffer[i];
if CaseSensitive then begin
if copy(NewWord,1,PrefixLen)=Prefix then
Add(NewWord);
end else if CompareText(copy(NewWord,1,PrefixLen),UpPrefix)=0 then begin
Add(NewWord)
end;
AddIfMatch(FWordBuffer[i]);
dec(i);
end;
if AWordList.Count>=MaxResults then exit;
@ -163,20 +180,8 @@ begin
repeat
inc(i);
until (i>LineLen) or (CharTable[LineText[i]]=ctNone);
if i-x>=PrefixLen then begin
if CaseSensitive then begin
j:=1;
while (j<=PrefixLen) and (Prefix[j]=LineText[x+j-1]) do
inc(j);
if (j>PrefixLen) and (Line<>IgnoreWordEndPos.Y) and (i<>IgnoreWordEndPos.X) then
Add(copy(LineText,x,i-x));
end else begin
j:=1;
while (j<=PrefixLen) and (UpPrefix[j]=UpLineText[x+j-1]) do
inc(j);
if (j>PrefixLen) and (Line<>IgnoreWordEndPos.Y) and (i<>IgnoreWordEndPos.X) then
Add(copy(LineText,x,i-x))
end;
if (i-x>=FilterLen) and (Line<>IgnoreWordEndPos.Y) and (i<>IgnoreWordEndPos.X) then begin
AddIfMatch(copy(LineText,x,i-x));
if AWordList.Count>=MaxResults then exit;
end;
x:=i;
@ -213,7 +218,7 @@ begin
WordList:=TStringList.Create;
try
// fetch all words with Prefix
GetWordList(WordList,Prefix,CaseSensitive,10000);
GetWordList(WordList,Prefix,False,CaseSensitive,10000);
if WordList.Count=0 then exit;
// find the biggest prefix of all available words
CompletedPrefix:=WordList[0];