codetools: identifier completion: show generic parameters

git-svn-id: trunk@50341 -
This commit is contained in:
mattias 2015-11-16 21:28:38 +00:00
parent a8546cf427
commit 07d6956baa
5 changed files with 75 additions and 30 deletions

View File

@ -138,12 +138,12 @@ const
ctnSpecialize = 88;
ctnSpecializeType = 89;
ctnSpecializeParams = 90;
ctnGenericType = 91;// 1. child = ctnGenericName, 2. child = ctnGenericParams, 3. child = type
ctnGenericType = 91;// 1st child = ctnGenericName, 2nd child = ctnGenericParams, 3th child = type
ctnGenericName = 92; // parent = ctnGenericType
ctnGenericParams = 93; // parent = ctnGenericType, children = ctnGenericParameter
ctnGenericParameter = 94; // can has a child ctnGenericConstraint
ctnGenericConstraint = 95; // parent = ctnGenericParameter
ctnReferenceTo = 96; // 1. child = ctnProcedure
ctnReferenceTo = 96; // 1st child = ctnProcedure
ctnConstant = 97;
ctnHintModifier = 98; // deprecated, platform, unimplemented, library, experimental

View File

@ -3739,22 +3739,19 @@ var
end;
end;
function SearchInGenericParams(GenericNode: TCodeTreeNode): boolean;
function SearchInGenericParams(GenParamsNode: TCodeTreeNode): boolean;
var
Node: TCodeTreeNode;
begin
Result:=false;
Node:=GenericNode.FirstChild;
if Node=nil then exit;
Node:=Node.NextBrother;
if (Node=nil) or (Node.Desc<>ctnGenericParams) then exit;
Node:=Node.FirstChild;
if (GenParamsNode=nil) or (GenParamsNode.Desc<>ctnGenericParams) then exit;
Node:=GenParamsNode.FirstChild;
while Node<>nil do begin
if (fdfCollect in Flags)
or CompareSrcIdentifiers(Node.StartPos,Params.Identifier)
then begin
{$IFDEF ShowTriedIdentifiers}
DebugLn(' SearchInGenericParams Identifier found="',GetIdentifier(Params.Identifier),'"');
DebugLn(' SearchInGenericParams Identifier found="',GetIdentifier(@Src[Node.StartPos]),'" at '+CleanPosToStr(Node.StartPos));
{$ENDIF}
// identifier found
Params.SetResult(Self,Node);
@ -3806,6 +3803,44 @@ var
end;
end;
function SearchInGenericType: boolean;
// returns: true if ok to exit
// false if search should continue
var
NameNode: TCodeTreeNode;
begin
Result:=false;
NameNode:=ContextNode.FirstChild;
if NameNode=nil then exit;
// try type name
if (fdfCollect in Flags)
or CompareSrcIdentifiers(NameNode.StartPos,Params.Identifier)
then begin
{$IFDEF ShowTriedIdentifiers}
DebugLn(' Definition Identifier found="',GetIdentifier(Params.Identifier),'"');
{$ENDIF}
// identifier found
Params.SetResult(Self,ContextNode);
Result:=CheckResult(true,true);
if not (fdfCollect in Flags) then begin
if (fdfSkipClassForward in Flags)
and (ContextNode.LastChild.Desc in AllClasses)
and ((ctnsForwardDeclaration and ContextNode.LastChild.SubDesc)<>0)
then begin
FindNonForwardClass(Params);
end;
exit;
end;
end;
// search for enums
Params.ContextNode:=ContextNode;
if FindEnumInContext(Params) then begin
Result:=CheckResult(true,false);
end;
end;
function SearchInTypeOfVarConst: boolean;
// returns: true if ok to exit
// false if search should continue
@ -4056,20 +4091,22 @@ var
{$ENDIF}
LastSearchedNode:=ContextNode;
if (ContextNode.Parent<>nil) and (ContextNode.Parent.Desc=ctnGenericType)
then begin
// after search in the generic, search in the generic parameter names
if SearchInGenericParams(ContextNode.Parent) then begin
FindIdentifierInContext:=true;
{$IFDEF ShowCollect}
if fdfCollect in Flags then
raise Exception.Create('fdfCollect must never return true');
{$ENDIF}
exit(AbortNoCacheResult);
end;
end;
if (ContextNode.Desc in AllClasses) then begin
// after searching in a class definition ...
if (ContextNode.PriorBrother<>nil) and (ContextNode.PriorBrother.Desc=ctnGenericParams)
then begin
// before searching in the ancestors, search in the generic parameters
if SearchInGenericParams(ContextNode.PriorBrother) then begin
FindIdentifierInContext:=true;
{$IFDEF ShowCollect}
if fdfCollect in Flags then
raise Exception.Create('fdfCollect must never return true');
{$ENDIF}
exit(AbortNoCacheResult);
end;
end;
//allow ctnRecordType and ctnTypeTypeBeforeHelper: they can have helpers!
if (fdfSearchInAncestors in Flags) then begin
// after searching in a class definition, search in its ancestors
@ -4354,9 +4391,13 @@ begin
MoveContextNodeToChildren;
ctnTypeDefinition, ctnVarDefinition, ctnConstDefinition,
ctnGenericType, ctnGlobalProperty:
ctnGlobalProperty:
if SearchInTypeVarConstGlobPropDefinition then exit;
ctnGenericType:
if SearchInGenericType then exit;
// ctnGenericParams: skip here, it was searched before searching the ancestors
ctnIdentifier:
if (ContextNode.Parent.Desc in [ctnConstDefinition,ctnVarDefinition])
and (ContextNode=ContextNode.Parent.LastChild)

