Add hook to be called after defaults have been applied

Previously, the only way for a module type to create modules (other
than defining its own mutator) was to register a LoadHook. However,
that is called before defaults are applied so any properties used in
that hook cannot take advantage of defaults, e.g. java_sdk_library
cannot use defaults to set its sdk_version property and have that
affect its child modules.

This change adds a new SetDefaultableHook() to DefaultableModule to
register a hook that is called after any defaults have been applied.

Also adds some tests to ensure that errors in the visibility property
introduced in a DefaultableHook are reported in the gather phase of
visibility processing.

A follow up change will switch java_sdk_library to use that instead
of the AddLoadHook() mechanism.

Bug: 155295806
Test: m checkapi
Change-Id: I13df3115f9e225f7324b6725eaeb16a78cc2538a
This commit is contained in:
Paul Duffin
2020-04-29 16:47:28 +01:00
parent c988c8e202
commit afa9fa104d
4 changed files with 168 additions and 17 deletions

View File

@@ -903,6 +903,69 @@ var visibilityTests = []struct {
}`),
},
},
{
name: "ensure visibility properties are checked for correctness",
fs: map[string][]byte{
"top/Blueprints": []byte(`
mock_parent {
name: "parent",
visibility: ["//top/nested"],
child: {
name: "libchild",
visibility: ["top/other"],
},
}`),
},
expectedErrors: []string{
`module "parent": child.visibility: invalid visibility pattern "top/other"`,
},
},
{
name: "invalid visibility added to child detected during gather phase",
fs: map[string][]byte{
"top/Blueprints": []byte(`
mock_parent {
name: "parent",
visibility: ["//top/nested"],
child: {
name: "libchild",
invalid_visibility: ["top/other"],
},
}`),
},
expectedErrors: []string{
// That this error is reported against the child not the parent shows it was
// not being detected in the parent which is correct as invalid_visibility is
// purposely not added to the list of visibility properties to check, and was
// in fact detected in the child in the gather phase. Contrast this error message
// with the preceding one.
`module "libchild" \(created by module "parent"\): visibility: invalid visibility pattern "top/other"`,
},
},
{
name: "automatic visibility inheritance enabled",
fs: map[string][]byte{
"top/Blueprints": []byte(`
mock_parent {
name: "parent",
visibility: ["//top/nested"],
child: {
name: "libchild",
visibility: ["//top/other"],
},
}`),
"top/nested/Blueprints": []byte(`
mock_library {
name: "libnested",
deps: ["libchild"],
}`),
"top/other/Blueprints": []byte(`
mock_library {
name: "libother",
deps: ["libchild"],
}`),
},
},
}
func TestVisibility(t *testing.T) {
@@ -936,6 +999,7 @@ func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []erro
ctx := NewTestArchContext()
ctx.RegisterModuleType("mock_library", newMockLibraryModule)
ctx.RegisterModuleType("mock_parent", newMockParentFactory)
ctx.RegisterModuleType("mock_defaults", defaultsFactory)
// Order of the following method calls is significant.
@@ -996,3 +1060,42 @@ func defaultsFactory() Module {
InitDefaultsModule(m)
return m
}
type mockParentProperties struct {
Child struct {
Name *string
// Visibility to pass to the child module.
Visibility []string
// Purposely not validated visibility to pass to the child.
Invalid_visibility []string
}
}
type mockParent struct {
ModuleBase
DefaultableModuleBase
properties mockParentProperties
}
func (p *mockParent) GenerateAndroidBuildActions(ModuleContext) {
}
func newMockParentFactory() Module {
m := &mockParent{}
m.AddProperties(&m.properties)
InitAndroidArchModule(m, HostAndDeviceSupported, MultilibCommon)
InitDefaultableModule(m)
AddVisibilityProperty(m, "child.visibility", &m.properties.Child.Visibility)
m.SetDefaultableHook(func(ctx DefaultableHookContext) {
visibility := m.properties.Child.Visibility
visibility = append(visibility, m.properties.Child.Invalid_visibility...)
ctx.CreateModule(newMockLibraryModule, &struct {
Name *string
Visibility []string
}{m.properties.Child.Name, visibility})
})
return m
}