| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 1 | // Copyright 2015 Google Inc. All rights reserved. | 
 | 2 | // | 
 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 4 | // you may not use this file except in compliance with the License. | 
 | 5 | // You may obtain a copy of the License at | 
 | 6 | // | 
 | 7 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
 | 8 | // | 
 | 9 | // Unless required by applicable law or agreed to in writing, software | 
 | 10 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 12 | // See the License for the specific language governing permissions and | 
 | 13 | // limitations under the License. | 
 | 14 |  | 
| Colin Cross | 635c3b0 | 2016-05-18 15:37:25 -0700 | [diff] [blame] | 15 | package android | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 16 |  | 
 | 17 | import ( | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 18 | 	"reflect" | 
 | 19 |  | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 20 | 	"github.com/google/blueprint" | 
 | 21 | 	"github.com/google/blueprint/proptools" | 
 | 22 | ) | 
 | 23 |  | 
| Colin Cross | c99deeb | 2016-04-11 15:06:20 -0700 | [diff] [blame] | 24 | type defaultsDependencyTag struct { | 
 | 25 | 	blueprint.BaseDependencyTag | 
 | 26 | } | 
 | 27 |  | 
 | 28 | var DefaultsDepTag defaultsDependencyTag | 
 | 29 |  | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 30 | type defaultsProperties struct { | 
 | 31 | 	Defaults []string | 
 | 32 | } | 
 | 33 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 34 | type DefaultableModuleBase struct { | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 35 | 	defaultsProperties            defaultsProperties | 
 | 36 | 	defaultableProperties         []interface{} | 
 | 37 | 	defaultableVariableProperties interface{} | 
| Paul Duffin | afa9fa1 | 2020-04-29 16:47:28 +0100 | [diff] [blame] | 38 |  | 
 | 39 | 	// The optional hook to call after any defaults have been applied. | 
 | 40 | 	hook DefaultableHook | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 41 | } | 
 | 42 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 43 | func (d *DefaultableModuleBase) defaults() *defaultsProperties { | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 44 | 	return &d.defaultsProperties | 
 | 45 | } | 
 | 46 |  | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 47 | func (d *DefaultableModuleBase) setProperties(props []interface{}, variableProperties interface{}) { | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 48 | 	d.defaultableProperties = props | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 49 | 	d.defaultableVariableProperties = variableProperties | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 50 | } | 
 | 51 |  | 
| Paul Duffin | afa9fa1 | 2020-04-29 16:47:28 +0100 | [diff] [blame] | 52 | func (d *DefaultableModuleBase) SetDefaultableHook(hook DefaultableHook) { | 
 | 53 | 	d.hook = hook | 
 | 54 | } | 
 | 55 |  | 
 | 56 | func (d *DefaultableModuleBase) callHookIfAvailable(ctx DefaultableHookContext) { | 
 | 57 | 	if d.hook != nil { | 
 | 58 | 		d.hook(ctx) | 
 | 59 | 	} | 
 | 60 | } | 
 | 61 |  | 
| Paul Duffin | 7df7fb0 | 2019-07-24 12:26:14 +0100 | [diff] [blame] | 62 | // Interface that must be supported by any module to which defaults can be applied. | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 63 | type Defaultable interface { | 
| Paul Duffin | 7df7fb0 | 2019-07-24 12:26:14 +0100 | [diff] [blame] | 64 | 	// Get a pointer to the struct containing the Defaults property. | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 65 | 	defaults() *defaultsProperties | 
| Paul Duffin | 7df7fb0 | 2019-07-24 12:26:14 +0100 | [diff] [blame] | 66 |  | 
 | 67 | 	// Set the property structures into which defaults will be added. | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 68 | 	setProperties(props []interface{}, variableProperties interface{}) | 
| Paul Duffin | 7df7fb0 | 2019-07-24 12:26:14 +0100 | [diff] [blame] | 69 |  | 
 | 70 | 	// Apply defaults from the supplied Defaults to the property structures supplied to | 
 | 71 | 	// setProperties(...). | 
