View Issue Details

IDProjectCategoryView StatusLast Update
0037761pas2jsrtlpublic2020-09-25 15:32
Reporterhenrique Assigned ToMichael Van Canneyt  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
PlatformPas2JsOSWindows 
Target VersiontrunkFixed in Versiontrunk 
Summary0037761: Implemented TRttiDynArray and other things
DescriptionImplemented the TRttiDynArray class to check array types via RTTI.

In this patch you also have a new version of property value padding.

I also changed the way RTTI classes are created, because not all of them were being mapped.

All this for my serializer to work.
TagsNo tags attached.
Fixed in Revision886.
Attached Files

Activities

henrique

2020-09-16 21:12

reporter  

Rtti.patch (3,982 bytes)   
diff -r packages/rtl/rtti.pas (f0ef6487) packages/rtl/rtti.pas (Working Tree)
179a180
> 
181c182,185
<     procedure SetValue(Instance: TObject; const AValue: TValue);
---
> 
>     procedure SetValue(Instance: TObject; const AValue: JSValue); overload;
>     procedure SetValue(Instance: TObject; const AValue: TValue); overload;
> 
236a241,242
>   TRttiTypeClass = class of TRttiType;
> 
315a322,335
>   { TRttiDynamicArrayType }
> 
>   TRttiDynamicArrayType = class(TRttiType)
>   private
>     function GetDynArrayTypeInfo: TTypeInfoDynArray;
>     function GetElementType: TRttiType;
>   public
>     constructor Create(ATypeInfo: PTypeInfo);
> 
>     property DynArrayTypeInfo: TTypeInfoDynArray read GetDynArrayTypeInfo;
>     property ElementType: TRttiType read GetElementType;
>   end;
> 
> 
364a385,404
> { TRttiDynamicArrayType }
> 
> function TRttiDynamicArrayType.GetDynArrayTypeInfo: TTypeInfoDynArray;
> begin
>   Result := TTypeInfoDynArray(FTypeInfo);
> end;
> 
> function TRttiDynamicArrayType.GetElementType: TRttiType;
> begin
>   Result := GRttiContext.GetType(DynArrayTypeInfo.ElType);
> end;
> 
> constructor TRttiDynamicArrayType.Create(ATypeInfo: PTypeInfo);
> begin
>   if not (TTypeInfo(ATypeInfo) is TTypeInfoDynArray) then
>     raise EInvalidCast.Create('');
> 
>   inherited Create(ATypeInfo);
> end;
> 
748c788
<   A: Integer;
---
>   Prop: TRttiProperty;
753,755c793,795
<   for A := 0 to Pred(StructTypeInfo.PropCount) do
<     if StructTypeInfo.GetProp(A).Name = AName then
<       Exit(TRttiProperty.Create(Self, StructTypeInfo.GetProp(A)));
---
>   for Prop in GetDeclaredProperties do
>     if Prop.Name = AName then
>       Exit(Prop);
760c800
<   A: Integer;
---
>   A, PropertyCount: Integer;
761a802,803
>   BaseClass: TRttiStructuredType;
> 
763c805,815
<   SetLength(Result, StructTypeInfo.PropCount);
---
>   BaseClass := Self;
>   PropertyCount := 0;
> 
>   while Assigned(BaseClass) do
>   begin
>     Inc(PropertyCount, BaseClass.StructTypeInfo.PropCount);
> 
>     BaseClass := BaseClass.GetAncestor;
>   end;
> 
>   SetLength(Result, PropertyCount);
765,766c817,830
<   for A := 0 to Pred(StructTypeInfo.PropCount) do
<     Result[A] := TRttiProperty.Create(Self, StructTypeInfo.GetProp(A));
---
>   BaseClass := Self;
>   PropertyCount := 0;
> 
>   while Assigned(BaseClass) do
>   begin
>     for A := 0 to Pred(BaseClass.StructTypeInfo.PropCount) do
>     begin
>       Result[PropertyCount] := TRttiProperty.Create(BaseClass, BaseClass.StructTypeInfo.GetProp(A));
> 
>       Inc(PropertyCount);
>     end;
> 
>     BaseClass := BaseClass.GetAncestor;
>   end;
866a931,953
>   RttiTypeClass: array[TTypeKind] of TRttiTypeClass = (
>     nil, // tkUnknown
>     TRttiOrdinalType, // tkInteger
>     TRttiOrdinalType, // tkChar
>     TRttiType, // tkString
>     TRttiEnumerationType, // tkEnumeration
>     TRttiType, // tkSet
>     TRttiOrdinalType, // tkDouble
>     TRttiEnumerationType, // tkBool
>     TRttiType, // tkProcVar
>     nil, // tkMethod
>     TRttiType, // tkArray
>     TRttiDynamicArrayType, // tkDynArray
>     TRttiType, // tkRecord
>     TRttiInstanceType, // tkClass
>     TRttiType, // tkClassRef
>     TRttiType, // tkPointer
>     TRttiType, // tkJSValue
>     TRttiType, // tkRefToProcVar
>     TRttiInterfaceType, // tkInterface
>     TRttiType, // tkHelper
>     TRttiInstanceType // tkExtClass
>   );
878,882c965
<       case T.Kind of
<         tkClass: Result:=TRttiInstanceType.Create(aTypeInfo);
<         tkInterface: Result:=TRttiInterfaceType.Create(aTypeInfo);
<         else Result:=TRttiType.Create(aTypeInfo);
<       end;
---
>     Result := RttiTypeClass[T.Kind].Create(aTypeInfo);
1020a1104,1108
> procedure TRttiProperty.SetValue(Instance: TObject; const AValue: JSValue);
> begin
>   SetJSValueProp(Instance, PropertyTypeInfo, AValue);
> end;
> 
Rtti.patch (3,982 bytes)   

