Prechádzať zdrojové kódy

* Parse type constraints in generics

git-svn-id: trunk@40939 -
michael 6 rokov pred
rodič
commit
6e704b6a4f

+ 4 - 1
packages/fcl-passrc/src/pastree.pp

@@ -730,7 +730,10 @@ type
     Function IsAdvancedRecord : Boolean;
     Function IsAdvancedRecord : Boolean;
   end;
   end;
 
 
-  TPasGenericTemplateType = Class(TPasType);
+  TPasGenericTemplateType = Class(TPasType)
+  Public
+    TypeConstraint : String;
+  end;
 
 
   TPasObjKind = (
   TPasObjKind = (
     okObject, okClass, okInterface,
     okObject, okClass, okInterface,

+ 10 - 3
packages/fcl-passrc/src/pparser.pp

@@ -3992,16 +3992,23 @@ procedure TPasParser.ReadGenericArguments(List: TFPList; Parent: TPasElement);
 
 
 Var
 Var
   N : String;
   N : String;
+  T : TPasGenericTemplateType;
 
 
 begin
 begin
   ExpectToken(tkLessThan);
   ExpectToken(tkLessThan);
   repeat
   repeat
     N:=ExpectIdentifier;
     N:=ExpectIdentifier;
-    List.Add(CreateElement(TPasGenericTemplateType,N,Parent));
+    T:=TPasGenericTemplateType(CreateElement(TPasGenericTemplateType,N,Parent));
+    List.Add(T);
     NextToken;
     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,
       ParseExc(nParserExpectToken2Error,SParserExpectToken2Error,
-        [TokenInfos[tkComma], TokenInfos[tkGreaterThan]]);
+        [TokenInfos[tkComma], TokenInfos[tkColon], TokenInfos[tkGreaterThan]]);
   until CurToken = tkGreaterThan;
   until CurToken = tkGreaterThan;
 end;
 end;
 
 

+ 22 - 0
packages/fcl-passrc/tests/tcgenerics.pp

@@ -12,11 +12,13 @@ Type
   { TTestGenerics }
   { TTestGenerics }
 
 
   TTestGenerics = Class(TBaseTestTypeParser)
   TTestGenerics = Class(TBaseTestTypeParser)
+  private
   Published
   Published
     Procedure TestObjectGenerics;
     Procedure TestObjectGenerics;
     Procedure TestRecordGenerics;
     Procedure TestRecordGenerics;
     Procedure TestArrayGenerics;
     Procedure TestArrayGenerics;
     Procedure TestSpecializationDelphi;
     Procedure TestSpecializationDelphi;
+    procedure TestDeclarationConstraint;
     Procedure TestDeclarationDelphi;
     Procedure TestDeclarationDelphi;
     Procedure TestDeclarationDelphiSpecialize;
     Procedure TestDeclarationDelphiSpecialize;
     Procedure TestMethodImplementation;
     Procedure TestMethodImplementation;
@@ -84,6 +86,26 @@ begin
   AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
   AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
 end;
 end;
 
 
+procedure TTestGenerics.TestDeclarationConstraint;
+Var
+  T : TPasClassType;
+begin
+  Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
+  Source.Add('Type');
+  Source.Add('  TSomeClass<T: T2> = 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;
 procedure TTestGenerics.TestDeclarationDelphiSpecialize;
 Var
 Var
   T : TPasClassType;
   T : TPasClassType;