| Colin Cross | 1317701 | 2016-08-09 12:00:45 -0700 | [diff] [blame] | 72 | 	applyDefaults(TopDownMutatorContext, []Defaults) | 
| Paul Duffin | afa9fa1 | 2020-04-29 16:47:28 +0100 | [diff] [blame] | 73 |  | 
 | 74 | 	// Set the hook to be called after any defaults have been applied. | 
 | 75 | 	// | 
 | 76 | 	// Should be used in preference to a AddLoadHook when the behavior of the load | 
 | 77 | 	// hook is dependent on properties supplied in the Android.bp file. | 
 | 78 | 	SetDefaultableHook(hook DefaultableHook) | 
 | 79 |  | 
 | 80 | 	// Call the hook if specified. | 
 | 81 | 	callHookIfAvailable(context DefaultableHookContext) | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 82 | } | 
 | 83 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 84 | type DefaultableModule interface { | 
 | 85 | 	Module | 
 | 86 | 	Defaultable | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 87 | } | 
 | 88 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 89 | var _ Defaultable = (*DefaultableModuleBase)(nil) | 
 | 90 |  | 
 | 91 | func InitDefaultableModule(module DefaultableModule) { | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 92 | 	if module.(Module).base().module == nil { | 
 | 93 | 		panic("InitAndroidModule must be called before InitDefaultableModule") | 
 | 94 | 	} | 
 | 95 | 	module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties) | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 96 |  | 
 | 97 | 	module.AddProperties(module.defaults()) | 
| Liz Kammer | dbd4809 | 2020-09-21 22:24:17 +0000 | [diff] [blame] | 98 |  | 
 | 99 | 	module.base().customizableProperties = module.GetProperties() | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 100 | } | 
 | 101 |  | 
| Paul Duffin | afa9fa1 | 2020-04-29 16:47:28 +0100 | [diff] [blame] | 102 | // A restricted subset of context methods, similar to LoadHookContext. | 
 | 103 | type DefaultableHookContext interface { | 
 | 104 | 	EarlyModuleContext | 
 | 105 |  | 
 | 106 | 	CreateModule(ModuleFactory, ...interface{}) Module | 
 | 107 | } | 
 | 108 |  | 
 | 109 | type DefaultableHook func(ctx DefaultableHookContext) | 
 | 110 |  | 
| Paul Duffin | 95d53b5 | 2019-07-24 13:45:05 +0100 | [diff] [blame] | 111 | // The Defaults_visibility property. | 
 | 112 | type DefaultsVisibilityProperties struct { | 
 | 113 |  | 
 | 114 | 	// Controls the visibility of the defaults module itself. | 
 | 115 | 	Defaults_visibility []string | 
 | 116 | } | 
 | 117 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 118 | type DefaultsModuleBase struct { | 
 | 119 | 	DefaultableModuleBase | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 120 | } | 
 | 121 |  | 
| Martin Stjernholm | ebd757d | 2019-05-24 11:00:30 +0100 | [diff] [blame] | 122 | // The common pattern for defaults modules is to register separate instances of | 
 | 123 | // the xxxProperties structs in the AddProperties calls, rather than reusing the | 
 | 124 | // ones inherited from Module. | 
 | 125 | // | 
 | 126 | // The effect is that e.g. myDefaultsModuleInstance.base().xxxProperties won't | 
 | 127 | // contain the values that have been set for the defaults module. Rather, to | 
 | 128 | // retrieve the values it is necessary to iterate over properties(). E.g. to get | 
 | 129 | // the commonProperties instance that have the real values: | 
 | 130 | // | 
 | 131 | //   d := myModule.(Defaults) | 
 | 132 | //   for _, props := range d.properties() { | 
 | 133 | //     if cp, ok := props.(*commonProperties); ok { | 
 | 134 | //       ... access property values in cp ... | 
 | 135 | //     } | 
 | 136 | //   } | 
 | 137 | // | 
 | 138 | // The rationale is that the properties on a defaults module apply to the | 
 | 139 | // defaultable modules using it, not to the defaults module itself. E.g. setting | 
 | 140 | // the "enabled" property false makes inheriting modules disabled by default, | 
 | 141 | // rather than disabling the defaults module itself. | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 142 | type Defaults interface { | 
| Colin Cross | e7b0713 | 2016-07-27 10:15:06 -0700 | [diff] [blame] | 143 | 	Defaultable | 
| Paul Duffin | 7df7fb0 | 2019-07-24 12:26:14 +0100 | [diff] [blame] | 144 |  | 
 | 145 | 	// Although this function is unused it is actually needed to ensure that only modules that embed | 
 | 146 | 	// DefaultsModuleBase will type-assert to the Defaults interface. | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 147 | 	isDefaults() bool | 
