@@ -308,7 +308,7 @@ public void exitBatchSetDefinition(MSpecParser.BatchSetDefinitionContext ctx) {
308308 @ Override
309309 public void enterAbstractField (MSpecParser .AbstractFieldContext ctx ) {
310310 var name = getIdString (ctx .name );
311- var field = new DefaultAbstractField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , consumePendingComment (ctx ));
311+ var field = new DefaultAbstractField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , consumePendingComment (ctx ));
312312 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
313313 if (throwable != null ) {
314314 // TODO: proper error collection in type context error bucket
@@ -327,7 +327,7 @@ public void enterArrayField(MSpecParser.ArrayFieldContext ctx) {
327327 var name = getIdString (ctx .name );
328328 var loopType = ArrayField .LoopType .valueOf (ctx .loopType .getText ().toUpperCase ());
329329 var loopExpression = getExpressionTerm (ctx .loopExpression );
330- var field = new DefaultArrayField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , loopType , loopExpression , consumePendingComment (ctx ));
330+ var field = new DefaultArrayField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , loopType , loopExpression , consumePendingComment (ctx ));
331331 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
332332 if (throwable != null ) {
333333 // TODO: proper error collection in type context error bucket
@@ -345,7 +345,7 @@ public void enterArrayField(MSpecParser.ArrayFieldContext ctx) {
345345 public void enterAssertField (MSpecParser .AssertFieldContext ctx ) {
346346 var name = getIdString (ctx .name );
347347 var conditionExpression = getExpressionTerm (ctx .condition );
348- var field = new DefaultAssertField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , conditionExpression , consumePendingComment (ctx ));
348+ var field = new DefaultAssertField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , conditionExpression , consumePendingComment (ctx ));
349349 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
350350 if (throwable != null ) {
351351 // TODO: proper error collection in type context error bucket
@@ -364,7 +364,7 @@ public void enterChecksumField(MSpecParser.ChecksumFieldContext ctx) {
364364 var type = getSimpleTypeReference (ctx .type );
365365 var name = getIdString (ctx .name );
366366 var checksumExpression = getExpressionTerm (ctx .checksumExpression );
367- var field = new DefaultChecksumField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , name , checksumExpression , consumePendingComment (ctx ));
367+ var field = new DefaultChecksumField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , name , checksumExpression , consumePendingComment (ctx ));
368368 if (parserContexts .peek () != null ) {
369369 parserContexts .peek ().add (field );
370370 }
@@ -373,7 +373,7 @@ public void enterChecksumField(MSpecParser.ChecksumFieldContext ctx) {
373373 @ Override
374374 public void enterConstField (MSpecParser .ConstFieldContext ctx ) {
375375 var name = getIdString (ctx .name );
376- var field = new DefaultConstField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , getValueLiteral (ctx .expected ), consumePendingComment (ctx ));
376+ var field = new DefaultConstField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , getValueLiteral (ctx .expected ), consumePendingComment (ctx ));
377377 if (ctx .type .dataType () != null ) {
378378 field .setType (getSimpleTypeReference (ctx .type .dataType ()));
379379 } else {
@@ -394,7 +394,7 @@ public void enterConstField(MSpecParser.ConstFieldContext ctx) {
394394 @ Override
395395 public void enterDiscriminatorField (MSpecParser .DiscriminatorFieldContext ctx ) {
396396 var name = getIdString (ctx .name );
397- var field = new DefaultDiscriminatorField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , consumePendingComment (ctx ));
397+ var field = new DefaultDiscriminatorField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , consumePendingComment (ctx ));
398398 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
399399 if (throwable != null ) {
400400 // TODO: proper error collection in type context error bucket
@@ -418,7 +418,7 @@ public void enterEnumField(MSpecParser.EnumFieldContext ctx) {
418418 if (ctx .fieldName != null ) {
419419 fieldName = getIdString (ctx .fieldName );
420420 }
421- var field = new DefaultEnumField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , name , fieldName , consumePendingComment (ctx ));
421+ var field = new DefaultEnumField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , name , fieldName , consumePendingComment (ctx ));
422422 if (parserContexts .peek () != null ) {
423423 parserContexts .peek ().add (field );
424424 }
@@ -429,7 +429,7 @@ public void enterImplicitField(MSpecParser.ImplicitFieldContext ctx) {
429429 var type = getSimpleTypeReference (ctx .type );
430430 var name = getIdString (ctx .name );
431431 var serializeExpression = getExpressionTerm (ctx .serializeExpression );
432- var field = new DefaultImplicitField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , name , serializeExpression , consumePendingComment (ctx ));
432+ var field = new DefaultImplicitField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , name , serializeExpression , consumePendingComment (ctx ));
433433 if (parserContexts .peek () != null ) {
434434 parserContexts .peek ().add (field );
435435 }
@@ -444,7 +444,7 @@ public void enterManualArrayField(MSpecParser.ManualArrayFieldContext ctx) {
444444 Term parseExpression = getExpressionTerm (ctx .parseExpression );
445445 Term serializeExpression = getExpressionTerm (ctx .serializeExpression );
446446 Term lengthExpression = getExpressionTerm (ctx .lengthExpression );
447- DefaultManualArrayField field = new DefaultManualArrayField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , loopType , loopExpression ,
447+ DefaultManualArrayField field = new DefaultManualArrayField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , loopType , loopExpression ,
448448 parseExpression , serializeExpression , lengthExpression , consumePendingComment (ctx ));
449449 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
450450 if (throwable != null ) {
@@ -465,7 +465,7 @@ public void enterManualField(MSpecParser.ManualFieldContext ctx) {
465465 Term parseExpression = getExpressionTerm (ctx .parseExpression );
466466 Term serializeExpression = getExpressionTerm (ctx .serializeExpression );
467467 Term lengthExpression = getExpressionTerm (ctx .lengthExpression );
468- DefaultManualField field = new DefaultManualField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , parseExpression ,
468+ DefaultManualField field = new DefaultManualField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , parseExpression ,
469469 serializeExpression ,
470470 lengthExpression , consumePendingComment (ctx ));
471471 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
@@ -488,7 +488,7 @@ public void enterOptionalField(MSpecParser.OptionalFieldContext ctx) {
488488 if (ctx .condition != null ) {
489489 conditionExpression = getExpressionTerm (ctx .condition );
490490 }
491- var field = new DefaultOptionalField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , conditionExpression , consumePendingComment (ctx ));
491+ var field = new DefaultOptionalField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , conditionExpression , consumePendingComment (ctx ));
492492 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
493493 if (throwable != null ) {
494494 // TODO: proper error collection in type context error bucket
@@ -508,7 +508,7 @@ public void enterPaddingField(MSpecParser.PaddingFieldContext ctx) {
508508 var name = getIdString (ctx .name );
509509 var paddingValue = getExpressionTerm (ctx .paddingValue );
510510 var timesPadding = getExpressionTerm (ctx .timesPadding );
511- var field = new DefaultPaddingField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , name , paddingValue , timesPadding , consumePendingComment (ctx ));
511+ var field = new DefaultPaddingField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , name , paddingValue , timesPadding , consumePendingComment (ctx ));
512512 if (parserContexts .peek () != null ) {
513513 parserContexts .peek ().add (field );
514514 }
@@ -521,7 +521,7 @@ public void enterPeekField(MSpecParser.PeekFieldContext ctx) {
521521 if (ctx .offset != null ) {
522522 offsetExpression = getExpressionTerm (ctx .offset );
523523 }
524- var field = new DefaultPeekField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , offsetExpression , consumePendingComment (ctx ));
524+ var field = new DefaultPeekField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , offsetExpression , consumePendingComment (ctx ));
525525 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
526526 if (throwable != null ) {
527527 // TODO: proper error collection in type context error bucket
@@ -539,7 +539,7 @@ public void enterPeekField(MSpecParser.PeekFieldContext ctx) {
539539 public void enterReservedField (MSpecParser .ReservedFieldContext ctx ) {
540540 var type = getSimpleTypeReference (ctx .type );
541541 var expected = getExprString (ctx .expected );
542- var field = new DefaultReservedField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , expected , consumePendingComment (ctx ));
542+ var field = new DefaultReservedField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , expected , consumePendingComment (ctx ));
543543 if (parserContexts .peek () != null ) {
544544 parserContexts .peek ().add (field );
545545 }
@@ -548,7 +548,7 @@ public void enterReservedField(MSpecParser.ReservedFieldContext ctx) {
548548 @ Override
549549 public void enterSimpleField (MSpecParser .SimpleFieldContext ctx ) {
550550 var name = getIdString (ctx .name );
551- var field = new DefaultSimpleField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , consumePendingComment (ctx ));
551+ var field = new DefaultSimpleField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , consumePendingComment (ctx ));
552552 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
553553 if (throwable != null ) {
554554 // TODO: proper error collection in type context error bucket
@@ -592,7 +592,7 @@ public void enterStateField(MSpecParser.StateFieldContext ctx) {
592592 () -> new RuntimeException ("state fields must refer to arguments by using the same name." )).type ;
593593 // The variable term is always just a direct reference to the parser argument.
594594 var valueExpression = new DefaultVariableLiteral (name , null , null , null );
595- var field = new DefaultStateField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , valueExpression , consumePendingComment (ctx ));
595+ var field = new DefaultStateField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , valueExpression , consumePendingComment (ctx ));
596596 getTypeReference (type ).whenComplete ((typeReference , throwable ) -> {
597597 if (throwable != null ) {
598598 // TODO: proper error collection in type context error bucket
@@ -611,7 +611,7 @@ public void enterTypeSwitchField(MSpecParser.TypeSwitchFieldContext ctx) {
611611 var variableLiterals = ctx .discriminators .variableLiteral ().stream ()
612612 .map (this ::getVariableLiteral )
613613 .collect (Collectors .toList ());
614- var field = new DefaultSwitchField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), variableLiterals , consumePendingComment (ctx ));
614+ var field = new DefaultSwitchField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), variableLiterals , consumePendingComment (ctx ));
615615 if (parserContexts .peek () != null ) {
616616 parserContexts .peek ().add (field );
617617 }
@@ -620,7 +620,7 @@ public void enterTypeSwitchField(MSpecParser.TypeSwitchFieldContext ctx) {
620620 @ Override
621621 public void enterUnknownField (MSpecParser .UnknownFieldContext ctx ) {
622622 var type = getSimpleTypeReference (ctx .type );
623- var field = new DefaultUnknownField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , consumePendingComment (ctx ));
623+ var field = new DefaultUnknownField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), type , consumePendingComment (ctx ));
624624 if (parserContexts .peek () != null ) {
625625 parserContexts .peek ().add (field );
626626 }
@@ -637,7 +637,7 @@ public void enterValidationField(MSpecParser.ValidationFieldContext ctx) {
637637 if (ctx .description != null ) {
638638 description = ctx .description .getText ();
639639 }
640- var field = new DefaultValidationField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), validationExpression , description , shouldFail , consumePendingComment (ctx ));
640+ var field = new DefaultValidationField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), validationExpression , description , shouldFail , consumePendingComment (ctx ));
641641 if (parserContexts .peek () != null ) {
642642 parserContexts .peek ().add (field );
643643 }
@@ -647,7 +647,7 @@ public void enterValidationField(MSpecParser.ValidationFieldContext ctx) {
647647 public void enterVirtualField (MSpecParser .VirtualFieldContext ctx ) {
648648 var name = getIdString (ctx .name );
649649 var valueExpression = getExpressionTerm (ctx .valueExpression );
650- var field = new DefaultVirtualField (getAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , valueExpression , consumePendingComment (ctx ));
650+ var field = new DefaultVirtualField (getCuratedAttributes (ctx ), getCurFieldAttributeNames (ctx ), name , valueExpression , consumePendingComment (ctx ));
651651 getTypeReference (ctx .type ).whenComplete ((typeReference , throwable ) -> {
652652 if (throwable != null ) {
653653 // TODO: proper error collection in type context error bucket
@@ -1005,6 +1005,41 @@ private Map<String, Term> getAttributes(RuleContext ctx) {
10051005 return attributes ;
10061006 }
10071007
1008+ /**
1009+ * This is a variant of getAttributes, which respects that setting an attribute "encoding"
1010+ * also sets all types of individual encoding.
1011+ * @param ctx current Context
1012+ * @return map of curated attributes
1013+ */
1014+ private Map <String , Term > getCuratedAttributes (ParserRuleContext ctx ) {
1015+ Map <String , Term > attributes = new HashMap <>();
1016+ // Add any attributes from the current batchSet context.
1017+ if (!batchSetAttributes .empty ()) {
1018+ attributes .putAll (batchSetAttributes .peek ());
1019+ }
1020+ // Add any attributes set on the current field itself.
1021+ boolean localGlobalEncoding = false ;
1022+ if (ctx .parent .parent instanceof MSpecParser .FieldDefinitionContext fieldDefinitionContext ) {
1023+ for (MSpecParser .AttributeContext attributeContext : fieldDefinitionContext .attributes .attribute ()) {
1024+ String attributeName = attributeContext .name .getText ();
1025+ Term valueExpression = getExpressionTerm (attributeContext .value );
1026+ if ("encoding" .equalsIgnoreCase (attributeName )) {
1027+ localGlobalEncoding = true ;
1028+ }
1029+ attributes .put (attributeContext .name .getText (), valueExpression );
1030+ }
1031+ }
1032+ // If the attribute's name is "encoding", ensure it overrides all sub-encodings.
1033+ if (localGlobalEncoding ) {
1034+ Term valueExpression = attributes .get ("encoding" );
1035+ attributes .put ("unsignedIntegerEncoding" , valueExpression );
1036+ attributes .put ("signedIntegerEncoding" , valueExpression );
1037+ attributes .put ("floatEncoding" , valueExpression );
1038+ attributes .put ("stringEncoding" , valueExpression );
1039+ }
1040+ return attributes ;
1041+ }
1042+
10081043 private Set <String > getCurFieldAttributeNames (RuleContext ctx ) {
10091044 Set <String > attributeNames = new HashSet <>();
10101045 if (ctx .parent .parent instanceof MSpecParser .FieldDefinitionContext fieldDefinitionContext ) {
0 commit comments