View File

@ -1215,6 +1215,9 @@ begin
end;
end;
end;
ctnGenericParameter:
Ident:=@FoundContext.Tool.Src[FoundContext.Node.StartPos];
ctnVarDefinition,ctnConstDefinition,ctnEnumIdentifier,ctnLabel,ctnGlobalProperty:
Ident:=@FoundContext.Tool.Src[FoundContext.Node.StartPos];

View File

@ -11,16 +11,16 @@ uses
Classes, SysUtils;
type
generic TGenBaseAction<T> = class
BaseName: T{declaration:fdt_generics.TGenBaseAction.T};
generic TGenBaseAction<GenParam1> = class
BaseName: GenParam1{declaration:fdt_generics.TGenBaseAction.GenParam1};
end;
generic TGenCustomAction<T> = class(specialize TGenBaseAction{declaration:fdt_generics.TGenBaseAction}<T>)
CustomName: T;
generic TGenCustomAction<GenParam2> = class(specialize TGenBaseAction{declaration:fdt_generics.TGenBaseAction}<GenParam2>)
CustomName: GenParam2;
end;
generic TGenAction<T> = class(specialize TGenCustomAction{declaration:fdt_generics.TGenCustomAction}<T>)
ActionName: T;
generic TGenAction<GenParam3> = class(specialize TGenCustomAction{declaration:fdt_generics.TGenCustomAction}<GenParam3>)
ActionName: GenParam3;
end;
implementation

View File

@ -90,7 +90,7 @@ procedure TTestFindDeclaration.FindDeclarations(Filename: string);
end;
Node:=Node.Parent;
end;
debugln(['NodeAsPath ',Result]);
//debugln(['NodeAsPath ',Result]);
end;
var
@ -191,6 +191,7 @@ begin
i:=CodeToolBoss.IdentifierList.GetFilteredCount-1;
while i>=0 do begin
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[i];
//debugln(['TTestFindDeclaration.FindDeclarations ',IdentItem.Identifier]);
l:=length(IdentItem.Identifier);
if ((l=length(ExpectedPath)) or (ExpectedPath[length(ExpectedPath)-l]='.'))
and (CompareText(IdentItem.Identifier,RightStr(ExpectedPath,l))=0)