Browse Source

* Patch from henrique Werlang to check parent classes when getting methods (bug ID 377736)

michael 4 years ago
parent
commit
48a57fc9f1
1 changed files with 60 additions and 22 deletions
  1. 60 22
      packages/rtl/rtti.pas

+ 60 - 22
packages/rtl/rtti.pas

@@ -236,6 +236,7 @@ type
 
 
   TRttiStructuredType = class abstract(TRttiType)
   TRttiStructuredType = class abstract(TRttiType)
   protected
   protected
+    function GetAncestor: TRttiStructuredType; virtual; abstract;
     function GetDeclaredProperties: TRttiPropertyArray; override;
     function GetDeclaredProperties: TRttiPropertyArray; override;
     function GetMethod(const aName: String): TRttiMethod; override;
     function GetMethod(const aName: String): TRttiMethod; override;
     function GetMethods: TRttiMethodArray; override;
     function GetMethods: TRttiMethodArray; override;
@@ -254,6 +255,8 @@ type
   private
   private
     function GetClassTypeInfo: TTypeInfoClass;
     function GetClassTypeInfo: TTypeInfoClass;
     function GetMetaClassType: TClass;
     function GetMetaClassType: TClass;
+  protected
+    function GetAncestor: TRttiStructuredType; override;
   public
   public
     constructor Create(ATypeInfo: PTypeInfo);
     constructor Create(ATypeInfo: PTypeInfo);
     function GetIsInstance: boolean; override;
     function GetIsInstance: boolean; override;
@@ -261,10 +264,14 @@ type
     property MetaClassType: TClass read GetMetaClassType;
     property MetaClassType: TClass read GetMetaClassType;
   end;
   end;
 
 
+  { TRttiInterfaceType }
+
   TRttiInterfaceType = class(TRttiStructuredType)
   TRttiInterfaceType = class(TRttiStructuredType)
   private
   private
     function GetGUID: TGUID;
     function GetGUID: TGUID;
     function GetInterfaceTypeInfo: TTypeInfoInterface;
     function GetInterfaceTypeInfo: TTypeInfoInterface;
+  protected
+    function GetAncestor: TRttiStructuredType; override;
   public
   public
     constructor Create(ATypeInfo: PTypeInfo);
     constructor Create(ATypeInfo: PTypeInfo);
 
 
@@ -667,49 +674,70 @@ end;
 
 
 function TRttiStructuredType.GetMethods: TRttiMethodArray;
 function TRttiStructuredType.GetMethods: TRttiMethodArray;
 var
 var
-  A: Integer;
+  A, MethodCount: Integer;
+
+  BaseClass: TRttiStructuredType;
 
 
 begin
 begin
+  BaseClass := Self;
+  MethodCount := 0;
+
+  while Assigned(BaseClass) do
+  begin
+    Inc(MethodCount, BaseClass.StructTypeInfo.MethodCount);
+
+    BaseClass := BaseClass.GetAncestor;
+  end;
+
   SetLength(Result, StructTypeInfo.MethodCount);
   SetLength(Result, StructTypeInfo.MethodCount);
 
 
-  for A := 0 to Pred(StructTypeInfo.MethodCount) do
-    Result[A] := TRttiMethod.Create(Self, StructTypeInfo.GetMethod(A));
+  BaseClass := Self;
+
+  while Assigned(BaseClass) do
+  begin
+    for A := 0 to Pred(BaseClass.StructTypeInfo.MethodCount) do
+    begin
+      Dec(MethodCount);
+
+      Result[MethodCount] := TRttiMethod.Create(BaseClass, BaseClass.StructTypeInfo.GetMethod(A));
+    end;
+
+    BaseClass := BaseClass.GetAncestor;
+  end;
 end;
 end;
 
 
 function TRttiStructuredType.GetMethods(const aName: String): TRttiMethodArray;
 function TRttiStructuredType.GetMethods(const aName: String): TRttiMethodArray;
 var
 var
-  A: Integer;
+  Method: TRttiMethod;
 
 
-  Method: TTypeMemberMethod;
+  MethodCount: Integer;
 
 
 begin
 begin
-  SetLength(Result, StructTypeInfo.MethodCount);
+  MethodCount := 0;
 
 
-  for A := 0 to Pred(StructTypeInfo.MethodCount) do
-  begin
-    Method := StructTypeInfo.GetMethod(A);
+  for Method in GetMethods do
+    if aName = Method.Name then
+      Inc(MethodCount);
+
+  SetLength(Result, MethodCount);
 
 
+  for Method in GetMethods do
     if aName = Method.Name then
     if aName = Method.Name then
-      Result[A] := TRttiMethod.Create(Self, Method);
-  end;
+    begin
+      Dec(MethodCount);
+
+      Result[MethodCount] := Method;
+    end;
 end;
 end;
 
 
 function TRttiStructuredType.GetMethod(const aName: String): TRttiMethod;
 function TRttiStructuredType.GetMethod(const aName: String): TRttiMethod;
 var
 var
-  A: Integer;
-
-  Method: TTypeMemberMethod;
+  Method: TRttiMethod;
 
 
 begin
 begin
-  Result := nil;
-
-  for A := 0 to Pred(StructTypeInfo.MethodCount) do
-  begin
-    Method := StructTypeInfo.GetMethod(A);
-
+  for Method in GetMethods do
     if aName = Method.Name then
     if aName = Method.Name then
-      Exit(TRttiMethod.Create(Self, Method));
-  end;
+      Exit(Method);
 end;
 end;
 
 
 function TRttiStructuredType.GetProperty(const AName: string): TRttiProperty;
 function TRttiStructuredType.GetProperty(const AName: string): TRttiProperty;
@@ -760,6 +788,11 @@ begin
   Result:=ClassTypeInfo.ClassType;
   Result:=ClassTypeInfo.ClassType;
 end;
 end;
 
 
+function TRttiInstanceType.GetAncestor: TRttiStructuredType;
+begin
+  Result := GRttiContext.GetType(ClassTypeInfo.Ancestor) as TRttiStructuredType;
+end;
+
 constructor TRttiInstanceType.Create(ATypeInfo: PTypeInfo);
 constructor TRttiInstanceType.Create(ATypeInfo: PTypeInfo);
 begin
 begin
   if not (TTypeInfo(ATypeInfo) is TTypeInfoClass) then
   if not (TTypeInfo(ATypeInfo) is TTypeInfoClass) then
@@ -796,6 +829,11 @@ begin
   Result := TTypeInfoInterface(FTypeInfo);
   Result := TTypeInfoInterface(FTypeInfo);
 end;
 end;
 
 
+function TRttiInterfaceType.GetAncestor: TRttiStructuredType;
+begin
+  Result := GRttiContext.GetType(InterfaceTypeInfo.Ancestor) as TRttiStructuredType;
+end;
+
 { TRTTIContext }
 { TRTTIContext }
 
 
 class constructor TRTTIContext.Init;
 class constructor TRTTIContext.Init;