mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-02 12:20:38 +02:00
codetools: test write tpersistent
git-svn-id: trunk@56173 -
This commit is contained in:
parent
d72b90506d
commit
8ba2af9481
@ -4,10 +4,13 @@
|
|||||||
./runtests --format=plain --suite=TTestCompReaderWriterPas.TestBaseTypesMaxValues
|
./runtests --format=plain --suite=TTestCompReaderWriterPas.TestBaseTypesMaxValues
|
||||||
|
|
||||||
Working:
|
Working:
|
||||||
|
- boolean
|
||||||
- integer
|
- integer
|
||||||
- strings
|
- strings
|
||||||
- enum, custom enum range
|
- enum, custom enum range
|
||||||
- set of enum, set of custom enum range
|
- set of enum, set of custom enum range
|
||||||
|
- variant
|
||||||
|
- method
|
||||||
|
|
||||||
ToDo:
|
ToDo:
|
||||||
- enum: add unit, avoid nameclash with-do
|
- enum: add unit, avoid nameclash with-do
|
||||||
@ -15,8 +18,6 @@ ToDo:
|
|||||||
- set of char
|
- set of char
|
||||||
- custom integer TColor, add unit, avoid nameclash with-do
|
- custom integer TColor, add unit, avoid nameclash with-do
|
||||||
- method, avoid nameclash with-do
|
- method, avoid nameclash with-do
|
||||||
- variant
|
|
||||||
- datetime
|
|
||||||
- TComponent.Left/Right
|
- TComponent.Left/Right
|
||||||
- subcomponents
|
- subcomponents
|
||||||
- cycle in subcomponents
|
- cycle in subcomponents
|
||||||
@ -25,6 +26,7 @@ ToDo:
|
|||||||
- inline component
|
- inline component
|
||||||
- collection
|
- collection
|
||||||
- DefineProperties
|
- DefineProperties
|
||||||
|
- tkInterface
|
||||||
}
|
}
|
||||||
unit TestCompReaderWriterPas;
|
unit TestCompReaderWriterPas;
|
||||||
|
|
||||||
@ -81,7 +83,7 @@ type
|
|||||||
procedure SetRoot(const AValue: TComponent);
|
procedure SetRoot(const AValue: TComponent);
|
||||||
procedure WriteComponentData(Instance: TComponent);
|
procedure WriteComponentData(Instance: TComponent);
|
||||||
procedure WriteProperty(Instance: TPersistent; PropInfo: PPropInfo);
|
procedure WriteProperty(Instance: TPersistent; PropInfo: PPropInfo);
|
||||||
procedure WriteProperties(Instance: TComponent);
|
procedure WriteProperties(Instance: TPersistent);
|
||||||
function GetBoolLiteral(b: boolean): string;
|
function GetBoolLiteral(b: boolean): string;
|
||||||
function GetStringLiteral(const s: string): string;
|
function GetStringLiteral(const s: string): string;
|
||||||
function GetWStringLiteral(p: PWideChar; Count: integer): string;
|
function GetWStringLiteral(p: PWideChar; Count: integer): string;
|
||||||
@ -370,6 +372,34 @@ type
|
|||||||
property V20: variant read FV20 write FV20;
|
property V20: variant read FV20 write FV20;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TPersistentSimple }
|
||||||
|
|
||||||
|
TPersistentSimple = class(TPersistent)
|
||||||
|
private
|
||||||
|
FSize: longint;
|
||||||
|
FSub: TPersistentSimple;
|
||||||
|
published
|
||||||
|
property Size: longint read FSize write FSize;
|
||||||
|
property Sub: TPersistentSimple read FSub write FSub;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TCompPropPersistent }
|
||||||
|
|
||||||
|
TCompPropPersistent = class(TComponent)
|
||||||
|
private
|
||||||
|
FAfter: longint;
|
||||||
|
FBefore: longint;
|
||||||
|
FMiddle: longint;
|
||||||
|
FSub: TPersistentSimple;
|
||||||
|
FSub2: TPersistentSimple;
|
||||||
|
published
|
||||||
|
property Before: longint read FBefore write FBefore;
|
||||||
|
property Sub: TPersistentSimple read FSub write FSub;
|
||||||
|
property Middle: longint read FMiddle write FMiddle;
|
||||||
|
property Sub2: TPersistentSimple read FSub2 write FSub2;
|
||||||
|
property After: longint read FAfter write FAfter;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TTestCompReaderWriterPas }
|
{ TTestCompReaderWriterPas }
|
||||||
|
|
||||||
TTestCompReaderWriterPas = class(TCustomTestCTStdCodetools)
|
TTestCompReaderWriterPas = class(TCustomTestCTStdCodetools)
|
||||||
@ -393,6 +423,8 @@ type
|
|||||||
procedure TestWideString_SrcCodePageSystem;
|
procedure TestWideString_SrcCodePageSystem;
|
||||||
procedure TestWideString_SrcCodePageUTF8;
|
procedure TestWideString_SrcCodePageUTF8;
|
||||||
procedure TestVariant;
|
procedure TestVariant;
|
||||||
|
procedure TestPropPersistent;
|
||||||
|
procedure TestChildComponent; // ToDo
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -707,10 +739,10 @@ type
|
|||||||
TSet = set of 0..31;
|
TSet = set of 0..31;
|
||||||
var
|
var
|
||||||
PropType, CompType: PTypeInfo;
|
PropType, CompType: PTypeInfo;
|
||||||
ObjValue: TObject;
|
ObjValue, AncestorObj: TObject;
|
||||||
HasAncestor, BoolValue, DefBoolValue: Boolean;
|
HasAncestor, BoolValue, DefBoolValue: Boolean;
|
||||||
Int32Value, DefValue: longint;
|
Int32Value, DefValue: longint;
|
||||||
PropName, Ident, s, StrValue, DefStrValue: String;
|
PropName, Ident, s, StrValue, DefStrValue, Name, SavedPropPath: String;
|
||||||
IntToIdentFn: TIntToIdent;
|
IntToIdentFn: TIntToIdent;
|
||||||
i, j: Integer;
|
i, j: Integer;
|
||||||
Int64Value, DefInt64Value: Int64;
|
Int64Value, DefInt64Value: Int64;
|
||||||
@ -720,6 +752,8 @@ var
|
|||||||
UStrValue, UDefStrValue: UnicodeString;
|
UStrValue, UDefStrValue: UnicodeString;
|
||||||
VarValue, DefVarValue: tvardata;
|
VarValue, DefVarValue: tvardata;
|
||||||
aTypeData: PTypeData;
|
aTypeData: PTypeData;
|
||||||
|
Component, C: TComponent;
|
||||||
|
SavedAncestor: TPersistent;
|
||||||
begin
|
begin
|
||||||
// do not stream properties without getter
|
// do not stream properties without getter
|
||||||
if not Assigned(PropInfo^.GetProc) then
|
if not Assigned(PropInfo^.GetProc) then
|
||||||
@ -923,24 +957,24 @@ begin
|
|||||||
begin
|
begin
|
||||||
// can't use variant() typecast, pulls in variants unit
|
// can't use variant() typecast, pulls in variants unit
|
||||||
case VarValue.vtype of
|
case VarValue.vtype of
|
||||||
varsmallint : WriteAssign(PropName,IntToStr(VarValue.vsmallint));
|
varsmallint : WriteAssign(PropName,'SmallInt('+IntToStr(VarValue.vsmallint)+')');
|
||||||
varinteger : WriteAssign(PropName,IntToStr(VarValue.vinteger));
|
varinteger : WriteAssign(PropName,'LongInt('+IntToStr(VarValue.vinteger)+')');
|
||||||
varsingle : WriteAssign(PropName,GetFloatLiteral(VarValue.vsingle));
|
varsingle : WriteAssign(PropName,'Single('+GetFloatLiteral(VarValue.vsingle)+')');
|
||||||
vardouble : WriteAssign(PropName,GetFloatLiteral(VarValue.vdouble));
|
vardouble : WriteAssign(PropName,'Double('+GetFloatLiteral(VarValue.vdouble)+')');
|
||||||
vardate : WriteAssign(PropName,GetFloatLiteral(VarValue.vdate));
|
vardate : WriteAssign(PropName,'TDateTime('+GetFloatLiteral(VarValue.vdate)+')');
|
||||||
varcurrency : WriteAssign(PropName,GetCurrencyLiteral(VarValue.vcurrency));
|
varcurrency : WriteAssign(PropName,'Currency('+GetCurrencyLiteral(VarValue.vcurrency)+')');
|
||||||
//varolestr : (volestr : pwidechar);
|
//varolestr : (volestr : pwidechar);
|
||||||
//vardispatch : (vdispatch : pointer);
|
//vardispatch : (vdispatch : pointer);
|
||||||
//varerror : (verror : hresult);
|
//varerror : (verror : hresult);
|
||||||
varboolean : WriteAssign(PropName,GetBoolLiteral(VarValue.vboolean));
|
varboolean : WriteAssign(PropName,GetBoolLiteral(VarValue.vboolean));
|
||||||
//varunknown : (vunknown : pointer);
|
//varunknown : (vunknown : pointer);
|
||||||
// vardecimal : ( : );
|
// vardecimal : ( : );
|
||||||
varshortint : WriteAssign(PropName,IntToStr(VarValue.vshortint));
|
varshortint : WriteAssign(PropName,'ShortInt('+IntToStr(VarValue.vshortint)+')');
|
||||||
varbyte : WriteAssign(PropName,IntToStr(VarValue.vbyte));
|
varbyte : WriteAssign(PropName,'Byte('+IntToStr(VarValue.vbyte)+')');
|
||||||
varword : WriteAssign(PropName,IntToStr(VarValue.vword));
|
varword : WriteAssign(PropName,'Word('+IntToStr(VarValue.vword)+')');
|
||||||
varlongword : WriteAssign(PropName,IntToStr(VarValue.vlongword));
|
varlongword : WriteAssign(PropName,'LongWord('+IntToStr(VarValue.vlongword)+')');
|
||||||
varint64 : WriteAssign(PropName,IntToStr(VarValue.vint64));
|
varint64 : WriteAssign(PropName,'Int64('+IntToStr(VarValue.vint64)+')');
|
||||||
varqword : WriteAssign(PropName,IntToStr(VarValue.vqword));
|
varqword : WriteAssign(PropName,'QWord('+IntToStr(VarValue.vqword)+')');
|
||||||
// duplicate: varword64
|
// duplicate: varword64
|
||||||
varstring : WriteAssign(PropName,GetStringLiteral(AnsiString(VarValue.vstring)));
|
varstring : WriteAssign(PropName,GetStringLiteral(AnsiString(VarValue.vstring)));
|
||||||
//varany : (vany : pointer);
|
//varany : (vany : pointer);
|
||||||
@ -956,6 +990,110 @@ begin
|
|||||||
//ToDo WriteVariant(pvariant(@VarValue)^);
|
//ToDo WriteVariant(pvariant(@VarValue)^);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
tkClass:
|
||||||
|
begin
|
||||||
|
ObjValue := TObject(GetObjectProp(Instance, PropInfo));
|
||||||
|
if HasAncestor then
|
||||||
|
begin
|
||||||
|
AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo));
|
||||||
|
if (AncestorObj is TComponent) and
|
||||||
|
(ObjValue is TComponent) then
|
||||||
|
begin
|
||||||
|
//debugln(['TWriter.WriteProperty AncestorObj=',TComponent(AncestorObj).Name,' OwnerFit=',TComponent(AncestorObj).Owner = FRootAncestor,' ',TComponent(ObjValue).Name,' OwnerFit=',TComponent(ObjValue).Owner = Root]);
|
||||||
|
if (AncestorObj<>ObjValue) and
|
||||||
|
(TComponent(AncestorObj).Owner = FRootAncestor) and
|
||||||
|
(TComponent(ObjValue).Owner = Root) and
|
||||||
|
(CompareText(TComponent(AncestorObj).Name,TComponent(ObjValue).Name)=0) then
|
||||||
|
begin
|
||||||
|
// different components, but with the same name
|
||||||
|
// -> keep property value
|
||||||
|
AncestorObj := ObjValue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
AncestorObj := nil;
|
||||||
|
|
||||||
|
if not Assigned(ObjValue) then
|
||||||
|
begin
|
||||||
|
if ObjValue <> AncestorObj then
|
||||||
|
WriteAssign(PropName,'Nil');
|
||||||
|
end
|
||||||
|
else if ObjValue.InheritsFrom(TPersistent) then
|
||||||
|
begin
|
||||||
|
// Subcomponents are streamed the same way as persistents
|
||||||
|
if ObjValue.InheritsFrom(TComponent)
|
||||||
|
and ((not (csSubComponent in TComponent(ObjValue).ComponentStyle))
|
||||||
|
or ((TComponent(ObjValue).Owner<>Instance) and (TComponent(ObjValue).Owner<>Nil))) then
|
||||||
|
begin
|
||||||
|
Component := TComponent(ObjValue);
|
||||||
|
if (ObjValue <> AncestorObj)
|
||||||
|
and not (csTransient in Component.ComponentStyle) then
|
||||||
|
begin
|
||||||
|
// set property value
|
||||||
|
Name:= '';
|
||||||
|
C:= Component;
|
||||||
|
While (C<>Nil) and (C.Name<>'') do
|
||||||
|
begin
|
||||||
|
If (Name<>'') Then
|
||||||
|
Name:='.'+Name;
|
||||||
|
if C.Owner = LookupRoot then
|
||||||
|
begin
|
||||||
|
Name := C.Name+Name;
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
else if C = LookupRoot then
|
||||||
|
begin
|
||||||
|
Name := 'Self' + Name;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
Name:=C.Name + Name;
|
||||||
|
C:= C.Owner;
|
||||||
|
end;
|
||||||
|
if (C=nil) and (Component.Owner=nil) then
|
||||||
|
if (Name<>'') then // Component is a foreign root
|
||||||
|
; // Name:=Name+'.Owner';
|
||||||
|
if Length(Name) > 0 then
|
||||||
|
WriteAssign(PropName,Name);
|
||||||
|
end; //(ObjValue <> AncestorObj)
|
||||||
|
end // ObjValue.InheritsFrom(TComponent)
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// keep property value, set sub properties recursively with full path
|
||||||
|
// e.g. Font.Size:=5;
|
||||||
|
SavedAncestor := Ancestor;
|
||||||
|
SavedPropPath := FPropPath;
|
||||||
|
try
|
||||||
|
FPropPath := FPropPath + PPropInfo(PropInfo)^.Name + '.';
|
||||||
|
if HasAncestor then
|
||||||
|
Ancestor := TPersistent(GetObjectProp(Ancestor, PropInfo));
|
||||||
|
WriteProperties(TPersistent(ObjValue));
|
||||||
|
finally
|
||||||
|
Ancestor := SavedAncestor;
|
||||||
|
FPropPath := SavedPropPath;
|
||||||
|
end;
|
||||||
|
if ObjValue.InheritsFrom(TCollection) then
|
||||||
|
begin
|
||||||
|
if (not HasAncestor) or (not CollectionsEqual(TCollection(ObjValue),
|
||||||
|
TCollection(GetObjectProp(Ancestor, PropInfo)),Root,RootAncestor)) then
|
||||||
|
begin
|
||||||
|
// create collection items
|
||||||
|
{$IFDEF VerboseCompWriterPas}
|
||||||
|
debugln(['TCompWriterPas.WriteProperty Property="',PropName,'" Kind=',PropType^.Kind,' ObjValue=',DbgSName(ObjValue)]);
|
||||||
|
raise EWriteError.Create('storing collection not yet supported');
|
||||||
|
{$ENDIF}
|
||||||
|
//Driver.BeginProperty(FPropPath + PPropInfo(PropInfo)^.Name);
|
||||||
|
SavedPropPath := FPropPath;
|
||||||
|
try
|
||||||
|
SetLength(FPropPath, 0);
|
||||||
|
//WriteCollection(TCollection(ObjValue));
|
||||||
|
finally
|
||||||
|
FPropPath := SavedPropPath;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end // TCollection
|
||||||
|
end;
|
||||||
|
end; // Inheritsfrom(TPersistent)
|
||||||
|
end;
|
||||||
tkInt64, tkQWord:
|
tkInt64, tkQWord:
|
||||||
begin
|
begin
|
||||||
Int64Value := GetInt64Prop(Instance, PropInfo);
|
Int64Value := GetInt64Prop(Instance, PropInfo);
|
||||||
@ -989,7 +1127,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCompWriterPas.WriteProperties(Instance: TComponent);
|
procedure TCompWriterPas.WriteProperties(Instance: TPersistent);
|
||||||
var
|
var
|
||||||
PropCount, i: integer;
|
PropCount, i: integer;
|
||||||
PropList: PPropList;
|
PropList: PPropList;
|
||||||
@ -1722,25 +1860,75 @@ begin
|
|||||||
V13:=currency(17.0001);
|
V13:=currency(17.0001);
|
||||||
end;
|
end;
|
||||||
TestWriteDescendant('TestVariant',AComponent,nil,[
|
TestWriteDescendant('TestVariant',AComponent,nil,[
|
||||||
'V1:=255;',
|
'V1:=Byte(255);',
|
||||||
'V2:=-128;',
|
'V2:=ShortInt(-128);',
|
||||||
'V3:=65535;',
|
'V3:=Word(65535);',
|
||||||
'V4:=-32768;',
|
'V4:=SmallInt(-32768);',
|
||||||
'V5:=4294967295;',
|
'V5:=LongWord(4294967295);',
|
||||||
'V6:=-2147483648;',
|
'V6:=LongInt(-2147483648);',
|
||||||
'V7:=18446744073709551615;',
|
'V7:=QWord(18446744073709551615);',
|
||||||
'V8:=-9223372036854775808;',
|
'V8:=Int64(-9223372036854775808);',
|
||||||
'V9:=True;',
|
'V9:=True;',
|
||||||
'V10:=''äöü'';',
|
'V10:=''äöü'';',
|
||||||
'V11:=-1.25;',
|
'V11:=Double(-1.25);',
|
||||||
'V12:=1.5;',
|
'V12:=Double(1.5);',
|
||||||
'V13:=1.70001E1;',
|
'V13:=Currency(1.70001E1);',
|
||||||
'']);
|
'']);
|
||||||
finally
|
finally
|
||||||
AComponent.Free;
|
AComponent.Free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestCompReaderWriterPas.TestPropPersistent;
|
||||||
|
var
|
||||||
|
aRoot: TCompPropPersistent;
|
||||||
|
begin
|
||||||
|
aRoot:=TCompPropPersistent.Create(nil);
|
||||||
|
try
|
||||||
|
with aRoot do begin
|
||||||
|
Name:=aRoot.ClassName+'1';
|
||||||
|
Before:=1;
|
||||||
|
Sub:=TPersistentSimple.Create;
|
||||||
|
Sub.Size:=11;
|
||||||
|
Middle:=2;
|
||||||
|
Sub2:=TPersistentSimple.Create;
|
||||||
|
Sub2.Size:=21;
|
||||||
|
Sub2.Sub:=TPersistentSimple.Create;
|
||||||
|
Sub2.Sub.Size:=211;
|
||||||
|
After:=3;
|
||||||
|
end;
|
||||||
|
TestWriteDescendant('TestPropPersistent',aRoot,nil,[
|
||||||
|
'Before:=1;',
|
||||||
|
'Sub.Size:=11;',
|
||||||
|
'Middle:=2;',
|
||||||
|
'Sub2.Size:=21;',
|
||||||
|
'Sub2.Sub.Size:=211;',
|
||||||
|
'After:=3;',
|
||||||
|
'']);
|
||||||
|
finally
|
||||||
|
FreeAndNil(aRoot.FSub2.FSub);
|
||||||
|
FreeAndNil(aRoot.FSub2);
|
||||||
|
FreeAndNil(aRoot.FSub);
|
||||||
|
aRoot.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestCompReaderWriterPas.TestChildComponent;
|
||||||
|
var
|
||||||
|
aRoot: TCompVariants;
|
||||||
|
begin
|
||||||
|
aRoot:=TCompVariants.Create(nil);
|
||||||
|
try
|
||||||
|
with aRoot do begin
|
||||||
|
Name:=aRoot.ClassName+'1';
|
||||||
|
end;
|
||||||
|
TestWriteDescendant('TestChildComponent',aRoot,nil,[
|
||||||
|
'']);
|
||||||
|
finally
|
||||||
|
aRoot.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
RegisterTest(TTestCompReaderWriterPas);
|
RegisterTest(TTestCompReaderWriterPas);
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user