tcgenerics.pp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. unit tcgenerics;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, fpcunit, pastree, testregistry, pscanner, tctypeparser;
  6. Type
  7. { TTestGenerics }
  8. TTestGenerics = Class(TBaseTestTypeParser)
  9. private
  10. Published
  11. Procedure TestObjectGenerics;
  12. Procedure TestRecordGenerics;
  13. Procedure TestArrayGenerics;
  14. Procedure TestSpecializationDelphi;
  15. procedure TestDeclarationConstraint;
  16. Procedure TestDeclarationDelphi;
  17. Procedure TestDeclarationDelphiSpecialize;
  18. Procedure TestMethodImplementation;
  19. Procedure TestInlineSpecializationInArgument;
  20. Procedure TestSpecializeNested;
  21. Procedure TestInlineSpecializeInStatement;
  22. end;
  23. implementation
  24. procedure TTestGenerics.TestObjectGenerics;
  25. begin
  26. Add([
  27. 'Type',
  28. 'Generic TSomeClass<T> = Object',
  29. ' b : T;',
  30. 'end;',
  31. '']);
  32. ParseDeclarations;
  33. end;
  34. procedure TTestGenerics.TestRecordGenerics;
  35. begin
  36. Add([
  37. 'Type',
  38. ' Generic TSome<T> = Record',
  39. ' b : T;',
  40. ' end;',
  41. '']);
  42. ParseDeclarations;
  43. end;
  44. procedure TTestGenerics.TestArrayGenerics;
  45. begin
  46. Add([
  47. 'Type',
  48. ' Generic TSome<T> = array of T;',
  49. '']);
  50. ParseDeclarations;
  51. end;
  52. procedure TTestGenerics.TestSpecializationDelphi;
  53. begin
  54. ParseType('TFPGList<integer>',TPasSpecializeType,'');
  55. end;
  56. procedure TTestGenerics.TestDeclarationDelphi;
  57. Var
  58. T : TPasClassType;
  59. begin
  60. Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
  61. Source.Add('Type');
  62. Source.Add(' TSomeClass<T,T2> = Class(TObject)');
  63. Source.Add(' b : T;');
  64. Source.Add(' b2 : T2;');
  65. Source.Add('end;');
  66. ParseDeclarations;
  67. AssertNotNull('have generic definition',Declarations.Classes);
  68. AssertEquals('have generic definition',1,Declarations.Classes.Count);
  69. AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
  70. T:=TPasClassType(Declarations.Classes[0]);
  71. AssertNotNull('have generic templates',T.GenericTemplateTypes);
  72. AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
  73. AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
  74. AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
  75. end;
  76. procedure TTestGenerics.TestDeclarationConstraint;
  77. Var
  78. T : TPasClassType;
  79. begin
  80. Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
  81. Source.Add('Type');
  82. Source.Add(' TSomeClass<T: T2> = Class(TObject)');
  83. Source.Add(' b : T;');
  84. Source.Add('end;');
  85. ParseDeclarations;
  86. AssertNotNull('have generic definition',Declarations.Classes);
  87. AssertEquals('have generic definition',1,Declarations.Classes.Count);
  88. AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
  89. T:=TPasClassType(Declarations.Classes[0]);
  90. AssertNotNull('have generic templates',T.GenericTemplateTypes);
  91. AssertEquals('1 template types',1,T.GenericTemplateTypes.Count);
  92. AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
  93. AssertEquals('Type constraint is recorded','T2',TPasGenericTemplateType(T.GenericTemplateTypes[0]).TypeConstraint);
  94. end;
  95. procedure TTestGenerics.TestDeclarationDelphiSpecialize;
  96. Var
  97. T : TPasClassType;
  98. begin
  99. Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
  100. Source.Add('Type');
  101. Source.Add(' TSomeClass<T,T2> = Class(TSomeGeneric<Integer,Integer>)');
  102. Source.Add(' b : T;');
  103. Source.Add(' b2 : T2;');
  104. Source.Add('end;');
  105. ParseDeclarations;
  106. AssertNotNull('have generic definition',Declarations.Classes);
  107. AssertEquals('have generic definition',1,Declarations.Classes.Count);
  108. AssertEquals('Pascal class',TPasClassType,TObject(Declarations.Classes[0]).ClassType);
  109. T:=TPasClassType(Declarations.Classes[0]);
  110. AssertEquals('Name is correct','TSomeClass',T.Name);
  111. AssertNotNull('have generic templates',T.GenericTemplateTypes);
  112. AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
  113. AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
  114. AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
  115. end;
  116. procedure TTestGenerics.TestMethodImplementation;
  117. begin
  118. With source do
  119. begin
  120. Add('unit afile;');
  121. Add('{$MODE DELPHI}');
  122. Add('interface');
  123. Add('type');
  124. Add(' TTest<T> = object');
  125. Add(' procedure foo(v:T);');
  126. Add(' end;');
  127. Add('implementation');
  128. Add('procedure TTest<T>.foo;');
  129. Add('begin');
  130. Add('end;');
  131. end;
  132. ParseModule;
  133. end;
  134. procedure TTestGenerics.TestInlineSpecializationInArgument;
  135. begin
  136. With source do
  137. begin
  138. Add('unit afile;');
  139. Add('{$MODE DELPHI}');
  140. Add('interface');
  141. Add('type');
  142. Add(' TFoo=class');
  143. Add(' procedure foo(var Node:TSomeGeneric<TBoundingBox>;const index:Integer);');
  144. Add(' end;');
  145. Add('implementation');
  146. end;
  147. ParseModule;
  148. end;
  149. procedure TTestGenerics.TestSpecializeNested;
  150. begin
  151. Add([
  152. 'Type',
  153. ' generic TSomeClass<A,B> = class(specialize TOther<A,specialize TAnother<B>>) end;',
  154. '']);
  155. ParseDeclarations;
  156. end;
  157. procedure TTestGenerics.TestInlineSpecializeInStatement;
  158. begin
  159. Add([
  160. 'begin',
  161. ' vec:=TVector<double>.create;',
  162. ' b:=a<b;',
  163. ' t:=a<b.c<d,e.f>>;',
  164. '']);
  165. ParseModule;
  166. end;
  167. initialization
  168. RegisterTest(TTestGenerics);
  169. end.