| Paul Duffin | 7df7fb0 | 2019-07-24 12:26:14 +0100 | [diff] [blame] | 148 |  | 
 | 149 | 	// Get the structures containing the properties for which defaults can be provided. | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 150 | 	properties() []interface{} | 
| Paul Duffin | 63c6e18 | 2019-07-24 14:24:38 +0100 | [diff] [blame] | 151 |  | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 152 | 	productVariableProperties() interface{} | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 153 | } | 
 | 154 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 155 | func (d *DefaultsModuleBase) isDefaults() bool { | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 156 | 	return true | 
 | 157 | } | 
 | 158 |  | 
| Paul Duffin | e62432f | 2019-07-24 12:51:21 +0100 | [diff] [blame] | 159 | type DefaultsModule interface { | 
 | 160 | 	Module | 
 | 161 | 	Defaults | 
 | 162 | } | 
 | 163 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 164 | func (d *DefaultsModuleBase) properties() []interface{} { | 
| Colin Cross | e7b0713 | 2016-07-27 10:15:06 -0700 | [diff] [blame] | 165 | 	return d.defaultableProperties | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 166 | } | 
 | 167 |  | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 168 | func (d *DefaultsModuleBase) productVariableProperties() interface{} { | 
 | 169 | 	return d.defaultableVariableProperties | 
 | 170 | } | 
 | 171 |  | 
| Colin Cross | 5903762 | 2019-06-10 13:12:56 -0700 | [diff] [blame] | 172 | func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) { | 
 | 173 | } | 
 | 174 |  | 
| Paul Duffin | e62432f | 2019-07-24 12:51:21 +0100 | [diff] [blame] | 175 | func InitDefaultsModule(module DefaultsModule) { | 
| Paul Duffin | 3f98d14 | 2020-09-02 13:28:25 +0100 | [diff] [blame] | 176 | 	commonProperties := &commonProperties{} | 
| Paul Duffin | 63c6e18 | 2019-07-24 14:24:38 +0100 | [diff] [blame] | 177 |  | 
| Colin Cross | 3624285 | 2017-06-23 15:06:31 -0700 | [diff] [blame] | 178 | 	module.AddProperties( | 
| Colin Cross | fc75458 | 2016-05-17 16:34:16 -0700 | [diff] [blame] | 179 | 		&hostAndDeviceProperties{}, | 
| Paul Duffin | 63c6e18 | 2019-07-24 14:24:38 +0100 | [diff] [blame] | 180 | 		commonProperties, | 
| Paul Duffin | ed87513 | 2020-09-02 13:08:57 +0100 | [diff] [blame] | 181 | 		&ApexProperties{}, | 
 | 182 | 		&distProperties{}) | 
| Colin Cross | fc75458 | 2016-05-17 16:34:16 -0700 | [diff] [blame] | 183 |  | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 184 | 	initAndroidModuleBase(module) | 
 | 185 | 	initProductVariableModule(module) | 
| Colin Cross | a684540 | 2020-11-16 15:08:19 -0800 | [diff] [blame] | 186 | 	initArchModule(module) | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 187 | 	InitDefaultableModule(module) | 
| Colin Cross | fc75458 | 2016-05-17 16:34:16 -0700 | [diff] [blame] | 188 |  | 
| Paul Duffin | 7df7fb0 | 2019-07-24 12:26:14 +0100 | [diff] [blame] | 189 | 	// Add properties that will not have defaults applied to them. | 
| Colin Cross | 08d6f8f | 2020-11-19 02:33:19 +0000 | [diff] [blame] | 190 | 	base := module.base() | 
| Paul Duffin | 3f98d14 | 2020-09-02 13:28:25 +0100 | [diff] [blame] | 191 | 	defaultsVisibility := &DefaultsVisibilityProperties{} | 
| Paul Duffin | 95d53b5 | 2019-07-24 13:45:05 +0100 | [diff] [blame] | 192 | 	module.AddProperties(&base.nameProperties, defaultsVisibility) | 
| Colin Cross | fc75458 | 2016-05-17 16:34:16 -0700 | [diff] [blame] | 193 |  | 
| Paul Duffin | 63c6e18 | 2019-07-24 14:24:38 +0100 | [diff] [blame] | 194 | 	// Unlike non-defaults modules the visibility property is not stored in m.base().commonProperties. | 
| Paul Duffin | 5ec73ec | 2020-05-01 17:52:01 +0100 | [diff] [blame] | 195 | 	// Instead it is stored in a separate instance of commonProperties created above so clear the | 
 | 196 | 	// existing list of properties. | 
 | 197 | 	clearVisibilityProperties(module) | 
 | 198 |  | 
 | 199 | 	// The defaults_visibility property controls the visibility of a defaults module so it must be | 
 | 200 | 	// set as the primary property, which also adds it to the list. | 
 | 201 | 	setPrimaryVisibilityProperty(module, "defaults_visibility", &defaultsVisibility.Defaults_visibility) | 
 | 202 |  | 
| Paul Duffin | 63c6e18 | 2019-07-24 14:24:38 +0100 | [diff] [blame] | 203 | 	// The visibility property needs to be checked (but not parsed) by the visibility module during | 
| Paul Duffin | 5ec73ec | 2020-05-01 17:52:01 +0100 | [diff] [blame] | 204 | 	// its checking phase and parsing phase so add it to the list as a normal property. | 
 | 205 | 	AddVisibilityProperty(module, "visibility", &commonProperties.Visibility) | 
| Paul Duffin | 63c6e18 | 2019-07-24 14:24:38 +0100 | [diff] [blame] | 206 |  | 
| Bob Badour | 37af046 | 2021-01-07 03:34:31 +0000 | [diff] [blame] | 207 | 	// The applicable licenses property for defaults is 'licenses'. | 
 | 208 | 	setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses) | 
 | 209 |  | 
