Only instantiate nil struct pointers that are used
unpackProperties was instantiating all nil struct pointers in any struct that had a property set. Check if the property is set first, and only instantiate the struct if it was set. This has a slight behavioral change, as now structures that only exist through nil pointers and are never set into will not be type-checked. This should be fixed in a later patch set that moves the type checking to be done across all property structs once per factory before blueprint files are loaded. Change-Id: I0dea34d7fff76bb4fc907516a2d996e4ea2408d6
This commit is contained in:
parent
fd1ef9ec7a
commit
a437135876
1 changed files with 10 additions and 4 deletions
14
unpack.go
14
unpack.go
|
@ -139,10 +139,15 @@ func unpackStructValue(namePrefix string, structValue reflect.Value,
|
||||||
panic(fmt.Errorf("field %s is not settable", propertyName))
|
panic(fmt.Errorf("field %s is not settable", propertyName))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the property value if it was specified.
|
||||||
|
packedProperty, propertyIsSet := propertyMap[propertyName]
|
||||||
|
|
||||||
origFieldValue := fieldValue
|
origFieldValue := fieldValue
|
||||||
|
|
||||||
// To make testing easier we validate the struct field's type regardless
|
// To make testing easier we validate the struct field's type regardless
|
||||||
// of whether or not the property was specified in the parsed string.
|
// of whether or not the property was specified in the parsed string.
|
||||||
|
// TODO(ccross): we don't validate types inside nil struct pointers
|
||||||
|
// Move type validation to a function that runs on each factory once
|
||||||
switch kind := fieldValue.Kind(); kind {
|
switch kind := fieldValue.Kind(); kind {
|
||||||
case reflect.Bool, reflect.String, reflect.Struct:
|
case reflect.Bool, reflect.String, reflect.Struct:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
|
@ -164,7 +169,10 @@ func unpackStructValue(namePrefix string, structValue reflect.Value,
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
switch ptrKind := fieldValue.Type().Elem().Kind(); ptrKind {
|
switch ptrKind := fieldValue.Type().Elem().Kind(); ptrKind {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if fieldValue.IsNil() {
|
if fieldValue.IsNil() && (propertyIsSet || field.Anonymous) {
|
||||||
|
// Instantiate nil struct pointers
|
||||||
|
// Set into origFieldValue in case it was an interface, in which case
|
||||||
|
// fieldValue points to the unsettable pointer inside the interface
|
||||||
fieldValue = reflect.New(fieldValue.Type().Elem())
|
fieldValue = reflect.New(fieldValue.Type().Elem())
|
||||||
origFieldValue.Set(fieldValue)
|
origFieldValue.Set(fieldValue)
|
||||||
}
|
}
|
||||||
|
@ -190,9 +198,7 @@ func unpackStructValue(namePrefix string, structValue reflect.Value,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the property value if it was specified.
|
if !propertyIsSet {
|
||||||
packedProperty, ok := propertyMap[propertyName]
|
|
||||||
if !ok {
|
|
||||||
// This property wasn't specified.
|
// This property wasn't specified.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue