@@ -93,8 +93,8 @@ public void generate() throws IOException
93
93
collectVarData (messageBody , offset , varData );
94
94
generateVarData (sb , ctorArgs , varData , BASE_INDENT + INDENT );
95
95
96
- generateDecodeFrom (sb , className , codecClassName , fields , groups , varData , BASE_INDENT + INDENT );
97
- generateEncodeInto (sb , codecClassName , fields , groups , varData , BASE_INDENT + INDENT );
96
+ generateMessageDecodeFrom (sb , className , codecClassName , fields , groups , varData , BASE_INDENT + INDENT );
97
+ generateMessageEncodeInto (sb , codecClassName , fields , groups , varData , BASE_INDENT + INDENT );
98
98
generateDisplay (sb , codecClassName , "WrapForEncode" , null , BASE_INDENT + INDENT );
99
99
100
100
removeTrailingComma (ctorArgs );
@@ -119,6 +119,12 @@ public void generate() throws IOException
119
119
}
120
120
}
121
121
122
+ private enum DefinitionKind
123
+ {
124
+ Composite ,
125
+ Message
126
+ }
127
+
122
128
private void generateGroups (
123
129
final StringBuilder sb ,
124
130
final StringBuilder ctorArgs ,
@@ -174,9 +180,9 @@ private void generateGroups(
174
180
175
181
generateDecodeListFrom (
176
182
groupRecordBody , groupClassName , qualifiedCodecClassName , indent + INDENT );
177
- generateDecodeFrom (
183
+ generateMessageDecodeFrom (
178
184
groupRecordBody , groupClassName , qualifiedCodecClassName , fields , groups , varData , indent + INDENT );
179
- generateEncodeInto (
185
+ generateMessageEncodeInto (
180
186
groupRecordBody , qualifiedCodecClassName , fields , groups , varData , indent + INDENT );
181
187
182
188
removeTrailingComma (groupCtorArgs );
@@ -210,7 +216,8 @@ private void generateCompositeDecodeFrom(
210
216
{
211
217
final Token token = tokens .get (i );
212
218
213
- generateFieldDecodeFrom (sb , token , token , codecClassName , indent + INDENT + INDENT );
219
+ generateFieldDecodeFrom (
220
+ sb , DefinitionKind .Composite , token , token , codecClassName , indent + INDENT + INDENT );
214
221
215
222
i += tokens .get (i ).componentTokenCount ();
216
223
}
@@ -270,7 +277,7 @@ private void generateDecodeListFrom(
270
277
.append (indent ).append ("}\n " );
271
278
}
272
279
273
- private void generateDecodeFrom (
280
+ private void generateMessageDecodeFrom (
274
281
final StringBuilder sb ,
275
282
final String dtoClassName ,
276
283
final String codecClassName ,
@@ -285,7 +292,7 @@ private void generateDecodeFrom(
285
292
.append (indent ).append ("{\n " );
286
293
287
294
sb .append (indent ).append (INDENT ).append ("return new " ).append (dtoClassName ).append ("(\n " );
288
- generateFieldsDecodeFrom (sb , fields , codecClassName , indent + INDENT + INDENT );
295
+ generateMessageFieldsDecodeFrom (sb , fields , codecClassName , indent + INDENT + INDENT );
289
296
generateGroupsDecodeFrom (sb , groups , indent + INDENT + INDENT );
290
297
generateVarDataDecodeFrom (sb , varData , indent + INDENT + INDENT );
291
298
removeTrailingComma (sb );
@@ -294,7 +301,7 @@ private void generateDecodeFrom(
294
301
sb .append (indent ).append ("}\n " );
295
302
}
296
303
297
- private void generateFieldsDecodeFrom (
304
+ private void generateMessageFieldsDecodeFrom (
298
305
final StringBuilder sb ,
299
306
final List <Token > tokens ,
300
307
final String codecClassName ,
@@ -307,35 +314,37 @@ private void generateFieldsDecodeFrom(
307
314
{
308
315
final Token encodingToken = tokens .get (i + 1 );
309
316
310
- generateFieldDecodeFrom (sb , signalToken , encodingToken , codecClassName , indent );
317
+ generateFieldDecodeFrom (sb , DefinitionKind . Message , signalToken , encodingToken , codecClassName , indent );
311
318
}
312
319
}
313
320
}
314
321
315
322
private void generateFieldDecodeFrom (
316
323
final StringBuilder sb ,
324
+ final DefinitionKind rootKind ,
317
325
final Token fieldToken ,
318
326
final Token typeToken ,
319
- final String codecClassName , final String indent )
327
+ final String codecClassName ,
328
+ final String indent )
320
329
{
321
330
switch (typeToken .signal ())
322
331
{
323
332
case ENCODING :
324
- generatePrimitiveDecodeFrom (sb , fieldToken , typeToken , codecClassName , indent );
333
+ generatePrimitiveDecodeFrom (sb , rootKind , fieldToken , typeToken , codecClassName , indent );
325
334
break ;
326
335
327
336
case BEGIN_SET :
328
- generatePropertyDecodeFrom (sb , fieldToken , "0" , null , indent );
337
+ generatePropertyDecodeFrom (sb , rootKind , fieldToken , "0" , null , indent );
329
338
break ;
330
339
331
340
case BEGIN_ENUM :
332
341
final String enumName = formatClassName (typeToken .applicableTypeName ());
333
342
final String nullValue = formatNamespace (ir .packageName ()) + "." + enumName + ".NULL_VALUE" ;
334
- generatePropertyDecodeFrom (sb , fieldToken , nullValue , null , indent );
343
+ generatePropertyDecodeFrom (sb , rootKind , fieldToken , nullValue , null , indent );
335
344
break ;
336
345
337
346
case BEGIN_COMPOSITE :
338
- generateComplexDecodeFrom (sb , fieldToken , typeToken , indent );
347
+ generateComplexDecodeFrom (sb , rootKind , fieldToken , typeToken , indent );
339
348
break ;
340
349
341
350
default :
@@ -345,6 +354,7 @@ private void generateFieldDecodeFrom(
345
354
346
355
private void generatePrimitiveDecodeFrom (
347
356
final StringBuilder sb ,
357
+ final DefinitionKind rootKind ,
348
358
final Token fieldToken ,
349
359
final Token typeToken ,
350
360
final String codecClassName ,
@@ -360,16 +370,17 @@ private void generatePrimitiveDecodeFrom(
360
370
if (arrayLength == 1 )
361
371
{
362
372
final String codecNullValue = codecClassName + "." + formatPropertyName (fieldToken .name ()) + "NullValue" ;
363
- generatePropertyDecodeFrom (sb , fieldToken , "null" , codecNullValue , indent );
373
+ generatePropertyDecodeFrom (sb , rootKind , fieldToken , "null" , codecNullValue , indent );
364
374
}
365
375
else if (arrayLength > 1 )
366
376
{
367
- generateArrayDecodeFrom (sb , fieldToken , typeToken , indent );
377
+ generateArrayDecodeFrom (sb , rootKind , fieldToken , typeToken , indent );
368
378
}
369
379
}
370
380
371
381
private void generateArrayDecodeFrom (
372
382
final StringBuilder sb ,
383
+ final DefinitionKind rootKind ,
373
384
final Token fieldToken ,
374
385
final Token typeToken ,
375
386
final String indent )
@@ -386,6 +397,7 @@ private void generateArrayDecodeFrom(
386
397
{
387
398
generateRecordPropertyAssignment (
388
399
sb ,
400
+ rootKind ,
389
401
fieldToken ,
390
402
indent ,
391
403
"codec.Get" + formattedPropertyName + "()" ,
@@ -397,6 +409,7 @@ private void generateArrayDecodeFrom(
397
409
{
398
410
generateRecordPropertyAssignment (
399
411
sb ,
412
+ rootKind ,
400
413
fieldToken ,
401
414
indent ,
402
415
"codec." + formattedPropertyName + "AsSpan().ToArray()" ,
@@ -408,6 +421,7 @@ private void generateArrayDecodeFrom(
408
421
409
422
private void generatePropertyDecodeFrom (
410
423
final StringBuilder sb ,
424
+ final DefinitionKind rootKind ,
411
425
final Token fieldToken ,
412
426
final String dtoNullValue ,
413
427
final String codecNullValue ,
@@ -423,6 +437,7 @@ private void generatePropertyDecodeFrom(
423
437
424
438
generateRecordPropertyAssignment (
425
439
sb ,
440
+ rootKind ,
426
441
fieldToken ,
427
442
indent ,
428
443
"codec." + formattedPropertyName ,
@@ -433,6 +448,7 @@ private void generatePropertyDecodeFrom(
433
448
434
449
private void generateComplexDecodeFrom (
435
450
final StringBuilder sb ,
451
+ final DefinitionKind rootKind ,
436
452
final Token fieldToken ,
437
453
final Token typeToken ,
438
454
final String indent )
@@ -443,6 +459,7 @@ private void generateComplexDecodeFrom(
443
459
444
460
generateRecordPropertyAssignment (
445
461
sb ,
462
+ rootKind ,
446
463
fieldToken ,
447
464
indent ,
448
465
dtoClassName + ".DecodeFrom(codec." + formattedPropertyName + ")" ,
@@ -469,6 +486,7 @@ private void generateGroupsDecodeFrom(
469
486
470
487
generateRecordPropertyAssignment (
471
488
sb ,
489
+ DefinitionKind .Message ,
472
490
groupToken ,
473
491
indent ,
474
492
groupDtoClassName + ".DecodeListFrom(codec." + formattedPropertyName + ")" ,
@@ -511,6 +529,7 @@ private void generateVarDataDecodeFrom(
511
529
512
530
generateRecordPropertyAssignment (
513
531
sb ,
532
+ DefinitionKind .Message ,
514
533
token ,
515
534
indent ,
516
535
"codec." + accessor + "()" ,
@@ -523,6 +542,7 @@ private void generateVarDataDecodeFrom(
523
542
524
543
private void generateRecordPropertyAssignment (
525
544
final StringBuilder sb ,
545
+ final DefinitionKind rootKind ,
526
546
final Token token ,
527
547
final String indent ,
528
548
final String presentExpression ,
@@ -534,8 +554,20 @@ private void generateRecordPropertyAssignment(
534
554
535
555
sb .append (indent ).append (formattedPropertyName ).append (": " );
536
556
537
- if (token .version () > 0 )
557
+ // N.B., in the IR, the composite information is "embedded" into each message/group field.
558
+ // When we are looking at a composite "field" (i.e., a type) the `token.version()` method
559
+ // returns the "sinceVersion" of the containing field. Therefore, we cannot decide presence
560
+ // based on `token.version()` when dealing with composites.
561
+ if (rootKind .equals (DefinitionKind .Message ) && token .version () > 0 )
538
562
{
563
+ if (token .signal () != Signal .BEGIN_VAR_DATA && !token .isOptionalEncoding ())
564
+ {
565
+ throw new IllegalStateException (
566
+ "Expected added field " + propertyName +
567
+ " (sinceVersion=" + token .version () + ") to have optional presence."
568
+ );
569
+ }
570
+
539
571
sb .append ("codec." ).append (formattedPropertyName ).append ("InActingVersion()" );
540
572
541
573
if (null != nullCodecValueOrNull )
@@ -553,7 +585,7 @@ private void generateRecordPropertyAssignment(
553
585
}
554
586
}
555
587
556
- private void generateEncodeInto (
588
+ private void generateMessageEncodeInto (
557
589
final StringBuilder sb ,
558
590
final String codecClassName ,
559
591
final List <Token > fields ,
@@ -674,7 +706,7 @@ private String nullableConvertedExpression(
674
706
final String expression ,
675
707
final String nullValue )
676
708
{
677
- return fieldToken .version () > 0 || fieldToken . isOptionalEncoding () ?
709
+ return fieldToken .isOptionalEncoding () ?
678
710
expression + " ?? " + nullValue :
679
711
expression ;
680
712
}
@@ -791,9 +823,19 @@ private void generateVarDataEncodeInto(
791
823
if (token .signal () == Signal .BEGIN_VAR_DATA )
792
824
{
793
825
final String propertyName = token .name ();
826
+ final String formattedPropertyName = formatPropertyName (propertyName );
827
+
828
+ if (token .version () > 0 )
829
+ {
830
+ sb .append (indent ).append ("if (null == " ).append (formattedPropertyName ).append (")\n " )
831
+ .append (indent ).append ("{\n " )
832
+ .append (indent ).append (INDENT ).append ("throw new System.InvalidOperationException(\" " )
833
+ .append (formattedPropertyName ).append (" must not be null.\" );\n " )
834
+ .append (indent ).append ("}\n \n " );
835
+ }
794
836
795
- sb .append (indent ).append ("codec.Set" ).append (formatPropertyName ( propertyName ) )
796
- .append ("(" ).append (formatPropertyName ( propertyName ) ).append (");\n " );
837
+ sb .append (indent ).append ("codec.Set" ).append (formattedPropertyName )
838
+ .append ("(" ).append (formattedPropertyName ).append (");\n " );
797
839
}
798
840
}
799
841
}
@@ -1181,7 +1223,8 @@ private void generateVarData(
1181
1223
final String propertyName = token .name ();
1182
1224
final Token varDataToken = Generators .findFirst ("varData" , tokens , i );
1183
1225
final String characterEncoding = varDataToken .encoding ().characterEncoding ();
1184
- final String dtoType = characterEncoding == null ? "byte[]" : "string" ;
1226
+ final String nullableSuffix = token .version () > 0 ? "?" : "" ;
1227
+ final String dtoType = (characterEncoding == null ? "byte[]" : "string" ) + nullableSuffix ;
1185
1228
1186
1229
final String formattedPropertyName = formatPropertyName (propertyName );
1187
1230
0 commit comments