Michael Van Canneyt

2020-09-25 13:43

administrator   ~0125846

Applied almost as-is:

The GetProperty change in implementation is not OK:

753,755c793,795
< for A := 0 to Pred(StructTypeInfo.PropCount) do
< if StructTypeInfo.GetProp(A).Name = AName then
< Exit(TRttiProperty.Create(Self, StructTypeInfo.GetProp(A)));
---
> for Prop in GetDeclaredProperties do
> if Prop.Name = AName then
> Exit(Prop);

This will create an TRTTIProperty instance for all the properties even if you don't need them.
I understand this is easier but I think the correct solution is to do what is done in GetDeclaredProperties, i.e. go to the parent class if it is not in the current class..
I reworked that part of your patch.

Please test and close if OK, thank you !

Sven Barth

2020-09-25 15:18

developer   ~0125854

Last edited: 2020-09-25 15:19

View 2 revisions

Because I just noticed this: did you say that GetDeclaredProperties also checks the parent types? That would be wrong then. GetProperties returns all properties of a type including its parents, GetDeclaredProperties only those of the current type without any parents (same for fields and methods). See: http://docwiki.embarcadero.com/Libraries/Sydney/en/System.Rtti.TRttiType.GetDeclaredProperties (or FPC's implementation of TRttiType.GetMethods which makes use of TRttiType.GetDeclaredMethods, TRttiType.GetDeclaredProperties is not yet supported)

henrique

2020-09-25 15:26

reporter   ~0125856

I forgot to check the Embarcadero documentation, but what I implemented was GetProperties, you have to rename the function

henrique

2020-09-25 15:26

reporter   ~0125857

I'm checking another issue now, as soon as I'm done, I can adjust the implementation and send the patch again

Michael Van Canneyt

2020-09-25 15:32

administrator   ~0125858

Yes, please !

Issue History

Date Modified Username Field Change
2020-09-16 21:12 henrique New Issue
2020-09-16 21:12 henrique File Added: Rtti.patch
2020-09-16 23:54 Michael Van Canneyt Assigned To => Michael Van Canneyt
2020-09-16 23:54 Michael Van Canneyt Status new => assigned
2020-09-25 13:43 Michael Van Canneyt Status assigned => resolved
2020-09-25 13:43 Michael Van Canneyt Resolution open => fixed
2020-09-25 13:43 Michael Van Canneyt Note Added: 0125846
2020-09-25 13:43 Michael Van Canneyt Fixed in Version => trunk
2020-09-25 13:43 Michael Van Canneyt Target Version => trunk
2020-09-25 13:43 Michael Van Canneyt Description Updated View Revisions
2020-09-25 13:43 Michael Van Canneyt Fixed in Revision => 886.
2020-09-25 15:18 Sven Barth Note Added: 0125854
2020-09-25 15:19 Sven Barth Note Edited: 0125854 View Revisions
2020-09-25 15:26 henrique Note Added: 0125856
2020-09-25 15:26 henrique Note Added: 0125857
2020-09-25 15:32 Michael Van Canneyt Note Added: 0125858