| Index: mojom/mojom_tool/mojom/mojom_descriptor.go
|
| diff --git a/mojom/mojom_tool/mojom/mojom_descriptor.go b/mojom/mojom_tool/mojom/mojom_descriptor.go
|
| index cedad88197f72d83d95dc3432376a206172f19d3..923b98f013914b9b9dd959c3e0d4aa9f68d7bc68 100644
|
| --- a/mojom/mojom_tool/mojom/mojom_descriptor.go
|
| +++ b/mojom/mojom_tool/mojom/mojom_descriptor.go
|
| @@ -8,6 +8,7 @@ import (
|
| "bytes"
|
| "fmt"
|
| "mojom/mojom_tool/lexer"
|
| + "sort"
|
| "strings"
|
| )
|
|
|
| @@ -306,6 +307,9 @@ type MojomDescriptor struct {
|
| // there are unresolved references in the .mojom files.
|
| unresolvedTypeReferences []*UserTypeRef
|
| unresolvedValueReferences []*UserValueRef
|
| +
|
| + // In testing mode we iterate through some maps in deterministic order.
|
| + testingMode bool
|
| }
|
|
|
| func NewMojomDescriptor() *MojomDescriptor {
|
| @@ -324,6 +328,13 @@ func NewMojomDescriptor() *MojomDescriptor {
|
| return descriptor
|
| }
|
|
|
| +// SetTestingMode is used to enable or disable testing mode. It is disabled by
|
| +// default. In testing mode some operations will iterate through maps in a
|
| +// deterministic order. This is less performant but enables deterministic testing.
|
| +func (d *MojomDescriptor) SetTestingMode(testingMode bool) {
|
| + d.testingMode = testingMode
|
| +}
|
| +
|
| func (d *MojomDescriptor) getAbstractModuleScope(fullyQualifiedName string) *Scope {
|
| if scope, ok := d.abstractScopesByName[fullyQualifiedName]; ok {
|
| return scope
|
| @@ -361,6 +372,41 @@ func (d *MojomDescriptor) ContainsFile(fileName string) bool {
|
| return ok
|
| }
|
|
|
| +// DetectIllFoundedTypes() should be invoked after Resolve() has completed
|
| +// successfully. It performs an analysis of the type graph in order to detect
|
| +// ill-founded types. An ill-founded type is one for which it is impossible
|
| +// to create an instance that would be legally serializable using Mojo
|
| +// serialization. This method returns a non-nil error just in case an
|
| +// ill-founded type is detected. The contained error message is appropriate
|
| +// for display to an end-user.
|
| +//
|
| +// An example of an ill-founded type is a struct |Foo| with a field whose type
|
| +// is a non-nullable Foo. Thus ill-foundedness may be due to a cycle in the
|
| +// type graph. But not all cycles cause ill-foundedness. Firstly nullable
|
| +// fields do not lead to ill-foundedness as the potential cycle can be broken
|
| +// by setting the field to null. Also the situation with unions is more complicated:
|
| +// Type graphs involving unions are only ill-founded if every possible way of
|
| +// chosing a value for all of the unions still leads to an unbreakable cycle.
|
| +func (d *MojomDescriptor) DetectIllFoundedTypes() error {
|
| + // We capture the keys of the map TypesByKey in a list and iterate over that list
|
| + // rather than iterating over the map. This is so that in testing mode
|
| + // we can first sort the list so as to iterate in a deterministic order.
|
| + keyList := make([]string, 0, len(d.TypesByKey))
|
| + for key, _ := range d.TypesByKey {
|
| + keyList = append(keyList, key)
|
| + }
|
| + if d.testingMode {
|
| + sort.Strings(keyList)
|
| + }
|
| + for _, key := range keyList {
|
| + udt := d.TypesByKey[key]
|
| + if err := udt.CheckWellFounded(); err != nil {
|
| + return err
|
| + }
|
| + }
|
| + return nil
|
| +}
|
| +
|
| /////////////////////////////////////////
|
| /// Type and Value Resolution
|
| ////////////////////////////////////////
|
|
|