Index: mojom/mojom_parser/mojom/computed_data.go |
diff --git a/mojom/mojom_parser/mojom/computed_data.go b/mojom/mojom_parser/mojom/computed_data.go |
index 1064a6e3dd85d856b0c02dd9b43bfff99642b857..e0a3438666b90e092616db8f82d78a5110d068d3 100644 |
--- a/mojom/mojom_parser/mojom/computed_data.go |
+++ b/mojom/mojom_parser/mojom/computed_data.go |
@@ -6,7 +6,9 @@ package mojom |
import ( |
"container/list" |
+ "errors" |
"fmt" |
+ "mojom/mojom_parser/lexer" |
"mojom/mojom_parser/utils" |
) |
@@ -125,6 +127,69 @@ func isBoolField(field *StructField) bool { |
return false |
} |
+var ErrMinVersionIllformed = errors.New("MinVersion attribute value illformed") |
+var ErrMinVersionOutOfOrder = errors.New("MinVersion attribute value out of order") |
+var ErrMinVersionNotNullable = errors.New("Non-Zero MinVersion attribute value on non-nullable field") |
+ |
+type StructFieldMinVersionError struct { |
+ // The field whose MinVersion is being set. |
+ field *StructField |
+ |
+ // The MinValue of the previous field. Only used for ErrMinVersionOutOfOrder |
+ previousValue uint32 |
+ |
+ // The LiteralValue of the attribute assignment. |
+ // NOTE: We use the following convention: literalValue.token == nil indicates that |
+ // there was no MinVersion attribute on the given field. This can only happen with |
+ // ErrMinVersionOutOfOrder |
+ literalValue LiteralValue |
+ |
+ // The type of error (ErrMinVersionIllfromed, ErrMinVersionOutOfOrder, ErrMinVersionNotNullable) |
+ err error |
+} |
+ |
+// StructFieldMinVersionError implements error. |
+func (e *StructFieldMinVersionError) Error() string { |
+ var message string |
+ var token lexer.Token |
+ switch e.err { |
+ case ErrMinVersionIllformed: |
+ message = fmt.Sprintf("Invalid MinVersion attribute for field %s: %s. "+ |
+ "The value must be a non-negative 32-bit integer value.", |
+ e.field.SimpleName(), e.literalValue) |
+ token = *e.literalValue.token |
+ case ErrMinVersionOutOfOrder: |
+ if e.literalValue.token == nil { |
+ message = fmt.Sprintf("Invalid missing MinVersion for field %s. "+ |
+ "The MinVersion must be non-decreasing as a function of the ordinal. "+ |
+ "This field must have a MinVersion attribute with a value at least %d.", |
+ e.field.SimpleName(), e.previousValue) |
+ token = e.field.NameToken() |
+ } else { |
+ message = fmt.Sprintf("Invalid MinVersion attribute for field %s: %s. "+ |
+ "The MinVersion must be non-decreasing as a function of the ordinal. "+ |
+ "This field's MinVersion must be at least %d.", |
+ e.field.SimpleName(), e.literalValue.token.Text, e.previousValue) |
+ token = *e.literalValue.token |
+ } |
+ case ErrMinVersionNotNullable: |
+ message = fmt.Sprintf("Invalid type for field %s: %s. "+ |
+ "Non-nullable reference fields are only allowed in version 0 of of a struct. "+ |
+ "This field's MinVersion is %s.", |
+ e.field.SimpleName(), e.field.FieldType.TypeName(), e.literalValue.token.Text) |
+ switch fieldType := e.field.FieldType.(type) { |
+ case *UserTypeRef: |
+ token = fieldType.token |
+ default: |
+ // It would be nice for the green carets in the snippit in the error message to point at |
+ // the type name, but other than for user type refs we don't store that token so |
+ // instead we use the field's name. |
+ token = e.field.NameToken() |
+ } |
+ } |
+ return UserErrorMessage(e.field.OwningFile(), token, message) |
+} |
+ |
// computeVersionInfo is invoked by ComputeFinalData() after the |
// computeFieldOffsets(). It examines the |MinVersion| |
// attributes of all of the fields of the struct, validates the values, and |
@@ -165,7 +230,7 @@ func (s *MojomStruct) computeVersionInfo() error { |
} |
} |
} |
- if value != 0 && !field.FieldType.Nullable() { |
+ if value != 0 && !field.FieldType.AllowedInNonZeroStructVersion() { |
return &StructFieldMinVersionError{ |
field: field, |
literalValue: literalValue, |