#1 2015-01-15 16:32:40

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

Line 152 needs to be changed to

      result.{{fullPropName}}.Add(Variant2{{typePascal}}(Value.{{fullPropName}}[i]));

I have added Variant2 so that the generated conversion function is called instead of the typecast. The tyecast of a variant to a recordtype is not supported in sms.

Offline

#2 2015-01-15 18:52:54

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

Which kind of pascal type are you talking about?
This line is about {{#nestedSimpleArray}}, so here it would be simple numbers or strings.

Records are handled just after this line, by the {{#nestedRecordArray}} ... {{/nestedRecordArray}} block.

Offline

#3 2015-01-15 21:09:02

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

I am talking about a record that contains an array of another record.

type
  Ta=record
    ...
  end;
  Tb=record
    arr:array of Ta;
    ...
  end;

so you may be right...

But a matter of fact is that the existing template generates code that can't be compiled by sms for the above data structure. I'm using such structure as a DTO in an interfaced service.

My fix resolves the issue for the above structure but I am not sure if it breaks something with arrays of simple types...

Last edited by martin.suer (2015-01-15 21:21:33)

Offline

#4 2015-01-15 22:05:59

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

ok, more details... I have done some more testing. (XE7,SMS2.1.2,Win8.1)

The following type in delphi

type
  TRecA=packed record
    v1,v2:integer;
  end;
  TRecB=packed record
    a1:array of TRecA;
    a2:array of integer;
    v1:integer;
  end;

results to this generated code in mORMotClient.pas (sms)

function Variant2TRecB(const Value: variant): TRecB;
begin
  if VariantType(Value.a1)=jvArray then
    for var i := 0 to integer(Value.a1.length)-1 do
      result.a1.Add(TRecA(Value.a1[i]));
  if VariantType(Value.a2)=jvArray then
    for var i := 0 to integer(Value.a2.length)-1 do
      result.a2.Add(Integer(Value.a2[i]));
  result.v1 := Value.v1;
end;

compiling that with sms raises
Syntax Error: Not a method [line: 226, column: 35, file: mORMotClient]

Offline

#5 2015-01-15 22:14:13

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

and with my fix applied the generated code changes to

function Variant2TRecB(const Value: variant): TRecB;
begin
  if VariantType(Value.a1)=jvArray then
    for var i := 0 to integer(Value.a1.length)-1 do
      result.a1.Add(Variant2TRecA(Value.a1[i]));
  if VariantType(Value.a2)=jvArray then
    for var i := 0 to integer(Value.a2.length)-1 do
      result.a2.Add(Variant2Integer(Value.a2[i]));
  result.v1 := Value.v1;
end;

which then calls the right conversion function Variant2RecA but breaks the typecast for Integer in the next for loop. So my fix doesn't work.
The type of the array member must be taken into account there

Offline

#6 2015-01-15 22:18:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

Which version of SMS did you use?

Offline

#7 2015-01-15 22:25:52

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

found the problem in the context, both arrays are tagged as simple arrays:

{
      name: "TRecB",
      fields: 
      [
        {
          typeWrapper: "wArray",
          typeSource: "",
          typeDelphi: null,
          typePascal: null,
          typeCS: null,
          typeJava: null,
          isArray: true,
          propName: "a1",
          fullPropName: "a1",
          isSimple: null,
          nestedSimpleArray: {
            typeWrapper: "wRecord",
            typeSource: "TRecA",
            typeDelphi: "TRecA",
            typePascal: "TRecA",
            typeCS: "TRecA",
            typeJava: "TRecA",
            isRecord: true,
            toVariant: "TRecA2Variant",
            fromVariant: "Variant2TRecA",
            nestedIdentation: "  ",
            isSimple: null
          }
        },
        {
          typeWrapper: "wArray",
          typeSource: "",
          typeDelphi: null,
          typePascal: null,
          typeCS: null,
          typeJava: null,
          isArray: true,
          propName: "a2",
          fullPropName: "a2",
          isSimple: null,
          nestedSimpleArray: {
            typeWrapper: "wInteger",
            typeSource: "Integer",
            typeDelphi: "Integer",
            typePascal: "Integer",
            typeCS: "integer",
            typeJava: "int",
            nestedIdentation: "  ",
            isSimple: true
          }
        },
        {
          typeWrapper: "wInteger",
          typeSource: "Integer",
          typeDelphi: "Integer",
          typePascal: "Integer",
          typeCS: "integer",
          typeJava: "int",
          propName: "v1",
          fullPropName: "v1",
          isSimple: true
        }
      ]
    }

Offline

#8 2015-01-15 22:27:01

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

used SMS 2.1.2 from Oktober

Offline

#9 2015-01-15 23:32:17

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

OK

I will check it tomorrow.

Offline

#10 2015-01-16 08:29:21

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

The problem is with TRecA.
It is an unmanaged record, i.e. it contains only non managed types (and no string, array or variant).
So in fact, there won't be any RTTI generated by the compiler.
Under Delphi 7, TypeInfo(TRecA) even does not compile!

So you should not use a record as TRecA as stand-alone.
This is a compiler limitation, not a mORMot limitation.

What you should write is:

type
  TRecB=packed record
    a1:array of packed record
      v1,v2:integer;
    end;
    a2:array of integer;
    v1:integer;
  end;

Then, the wrapper generated code will be:

function Variant2TRecB(const Value: variant): TRecB;
begin
  if VariantType(Value.a)=jvArray then begin
    var tmp: TRecB;
    tmp.J.SetLength(1);
    for var n := 0 to integer(Value.a.length)-1 do begin
      var source := Value.a[n];
      var dest := tmp.J[0];
      dest.v1 := source.v1;
      dest.v2 := source.v2;
      result.a.Add(dest);
    end;
  end;
  if VariantType(Value.a2)=jvArray then
    for var i := 0 to integer(Value.a2.length)-1 do
      result.a2.Add(Integer(Value.a2[i]));
  result.v1 := Value.v1;
end;

Which sounds quite correct.

Offline

#11 2015-01-16 09:56:56

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

Hi ab,

I can't confirm that. I have changed the TRecB to your proposal (cut & pasted directly from the forum) and the generated code then looks like this:

function Variant2TRecB(const Value: variant): TRecB;
begin
  if VariantType(Value.a1)=jvArray then
    for var i := 0 to integer(Value.a1.length)-1 do
      result.a1.Add(:TRecB.:1(Value.a1[i]));
  if VariantType(Value.a2)=jvArray then
    for var i := 0 to integer(Value.a2.length)-1 do
      result.a2.Add(Integer(Value.a2[i]));
  result.v1 := Value.v1;
end;

the context is:

    {
      name: "TRecB",
      fields: 
      [
        {
          typeWrapper: "wArray",
          typeSource: "",
          typeDelphi: null,
          typePascal: null,
          typeCS: null,
          typeJava: null,
          isArray: true,
          propName: "a1",
          fullPropName: "a1",
          isSimple: null,
          nestedSimpleArray: {
            typeWrapper: "wRecord",
            typeSource: ":TRecB.:1",
            typeDelphi: ":TRecB.:1",
            typePascal: ":TRecB.:1",
            typeCS: ":TRecB.:1",
            typeJava: ":TRecB.:1",
            isRecord: true,
            toVariant: ":TRecB.:12Variant",
            fromVariant: "Variant2:TRecB.:1",
            nestedIdentation: "  ",
            isSimple: null
          }
        },
        {
          typeWrapper: "wArray",
          typeSource: "",
          typeDelphi: null,
          typePascal: null,
          typeCS: null,
          typeJava: null,
          isArray: true,
          propName: "a2",
          fullPropName: "a2",
          isSimple: null,
          nestedSimpleArray: {
            typeWrapper: "wInteger",
            typeSource: "Integer",
            typeDelphi: "Integer",
            typePascal: "Integer",
            typeCS: "integer",
            typeJava: "int",
            nestedIdentation: "  ",
            isSimple: true
          }
        },
        {
          typeWrapper: "wInteger",
          typeSource: "Integer",
          typeDelphi: "Integer",
          typePascal: "Integer",
          typeCS: "integer",
          typeJava: "int",
          propName: "v1",
          fullPropName: "v1",
          isSimple: true
        }
      ]
    }

Last edited by martin.suer (2015-01-16 09:57:21)

Offline

#12 2015-01-16 10:03:50

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

also the generated types for the record are

  :TRecB.:1 = record
    v1: Integer;
    v2: Integer;
  end;

  TRecB = record
    a1: array of :TRecB.:1;
    a2: array of Integer;
    v1: Integer;
  end;

Offline

#13 2015-01-16 11:22:28

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

It was working with Delphi 7.
But sounds like if there is some change in generated RTTI with Delphi 2010 and up.
I will check out.

Offline

#14 2015-01-16 12:04:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

In fact, if you define:

const  __TRecB = 'a1 [v1,v2:integer] a2:array of integer v1:integer';
...
  TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TRecB),__TRecB);

as with Delphi 7, everything is fine under XE7.

So there seems to be an issue with the record definition as retrieved from enhanced RTTI (Delphi 2010+).

Offline

#15 2015-01-16 15:16:55

martin.suer
Member
Registered: 2013-12-15
Posts: 76

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

I could arrange with defining the text constants and calling RegisterCustomJSONSerializerFromText but that doesn't work either.

In your post http://synopse.info/forum/viewtopic.php … 438#p14438 your generated code "sounds quite correct" but doesn't compile either.


The J in variable tmp is not defined.

tmp.J.SetLength(1);

Offline

#16 2015-01-16 16:43:49

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

Should be fixed by http://synopse.info/fossil/info/2908dff5b2

But I still need to fix the problem with enhanced RTTI (Delphi 2010+).
I want it to work directly, as expected.

Offline

#17 2015-01-16 20:29:16

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: Bug (and Fix) in CrossPlatform Template SmartMobileStudio.pas.mustache

I think I have fix the code generation problem for nested arrays of record with enhanced RTTI (Delphi 2010+).
See http://synopse.info/fossil/info/612863b69f

Now it seems consistent with what is expected by the code generators.

More feedback is welcome!

Offline

Board footer

Powered by FluxBB