123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- unit tcgenerics;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, fpcunit, pastree, testregistry, pscanner, tctypeparser;
- Type
- { TTestGenerics }
- TTestGenerics = Class(TBaseTestTypeParser)
- Published
- Procedure TestObjectGenerics;
- Procedure TestRecordGenerics;
- Procedure TestArrayGenerics;
- Procedure TestGenericConstraint;
- Procedure TestGenericInterfaceConstraint; // ToDo
- Procedure TestDeclarationConstraint;
- Procedure TestSpecializationDelphi;
- Procedure TestDeclarationDelphi;
- Procedure TestDeclarationDelphiSpecialize;
- Procedure TestDeclarationFPC;
- Procedure TestMethodImplementation;
- Procedure TestInlineSpecializationInArgument;
- Procedure TestSpecializeNested;
- Procedure TestInlineSpecializeInStatement;
- Procedure TestInlineSpecializeInStatementDelphi;
- Procedure TestGenericFunction;
- end;
- implementation
- procedure TTestGenerics.TestObjectGenerics;
- begin
- Add([
- 'Type',
- 'Generic TSomeClass<T> = Object',
- ' b : T;',
- 'end;',
- '']);
- ParseDeclarations;
- end;
- procedure TTestGenerics.TestRecordGenerics;
- begin
- Add([
- 'Type',
- ' Generic TSome<T> = Record',
- ' b : T;',
- ' end;',
- '']);
- ParseDeclarations;
- end;
- procedure TTestGenerics.TestArrayGenerics;
- begin
- Add([
- 'Type',
- ' Generic TSome<T> = array of T;',
- '']);
- ParseDeclarations;
- end;
- procedure TTestGenerics.TestGenericConstraint;
- begin
- Add([
- 'Type',
- 'Generic TSomeClass<T: TObject> = class',
- ' b : T;',
- 'end;',
- 'Generic TBird<T: class> = class',
- ' c : TBird<T>;',
- 'end;',
- 'Generic TEagle<T: record> = class',
- 'end;',
- 'Generic TEagle<T: constructor> = class',
- 'end;',
- '']);
- ParseDeclarations;
- end;
- procedure TTestGenerics.TestGenericInterfaceConstraint;
- begin
- Add([
- 'Type',
- 'TIntfA = interface end;',
- 'TIntfB = interface end;',
- 'TBird = class(TInterfacedObject,TIntfA,TIntfB) end;',
- 'Generic TAnt<T: TIntfA, TIntfB> = class',
- ' b: T;',
- ' c: TAnt<T>;',
- 'end;',
- 'Generic TFly<T: TIntfA, TIntfB; S> = class',
- ' b: S;',
- ' c: TFly<T>;',
- 'end;',
- '']);
- ParseDeclarations;
- 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.TestSpecializationDelphi;
- begin
- ParseType('TFPGList<integer>',TPasSpecializeType,'');
- end;
- procedure TTestGenerics.TestDeclarationDelphi;
- 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(' b2 : T2;');
- 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('2 template types',2,T.GenericTemplateTypes.Count);
- AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
- AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
- end;
- procedure TTestGenerics.TestDeclarationDelphiSpecialize;
- Var
- T : TPasClassType;
- begin
- Scanner.CurrentModeSwitches:=[msDelphi]+Scanner.CurrentModeSwitches ;
- Source.Add('Type');
- Source.Add(' TSomeClass<T,T2> = Class(TSomeGeneric<Integer,Integer>)');
- Source.Add(' b : T;');
- Source.Add(' b2 : T2;');
- 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]);
- AssertEquals('Name is correct','TSomeClass',T.Name);
- AssertNotNull('have generic templates',T.GenericTemplateTypes);
- AssertEquals('2 template types',2,T.GenericTemplateTypes.Count);
- AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
- AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
- end;
- procedure TTestGenerics.TestDeclarationFPC;
- 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(' b2 : T2;');
- 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('2 template types',2,T.GenericTemplateTypes.Count);
- AssertSame('Parent 0 is class',T,TPasElement(T.GenericTemplateTypes[0]).Parent);
- AssertSame('Parent 1 is class',T,TPasElement(T.GenericTemplateTypes[1]).Parent);
- end;
- procedure TTestGenerics.TestMethodImplementation;
- begin
- With source do
- begin
- Add('unit afile;');
- Add('{$MODE DELPHI}');
- Add('interface');
- Add('type');
- Add(' TTest<T> = object');
- Add(' procedure foo(v:T);');
- Add(' end;');
- Add('implementation');
- Add('procedure TTest<T>.foo;');
- Add('begin');
- Add('end;');
- end;
- ParseModule;
- end;
- procedure TTestGenerics.TestInlineSpecializationInArgument;
- begin
- With source do
- begin
- Add('unit afile;');
- Add('{$MODE DELPHI}');
- Add('interface');
- Add('type');
- Add(' TFoo=class');
- Add(' procedure foo(var Node:TSomeGeneric<TBoundingBox>;const index:Integer);');
- Add(' end;');
- Add('implementation');
- end;
- ParseModule;
- end;
- procedure TTestGenerics.TestSpecializeNested;
- begin
- Add([
- 'Type',
- ' generic TSomeClass<A,B> = class(specialize TOther<A,specialize TAnother<B>>) end;',
- '']);
- ParseDeclarations;
- end;
- procedure TTestGenerics.TestInlineSpecializeInStatement;
- begin
- Add([
- 'begin',
- ' t:=specialize a<b>;',
- ' t:=a.specialize b<c>;',
- '']);
- ParseModule;
- end;
- procedure TTestGenerics.TestInlineSpecializeInStatementDelphi;
- begin
- Add([
- 'begin',
- ' vec:=TVector<double>.create;',
- ' b:=a<b;',
- ' t:=a<b.c<d,e.f>>;',
- ' t:=a.b<c>;',
- ' t:=a<b>.c;',
- // forbidden:' t:=a<b<c>.d>;',
- '']);
- ParseModule;
- end;
- procedure TTestGenerics.TestGenericFunction;
- begin
- Add([
- 'generic function IfThen<T>(val:boolean;const iftrue:T; const iffalse:T) :T; inline; overload;',
- 'begin',
- 'end;',
- 'begin',
- ' specialize IfThen<word>(true,2,3);',
- '']);
- ParseModule;
- end;
- initialization
- RegisterTest(TTestGenerics);
- end.
|