| Paul Duffin | 63c6e18 | 2019-07-24 14:24:38 +0100 | [diff] [blame] | 210 | 	base.module = module | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 211 | } | 
 | 212 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 213 | var _ Defaults = (*DefaultsModuleBase)(nil) | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 214 |  | 
| Colin Cross | 1f44a3a | 2017-07-07 14:33:33 -0700 | [diff] [blame] | 215 | func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext, | 
| Colin Cross | 1317701 | 2016-08-09 12:00:45 -0700 | [diff] [blame] | 216 | 	defaultsList []Defaults) { | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 217 |  | 
| Colin Cross | 1317701 | 2016-08-09 12:00:45 -0700 | [diff] [blame] | 218 | 	for _, defaults := range defaultsList { | 
 | 219 | 		for _, prop := range defaultable.defaultableProperties { | 
| Colin Cross | eabaedd | 2020-02-06 17:01:55 -0800 | [diff] [blame] | 220 | 			if prop == defaultable.defaultableVariableProperties { | 
 | 221 | 				defaultable.applyDefaultVariableProperties(ctx, defaults, prop) | 
 | 222 | 			} else { | 
 | 223 | 				defaultable.applyDefaultProperties(ctx, defaults, prop) | 
 | 224 | 			} | 
 | 225 | 		} | 
 | 226 | 	} | 
 | 227 | } | 
 | 228 |  | 
 | 229 | // Product variable properties need special handling, the type of the filtered product variable | 
 | 230 | // property struct may not be identical between the defaults module and the defaultable module. | 
 | 231 | // Use PrependMatchingProperties to apply whichever properties match. | 
 | 232 | func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext, | 
 | 233 | 	defaults Defaults, defaultableProp interface{}) { | 
 | 234 | 	if defaultableProp == nil { | 
 | 235 | 		return | 
 | 236 | 	} | 
 | 237 |  | 
 | 238 | 	defaultsProp := defaults.productVariableProperties() | 
 | 239 | 	if defaultsProp == nil { | 
 | 240 | 		return | 
 | 241 | 	} | 
 | 242 |  | 
 | 243 | 	dst := []interface{}{ | 
 | 244 | 		defaultableProp, | 
 | 245 | 		// Put an empty copy of the src properties into dst so that properties in src that are not in dst | 
 | 246 | 		// don't cause a "failed to find property to extend" error. | 
 | 247 | 		proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(), | 
 | 248 | 	} | 
 | 249 |  | 
 | 250 | 	err := proptools.PrependMatchingProperties(dst, defaultsProp, nil) | 
 | 251 | 	if err != nil { | 
 | 252 | 		if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { | 
 | 253 | 			ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) | 
 | 254 | 		} else { | 
 | 255 | 			panic(err) | 
 | 256 | 		} | 
 | 257 | 	} | 
 | 258 | } | 
 | 259 |  | 
 | 260 | func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext, | 
 | 261 | 	defaults Defaults, defaultableProp interface{}) { | 
 | 262 |  | 
 | 263 | 	for _, def := range defaults.properties() { | 
 | 264 | 		if proptools.TypeEqual(defaultableProp, def) { | 
 | 265 | 			err := proptools.PrependProperties(defaultableProp, def, nil) | 
 | 266 | 			if err != nil { | 
 | 267 | 				if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { | 
 | 268 | 					ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) | 
 | 269 | 				} else { | 
 | 270 | 					panic(err) | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 271 | 				} | 
 | 272 | 			} | 
 | 273 | 		} | 
 | 274 | 	} | 
 | 275 | } | 
 | 276 |  | 
