From 6e704b6a4f6b58950ec34d290980a5f23fc7a02e Mon Sep 17 00:00:00 2001 From: michael Date: Sun, 20 Jan 2019 16:45:31 +0000 Subject: [PATCH] * Parse type constraints in generics git-svn-id: trunk@40939 - --- packages/fcl-passrc/src/pastree.pp | 5 ++++- packages/fcl-passrc/src/pparser.pp | 13 ++++++++++--- packages/fcl-passrc/tests/tcgenerics.pp | 22 ++++++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/packages/fcl-passrc/src/pastree.pp b/packages/fcl-passrc/src/pastree.pp index 5918d817d6..73a13d8ca7 100644 --- a/packages/fcl-passrc/src/pastree.pp +++ b/packages/fcl-passrc/src/pastree.pp @@ -730,7 +730,10 @@ type Function IsAdvancedRecord : Boolean; end; - TPasGenericTemplateType = Class(TPasType); + TPasGenericTemplateType = Class(TPasType) + Public + TypeConstraint : String; + end; TPasObjKind = ( okObject, okClass, okInterface, diff --git a/packages/fcl-passrc/src/pparser.pp b/packages/fcl-passrc/src/pparser.pp index f459afa876..0687f7ec2c 100644 --- a/packages/fcl-passrc/src/pparser.pp +++ b/packages/fcl-passrc/src/pparser.pp @@ -3992,16 +3992,23 @@ procedure TPasParser.ReadGenericArguments(List: TFPList; Parent: TPasElement); Var N : String; + T : TPasGenericTemplateType; begin ExpectToken(tkLessThan); repeat N:=ExpectIdentifier; - List.Add(CreateElement(TPasGenericTemplateType,N,Parent)); + T:=TPasGenericTemplateType(CreateElement(TPasGenericTemplateType,N,Parent)); + List.Add(T); NextToken; - if not (CurToken in [tkComma, tkGreaterThan]) then + if Curtoken = tkColon then + begin + T.TypeConstraint:=ExpectIdentifier; + NextToken; + end; + if not (CurToken in [tkComma,tkGreaterThan]) then ParseExc(nParserExpectToken2Error,SParserExpectToken2Error, - [TokenInfos[tkComma], TokenInfos[tkGreaterThan]]); + [TokenInfos[tkComma], TokenInfos[tkColon], TokenInfos[tkGreaterThan]]); until CurToken = tkGreaterThan; end; diff --git a/packages/fcl-passrc/tests/tcgenerics.pp b/packages/fcl-passrc/tests/tcgenerics.pp index cab2db6344..3ee583b364 100644 --- a/packages/fcl-passrc/tests/tcgenerics.pp +++ b/packages/fcl-passrc/tests/tcgenerics.pp @@ -12,11 +12,13 @@ Type { TTestGenerics } TTestGenerics = Class(TBaseTestTypeParser) + private Published Procedure TestObjectGenerics; Procedure TestRecordGenerics; Procedure TestArrayGenerics; Procedure TestSpecializationDelphi; + procedure TestDeclarationConstraint; Procedure TestDeclarationDelphi; Procedure TestDeclarationDelphiSpecialize; Procedure TestMethodImplementation; @@ -84,6 +86,26 @@ begin AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent); end; +procedure TTestGenerics.TestDeclarationConstraint; +Var + T : TPasClassType; +begin + Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ; + Source.Add('Type'); + Source.Add(' TSomeClass = Class(TObject)'); + Source.Add(' b : T;'); + Source.Add('end;'); + ParseDeclarations; + AssertNotNull('have generic definition',Declarations.Classes); + AssertEquals('have generic definition',1,Declarations.Classes.Count); + AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType); + T:=TPasClassType(Declarations.Classes[0]); + AssertNotNull('have generic templates',T.GenericTemplateTypes); + AssertEquals('1 template types',1,T.GenericTemplateTypes.Count); + AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent); + AssertEquals('Type constraint is recorded','T2',TPasGenericTemplateType(T.GenericTemplateTypes[0]).TypeConstraint); +end; + procedure TTestGenerics.TestDeclarationDelphiSpecialize; Var T : TPasClassType;