[fpc-devel] class-attributes

Joost van der Sluis joost at cnoc.nl
Thu May 24 15:27:29 CEST 2012


On 17 May 2012, at 23:32, Joost van der Sluis wrote:

>> I'm trying to implement extended RTTI property attributes as
>> supported by recent Delphi versions.

>>Please add this functionality first to a separate branch for easier
>>reviewing.

I could, but I attached a patch first. Before I commit this to a branch
I want to know that I'm on the right track. Could you and/or others have
a look at the patch?

I'm especially interested if things are done in the right units, and if
the code in ptypes.pas is acceptable.

Attached are the patch and a simple test-program. 

First an example what class-attributes are:

type
  TMyObject = class
  published
    [TAttributeClassName('param1','param2')]
    property AProperty;
  end;

When you request the class-property that belongs to the property
AProperty, then you get an instance of the TAttributeClassName class
which is constructed by calling it's constructor with the supplied
parameters. (In this case 'param1' and 'param2')

How I implemented this:
For each attribute a function is generated that returns a class-instance
of the attribute. This function is generated in ptypes by creating a
tcgprocinfo. All the necessary nodes are added to it and then
tcgprocinfo.generate_code is executed.

In the rtti-info (ppropinfo) the address of this function is stored so
that it is possible to read those attributes.

If I'm on the right track I'll add a branch with this patch and work
from there. Some issues:

- In Delphi an attribute-class has to be defined as a TCustomAttribute.
That way it's also clear which constructor has to be called. For now, it
calls the first constructor it can find.

- The rtti-info is now stored inside PPropInfo, I don't think that this
is how Delphi does it, also because in Delphi you need the 'rtti' unit
to get this information. I've added it to typinfo and later on a 'rtti'
unit could be written as a wrapper around typinfo.

- When we add more rtti-information to types we need a way to specify
what to generate and what not and where to store it. Especially because
the rtti-info will grow. 

- No error is generated when you define an attribute for something else
then a property.

- The attribute-definition is stored in the .ppu, but that's not really
needed. Since at compile-time this information is never used by another
unit. I used it for debugging though (with ppudump) A side-effect is
that when an attribute is changed, a recompilation of the unit is
forced. Do we want that? (For now only the attribute-type is stored in
the ppu, not the parameters)

Joost.







-- 
Met vriendelijke groeten,

  Joost van der Sluis
  CNOC Informatiesystemen en Netwerken
  http://www.cnoc.nl
-------------- next part --------------
A non-text attachment was scrubbed...
Name: class_attributes.patch
Type: text/x-patch
Size: 19985 bytes
Desc: not available
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20120524/b0c628dc/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: testclassattributesunit.pas
Type: text/x-pascal
Size: 811 bytes
Desc: not available
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20120524/b0c628dc/attachment.pas>
-------------- next part --------------
program testclassattributes;

{$mode objfpc}{$H+}

uses
  Classes, testclassattributesunit,typinfo;

procedure WritePropInfo(APropInfo: PPropInfo);
var
  i: Integer;
  AnAttr: TObject;
begin
  writeln('Propertyname: ',APropInfo^.Name);
  writeln('Attributecount: ',APropInfo^.AttributeCount);
  for i := 0 to APropInfo^.AttributeCount-1 do
    begin
    AnAttr := GetPropAttribute(APropInfo,i);
    writeln('  attribute:', AnAttr.ClassName);
    if AnAttr is TAttribute then
    writeln('  value:', TAttribute(AnAttr).Value);
    end;
end;

procedure WriteClassPropInfo(AnObject: TObject);
var
  APropList: PPropList;
  propcount: integer;
  i: integer;
begin
  PropCount := GetPropList(AnObject,APropList);
  for i := 0 to propcount-1 do
    begin
    WritePropInfo(APropList^[i]);
    end;
end;

var
  HasAttributes: THasAttributes;

begin
  HasAttributes := THasAttributes.Create;
  WriteClassPropInfo(HasAttributes);
  HasAttributes.Free;
end.



More information about the fpc-devel mailing list