Codetools: Find type of generic, if specialized with build-in type (e.g. string)

This commit is contained in:
Martin 2023-03-07 22:41:24 +01:00
parent 31c8f2dadd
commit 89ab07a39f
2 changed files with 66 additions and 2 deletions

View File

@ -5328,7 +5328,10 @@ var
// only types allowed here
TestContext.Tool:=SubParams.NewCodeTool;
TestContext.Node:=SubParams.NewNode;
if not (TestContext.Node.Desc in [ctnTypeDefinition,ctnGenericType,ctnGenericParameter]) then
if (not (TestContext.Node.Desc in [ctnTypeDefinition,ctnGenericType,ctnGenericParameter,ctnSpecializeParam]))
// TODO: the parser marks ctnSpecializeParam as ctnIdentifier (at least for types like "string"
and not ((TestContext.Node.Desc=ctnIdentifier) and (TestContext.Node.Parent<>nil) and (TestContext.Node.Parent.Desc=ctnSpecializeParams))
then
begin
// not a type
{$IFDEF ShowTriedBaseContexts}
@ -5580,7 +5583,7 @@ begin
Result.Node:=Result.Node.Parent;
break;
end else
if (Result.Node.Desc in [ctnIdentifier,ctnOnIdentifier])
if (Result.Node.Desc in [ctnIdentifier,ctnOnIdentifier,ctnSpecializeParam])
then begin
// this type is just an alias for another type
// -> search the basic type
@ -14227,6 +14230,19 @@ begin
GenParams.SpecializeParamsNode:=nil;
end;
Result:=DoFindIdentifierInContext(ContextTool);
if not Result then begin
GenParamType := ContextNode.FirstChild;
for i := 2 to n do if GenParamType <> nil then GenParamType := GenParamType.NextBrother;
if GenParamType <> nil then begin
NewNode:=GenParamType;
NewCodeTool:=ContextTool;
Include(Flags, fdfDoNotCache);
Include(NewFlags, fodDoNotCache);
Result := True;
end;
end;
GenParams := OldGenParam;
end;
end;

View File

@ -0,0 +1,48 @@
program tgeneric_stringparam;
{$mode objfpc}
type
TStringHelper = type helper for string
procedure Helping;
end;
generic TGen<T> = class
function Foo: T;
procedure bar(param: T);
end;
TDataItem = class
Name, Address: String;
end;
TMyData = specialize TGen<TDataItem>;
TMyString = specialize TGen<string>;
procedure TStringHelper.Helping;
begin
end;
function TGen.Foo: T;
begin
end;
procedure TGen.bar(param: T);
begin
end;
var
MyData: TMyData;
MyString: TMyString;
begin
MyData.Foo.{completion:Name,Address,!Helping} ;
MyString.Foo.{completion:Helping,!Name,!Address} ;
d1 := MyData.Foo;
s1 := MyString.Foo;
MyData.bar(x);
MyString.bar(y);
end.