Преглед на файлове

* fix for Mantis #36196: free a property's attributes when the property is destroyed
+ added test

git-svn-id: trunk@43299 -

svenbarth преди 5 години
родител
ревизия
9dcd897ce6
променени са 3 файла, в които са добавени 170 реда и са изтрити 0 реда
  1. 1 0
      .gitattributes
  2. 10 0
      packages/rtl-objpas/src/inc/rtti.pp
  3. 159 0
      tests/webtbs/tw36196.pp

+ 1 - 0
.gitattributes

@@ -17846,6 +17846,7 @@ tests/webtbs/tw36156.pp svneol=native#text/plain
 tests/webtbs/tw36157.pp svneol=native#text/plain
 tests/webtbs/tw3617.pp svneol=native#text/plain
 tests/webtbs/tw3619.pp svneol=native#text/plain
+tests/webtbs/tw36196.pp svneol=native#text/pascal
 tests/webtbs/tw3621.pp svneol=native#text/plain
 tests/webtbs/tw3628.pp svneol=native#text/plain
 tests/webtbs/tw3634.pp svneol=native#text/plain

+ 10 - 0
packages/rtl-objpas/src/inc/rtti.pp

@@ -331,6 +331,7 @@ type
     function GetHandle: Pointer; override;
   public
     constructor Create(AParent: TRttiType; APropInfo: PPropInfo);
+    destructor Destroy; override;
     function GetAttributes: specialize TArray<TCustomAttribute>; override;
     function GetValue(Instance: pointer): TValue;
     procedure SetValue(Instance: pointer; const AValue: TValue);
@@ -3749,6 +3750,15 @@ begin
   FPropInfo := APropInfo;
 end;
 
+destructor TRttiProperty.Destroy;
+var
+  attr: TCustomAttribute;
+begin
+  for attr in FAttributes do
+    attr.Free;
+  inherited Destroy;
+end;
+
 function TRttiProperty.GetAttributes: specialize TArray<TCustomAttribute>;
 var
   i: SizeInt;

+ 159 - 0
tests/webtbs/tw36196.pp

@@ -0,0 +1,159 @@
+{ %OPT=-gh }
+
+program tw36196;
+
+{$mode objfpc}{$H+}
+{$modeswitch prefixedattributes}
+
+uses
+  {heaptrc, }SysUtils, typinfo, {%H-}rtti;
+
+type
+
+  IntRangeAttribute = class(TCustomAttribute)
+  private
+    FMinValue,
+    FMaxValue: Integer;
+  public
+    constructor Create(aMin, aMax: Integer);
+    property MinValue: Integer read FMinValue;
+    property MaxValue: Integer read FMaxValue;
+  end;
+
+  DefaultStrAttribute = class(TCustomAttribute)
+  private
+    FValue: string;
+  public
+    constructor Create;
+    constructor Create(const aValue: string);
+    property Value: string read FValue;
+  end;
+
+  CheckAttribute = class(TCustomAttribute)
+  private
+    FChecked: Boolean;
+  public
+    constructor Create;
+    constructor Create(aValue: Boolean);
+    property Checked: Boolean read FChecked;
+  end;
+
+  [Check(True)]
+  TMyClass = class
+  private
+    FName,
+    FDescr: string;
+    FId: Integer;
+  published
+    [DefaultStr]
+    property Name: string read FName write FName;
+    [DefaultStr('nice description')]
+    property Description: string read FDescr write FDescr;
+    [IntRange(100, 10000)]
+    property Id: Integer read FId write FId;
+  end;
+
+  [DefaultStr('this is TMyRec')][IntRange(0, 100)]
+  TMyRec = record
+    Name: string;
+    Value: Integer;
+  end;
+
+  [Check][IntRange(-10000, 10000)]
+  TMyInt = type Integer;
+
+{ CheckAttribute }
+
+constructor CheckAttribute.Create;
+begin
+  FChecked := False;
+end;
+
+constructor CheckAttribute.Create(aValue: Boolean);
+begin
+  FChecked := aValue;
+end;
+
+{ DefaultStrAttribute }
+
+constructor DefaultStrAttribute.Create;
+begin
+  FValue := 'Unassigned';
+end;
+
+constructor DefaultStrAttribute.Create(const aValue: string);
+begin
+  FValue := aValue;
+end;
+
+{ TIntRangeAttribute }
+
+constructor IntRangeAttribute.Create(aMin, aMax: Integer);
+begin
+  FMinValue := aMin;
+  FMaxValue := aMax;
+end;
+
+procedure PrintAttribute(Attr: TCustomAttribute);
+begin
+  if not Assigned(Attr) then
+    exit;
+  WriteLn('  Found attribute ', Attr.ClassName, ':');
+  if Attr is DefaultStrAttribute then
+    WriteLn('    property Value has value "', DefaultStrAttribute(Attr).Value, '"')
+  else
+    if Attr is IntRangeAttribute then
+      begin
+        WriteLn('    property MinValue has value ', IntRangeAttribute(Attr).MinValue);
+        WriteLn('    property MaxValue has value ', IntRangeAttribute(Attr).MaxValue);
+      end
+    else
+      if Attr is CheckAttribute then
+        WriteLn('    property Checked has value ', CheckAttribute(Attr).Checked);
+end;
+
+procedure PrintClassAttributes(aClass: TClass);
+var
+ RCtx: TRttiContext;
+ RType: TRttiType;
+ Prop: TRttiProperty;
+ Attr: TCustomAttribute;
+begin
+  RCtx := TRttiContext.Create;
+  try
+    RType := RCtx.GetType(aClass);
+    WriteLn(RType.Name, ' attributes:');
+    for Attr in RType.GetAttributes do
+      PrintAttribute(Attr);
+    for Prop in RType.GetProperties do
+      for Attr in Prop.GetAttributes do
+        PrintAttribute(Attr);
+  finally
+    RCtx.Free;
+  end;
+end;
+
+procedure PrintTypeAttributes(aInfo: PTypeInfo);
+var
+ RCtx: TRttiContext;
+ RType: TRttiType;
+ Attr: TCustomAttribute;
+begin
+  RCtx := TRttiContext.Create;
+  try
+    RType := RCtx.GetType(aInfo);
+    WriteLn(RType.Name, ' attributes:');
+    for Attr in RType.GetAttributes do
+      PrintAttribute(Attr);
+  finally
+    RCtx.Free;
+  end;
+end;
+
+begin
+  HaltOnNotReleased:=True;
+  //SetHeapTraceOutput('heap.log');
+  PrintClassAttributes(TMyClass);
+  PrintTypeAttributes(TypeInfo(TMyRec));
+  PrintTypeAttributes(TypeInfo(TMyInt));
+end.