mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-03 09:37:13 +01:00
codetools: identifier completion: show generic parameters
git-svn-id: trunk@50341 -
This commit is contained in:
parent
a8546cf427
commit
07d6956baa
@ -138,12 +138,12 @@ const
|
|||||||
ctnSpecialize = 88;
|
ctnSpecialize = 88;
|
||||||
ctnSpecializeType = 89;
|
ctnSpecializeType = 89;
|
||||||
ctnSpecializeParams = 90;
|
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
|
ctnGenericName = 92; // parent = ctnGenericType
|
||||||
ctnGenericParams = 93; // parent = ctnGenericType, children = ctnGenericParameter
|
ctnGenericParams = 93; // parent = ctnGenericType, children = ctnGenericParameter
|
||||||
ctnGenericParameter = 94; // can has a child ctnGenericConstraint
|
ctnGenericParameter = 94; // can has a child ctnGenericConstraint
|
||||||
ctnGenericConstraint = 95; // parent = ctnGenericParameter
|
ctnGenericConstraint = 95; // parent = ctnGenericParameter
|
||||||
ctnReferenceTo = 96; // 1. child = ctnProcedure
|
ctnReferenceTo = 96; // 1st child = ctnProcedure
|
||||||
ctnConstant = 97;
|
ctnConstant = 97;
|
||||||
ctnHintModifier = 98; // deprecated, platform, unimplemented, library, experimental
|
ctnHintModifier = 98; // deprecated, platform, unimplemented, library, experimental
|
||||||
|
|
||||||
|
|||||||
@ -3739,22 +3739,19 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function SearchInGenericParams(GenericNode: TCodeTreeNode): boolean;
|
function SearchInGenericParams(GenParamsNode: TCodeTreeNode): boolean;
|
||||||
var
|
var
|
||||||
Node: TCodeTreeNode;
|
Node: TCodeTreeNode;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
Node:=GenericNode.FirstChild;
|
if (GenParamsNode=nil) or (GenParamsNode.Desc<>ctnGenericParams) then exit;
|
||||||
if Node=nil then exit;
|
Node:=GenParamsNode.FirstChild;
|
||||||
Node:=Node.NextBrother;
|
|
||||||
if (Node=nil) or (Node.Desc<>ctnGenericParams) then exit;
|
|
||||||
Node:=Node.FirstChild;
|
|
||||||
while Node<>nil do begin
|
while Node<>nil do begin
|
||||||
if (fdfCollect in Flags)
|
if (fdfCollect in Flags)
|
||||||
or CompareSrcIdentifiers(Node.StartPos,Params.Identifier)
|
or CompareSrcIdentifiers(Node.StartPos,Params.Identifier)
|
||||||
then begin
|
then begin
|
||||||
{$IFDEF ShowTriedIdentifiers}
|
{$IFDEF ShowTriedIdentifiers}
|
||||||
DebugLn(' SearchInGenericParams Identifier found="',GetIdentifier(Params.Identifier),'"');
|
DebugLn(' SearchInGenericParams Identifier found="',GetIdentifier(@Src[Node.StartPos]),'" at '+CleanPosToStr(Node.StartPos));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
// identifier found
|
// identifier found
|
||||||
Params.SetResult(Self,Node);
|
Params.SetResult(Self,Node);
|
||||||
@ -3806,6 +3803,44 @@ var
|
|||||||
end;
|
end;
|
||||||
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;
|
function SearchInTypeOfVarConst: boolean;
|
||||||
// returns: true if ok to exit
|
// returns: true if ok to exit
|
||||||
// false if search should continue
|
// false if search should continue
|
||||||
@ -4056,20 +4091,22 @@ var
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
LastSearchedNode:=ContextNode;
|
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
|
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!
|
//allow ctnRecordType and ctnTypeTypeBeforeHelper: they can have helpers!
|
||||||
if (fdfSearchInAncestors in Flags) then begin
|
if (fdfSearchInAncestors in Flags) then begin
|
||||||
// after searching in a class definition, search in its ancestors
|
// after searching in a class definition, search in its ancestors
|
||||||
@ -4354,9 +4391,13 @@ begin
|
|||||||
MoveContextNodeToChildren;
|
MoveContextNodeToChildren;
|
||||||
|
|
||||||
ctnTypeDefinition, ctnVarDefinition, ctnConstDefinition,
|
ctnTypeDefinition, ctnVarDefinition, ctnConstDefinition,
|
||||||
ctnGenericType, ctnGlobalProperty:
|
ctnGlobalProperty:
|
||||||
if SearchInTypeVarConstGlobPropDefinition then exit;
|
if SearchInTypeVarConstGlobPropDefinition then exit;
|
||||||
|
|
||||||
|
ctnGenericType:
|
||||||
|
if SearchInGenericType then exit;
|
||||||
|
// ctnGenericParams: skip here, it was searched before searching the ancestors
|
||||||
|
|
||||||
ctnIdentifier:
|
ctnIdentifier:
|
||||||
if (ContextNode.Parent.Desc in [ctnConstDefinition,ctnVarDefinition])
|
if (ContextNode.Parent.Desc in [ctnConstDefinition,ctnVarDefinition])
|
||||||
and (ContextNode=ContextNode.Parent.LastChild)
|
and (ContextNode=ContextNode.Parent.LastChild)
|
||||||
|
|||||||
@ -1215,6 +1215,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
ctnGenericParameter:
|
||||||
|
Ident:=@FoundContext.Tool.Src[FoundContext.Node.StartPos];
|
||||||
|
|
||||||
ctnVarDefinition,ctnConstDefinition,ctnEnumIdentifier,ctnLabel,ctnGlobalProperty:
|
ctnVarDefinition,ctnConstDefinition,ctnEnumIdentifier,ctnLabel,ctnGlobalProperty:
|
||||||
Ident:=@FoundContext.Tool.Src[FoundContext.Node.StartPos];
|
Ident:=@FoundContext.Tool.Src[FoundContext.Node.StartPos];
|
||||||
|
|||||||
@ -11,16 +11,16 @@ uses
|
|||||||
Classes, SysUtils;
|
Classes, SysUtils;
|
||||||
|
|
||||||
type
|
type
|
||||||
generic TGenBaseAction<T> = class
|
generic TGenBaseAction<GenParam1> = class
|
||||||
BaseName: T{declaration:fdt_generics.TGenBaseAction.T};
|
BaseName: GenParam1{declaration:fdt_generics.TGenBaseAction.GenParam1};
|
||||||
end;
|
end;
|
||||||
|
|
||||||
generic TGenCustomAction<T> = class(specialize TGenBaseAction{declaration:fdt_generics.TGenBaseAction}<T>)
|
generic TGenCustomAction<GenParam2> = class(specialize TGenBaseAction{declaration:fdt_generics.TGenBaseAction}<GenParam2>)
|
||||||
CustomName: T;
|
CustomName: GenParam2;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
generic TGenAction<T> = class(specialize TGenCustomAction{declaration:fdt_generics.TGenCustomAction}<T>)
|
generic TGenAction<GenParam3> = class(specialize TGenCustomAction{declaration:fdt_generics.TGenCustomAction}<GenParam3>)
|
||||||
ActionName: T;
|
ActionName: GenParam3;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|||||||
@ -90,7 +90,7 @@ procedure TTestFindDeclaration.FindDeclarations(Filename: string);
|
|||||||
end;
|
end;
|
||||||
Node:=Node.Parent;
|
Node:=Node.Parent;
|
||||||
end;
|
end;
|
||||||
debugln(['NodeAsPath ',Result]);
|
//debugln(['NodeAsPath ',Result]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -191,6 +191,7 @@ begin
|
|||||||
i:=CodeToolBoss.IdentifierList.GetFilteredCount-1;
|
i:=CodeToolBoss.IdentifierList.GetFilteredCount-1;
|
||||||
while i>=0 do begin
|
while i>=0 do begin
|
||||||
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[i];
|
IdentItem:=CodeToolBoss.IdentifierList.FilteredItems[i];
|
||||||
|
//debugln(['TTestFindDeclaration.FindDeclarations ',IdentItem.Identifier]);
|
||||||
l:=length(IdentItem.Identifier);
|
l:=length(IdentItem.Identifier);
|
||||||
if ((l=length(ExpectedPath)) or (ExpectedPath[length(ExpectedPath)-l]='.'))
|
if ((l=length(ExpectedPath)) or (ExpectedPath[length(ExpectedPath)-l]='.'))
|
||||||
and (CompareText(IdentItem.Identifier,RightStr(ExpectedPath,l))=0)
|
and (CompareText(IdentItem.Identifier,RightStr(ExpectedPath,l))=0)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user