| Colin Cross | 89536d4 | 2017-07-07 14:35:50 -0700 | [diff] [blame] | 277 | func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) { | 
| Colin Cross | cec8171 | 2017-07-13 14:43:27 -0700 | [diff] [blame] | 278 | 	ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel() | 
 | 279 | 	ctx.TopDown("defaults", defaultsMutator).Parallel() | 
 | 280 | } | 
 | 281 |  | 
| Colin Cross | 635c3b0 | 2016-05-18 15:37:25 -0700 | [diff] [blame] | 282 | func defaultsDepsMutator(ctx BottomUpMutatorContext) { | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 283 | 	if defaultable, ok := ctx.Module().(Defaultable); ok { | 
| Colin Cross | c99deeb | 2016-04-11 15:06:20 -0700 | [diff] [blame] | 284 | 		ctx.AddDependency(ctx.Module(), DefaultsDepTag, defaultable.defaults().Defaults...) | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 285 | 	} | 
 | 286 | } | 
 | 287 |  | 
| Colin Cross | 1317701 | 2016-08-09 12:00:45 -0700 | [diff] [blame] | 288 | func defaultsMutator(ctx TopDownMutatorContext) { | 
| Paul Duffin | afa9fa1 | 2020-04-29 16:47:28 +0100 | [diff] [blame] | 289 | 	if defaultable, ok := ctx.Module().(Defaultable); ok { | 
 | 290 | 		if len(defaultable.defaults().Defaults) > 0 { | 
 | 291 | 			var defaultsList []Defaults | 
 | 292 | 			seen := make(map[Defaults]bool) | 
| Colin Cross | a1ce2a0 | 2018-06-20 15:19:39 -0700 | [diff] [blame] | 293 |  | 
| Paul Duffin | afa9fa1 | 2020-04-29 16:47:28 +0100 | [diff] [blame] | 294 | 			ctx.WalkDeps(func(module, parent Module) bool { | 
 | 295 | 				if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag { | 
 | 296 | 					if defaults, ok := module.(Defaults); ok { | 
 | 297 | 						if !seen[defaults] { | 
 | 298 | 							seen[defaults] = true | 
 | 299 | 							defaultsList = append(defaultsList, defaults) | 
 | 300 | 							return len(defaults.defaults().Defaults) > 0 | 
 | 301 | 						} | 
 | 302 | 					} else { | 
 | 303 | 						ctx.PropertyErrorf("defaults", "module %s is not an defaults module", | 
 | 304 | 							ctx.OtherModuleName(module)) | 
| Colin Cross | a1ce2a0 | 2018-06-20 15:19:39 -0700 | [diff] [blame] | 305 | 					} | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 306 | 				} | 
| Paul Duffin | afa9fa1 | 2020-04-29 16:47:28 +0100 | [diff] [blame] | 307 | 				return false | 
 | 308 | 			}) | 
 | 309 | 			defaultable.applyDefaults(ctx, defaultsList) | 
 | 310 | 		} | 
 | 311 |  | 
 | 312 | 		defaultable.callHookIfAvailable(ctx) | 
| Colin Cross | cfad119 | 2015-11-02 16:43:11 -0800 | [diff] [blame] | 313 | 	} | 
 | 314 | } |