@@ -1298,7 +1298,7 @@ public Type getType() {
12981298 // (custom options) into unknown fields.
12991299 if (type == Type .MESSAGE
13001300 && this .features != null
1301- && this . features .getMessageEncoding () == FeatureSet .MessageEncoding .DELIMITED ) {
1301+ && getFeatures () .getMessageEncoding () == FeatureSet .MessageEncoding .DELIMITED ) {
13021302 return Type .GROUP ;
13031303 }
13041304 return type ;
@@ -1319,13 +1319,13 @@ public boolean needsUtf8Check() {
13191319 // Always enforce strict UTF-8 checking for map fields.
13201320 return true ;
13211321 }
1322- if (this . features
1322+ if (getFeatures ()
13231323 .getExtension (JavaFeaturesProto .java_ )
13241324 .getUtf8Validation ()
13251325 .equals (JavaFeatures .Utf8Validation .VERIFY )) {
13261326 return true ;
13271327 }
1328- return this . features .getUtf8Validation ().equals (FeatureSet .Utf8Validation .VERIFY );
1328+ return getFeatures () .getUtf8Validation ().equals (FeatureSet .Utf8Validation .VERIFY );
13291329 }
13301330
13311331 public boolean isMapField () {
@@ -1341,14 +1341,14 @@ && isRepeated()
13411341
13421342 /** Is this field declared required? */
13431343 public boolean isRequired () {
1344- return this . features .getFieldPresence ()
1344+ return getFeatures () .getFieldPresence ()
13451345 == DescriptorProtos .FeatureSet .FieldPresence .LEGACY_REQUIRED ;
13461346 }
13471347
13481348 /** Is this field declared optional? */
13491349 public boolean isOptional () {
13501350 return proto .getLabel () == FieldDescriptorProto .Label .LABEL_OPTIONAL
1351- && this . features .getFieldPresence ()
1351+ && getFeatures () .getFieldPresence ()
13521352 != DescriptorProtos .FeatureSet .FieldPresence .LEGACY_REQUIRED ;
13531353 }
13541354
@@ -1367,7 +1367,7 @@ public boolean isPacked() {
13671367 if (!isPackable ()) {
13681368 return false ;
13691369 }
1370- return this . features
1370+ return getFeatures ()
13711371 .getRepeatedFieldEncoding ()
13721372 .equals (FeatureSet .RepeatedFieldEncoding .PACKED );
13731373 }
@@ -1467,7 +1467,7 @@ public boolean hasPresence() {
14671467 || getType () == Type .GROUP
14681468 || isExtension ()
14691469 || getContainingOneof () != null
1470- || this . features .getFieldPresence () != DescriptorProtos .FeatureSet .FieldPresence .IMPLICIT ;
1470+ || getFeatures () .getFieldPresence () != DescriptorProtos .FeatureSet .FieldPresence .IMPLICIT ;
14711471 }
14721472
14731473 /**
@@ -1476,7 +1476,8 @@ public boolean hasPresence() {
14761476 * been upgraded to editions.
14771477 */
14781478 boolean isGroupLike () {
1479- if (features .getMessageEncoding () != DescriptorProtos .FeatureSet .MessageEncoding .DELIMITED ) {
1479+ if (getFeatures ().getMessageEncoding ()
1480+ != DescriptorProtos .FeatureSet .MessageEncoding .DELIMITED ) {
14801481 // Groups are always tag-delimited.
14811482 return false ;
14821483 }
@@ -1577,7 +1578,7 @@ public boolean legacyEnumFieldTreatedAsClosed() {
15771578 }
15781579
15791580 return getType () == Type .ENUM
1580- && (this . features .getExtension (JavaFeaturesProto .java_ ).getLegacyClosedEnum ()
1581+ && (getFeatures () .getExtension (JavaFeaturesProto .java_ ).getLegacyClosedEnum ()
15811582 || enumType .isClosed ());
15821583 }
15831584
@@ -2115,7 +2116,7 @@ public FileDescriptor getFile() {
21152116 * handling quirks.
21162117 */
21172118 public boolean isClosed () {
2118- return this . features .getEnumType () == DescriptorProtos .FeatureSet .EnumType .CLOSED ;
2119+ return getFeatures () .getEnumType () == DescriptorProtos .FeatureSet .EnumType .CLOSED ;
21192120 }
21202121
21212122 /** If this is a nested type, get the outer descriptor, otherwise null. */
@@ -2811,6 +2812,17 @@ boolean hasInferredLegacyProtoFeatures() {
28112812
28122813 void validateFeatures () throws DescriptorValidationException {}
28132814
2815+ FeatureSet getFeatures () {
2816+ // TODO: Remove lazy resolution of unresolved features for legacy syntax for
2817+ // compatibility with older <4.26.x gencode in the next breaking release.
2818+ if (this .features == null
2819+ && (getFile ().getEdition () == Edition .EDITION_PROTO2
2820+ || getFile ().getEdition () == Edition .EDITION_PROTO3 )) {
2821+ getFile ().resolveAllFeaturesImmutable ();
2822+ }
2823+ return this .features ;
2824+ }
2825+
28142826 GenericDescriptor parent ;
28152827 volatile FeatureSet features ;
28162828 }
0 commit comments