bp2build: Refactor CreateBazelTargetModule API.

This CL refactors the CreateBazelTargetModule API to minimize boilerplate, and to establish a well defined function signature for the expected metadata about a BazelTargetModule.

Test: soong tests

Test: TH
Change-Id: I474ff5a2b0db8deeed49ba4ca73b416ccb494fdd
diff --git a/android/filegroup.go b/android/filegroup.go
index 7a6cc4f..b36238c 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -17,8 +17,6 @@
 import (
 	"android/soong/bazel"
 	"strings"
-
-	"github.com/google/blueprint/proptools"
 )
 
 func init() {
@@ -28,7 +26,6 @@
 
 // https://docs.bazel.build/versions/master/be/general.html#filegroup
 type bazelFilegroupAttributes struct {
-	Name *string
 	Srcs bazel.LabelList
 }
 
@@ -50,20 +47,23 @@
 
 func (bfg *bazelFilegroup) GenerateAndroidBuildActions(ctx ModuleContext) {}
 
-// TODO: Create helper functions to avoid this boilerplate.
 func FilegroupBp2Build(ctx TopDownMutatorContext) {
 	fg, ok := ctx.Module().(*fileGroup)
 	if !ok {
 		return
 	}
-
-	name := "__bp2build__" + fg.base().BaseModuleName()
-	ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
-		Name: proptools.StringPtr(name),
+	attrs := &bazelFilegroupAttributes{
 		Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs),
-	}, &bazel.BazelTargetModuleProperties{
+	}
+
+	// Can we automate this?
+	name := "__bp2build__" + fg.Name()
+	props := bazel.BazelTargetModuleProperties{
+		Name:       &name,
 		Rule_class: "filegroup",
-	})
+	}
+
+	ctx.CreateBazelTargetModule(BazelFileGroupFactory, props, attrs)
 }
 
 type fileGroupProperties struct {
diff --git a/android/mutator.go b/android/mutator.go
index 15be65f..91753d1 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"android/soong/bazel"
 	"reflect"
 
 	"github.com/google/blueprint"
@@ -275,6 +276,12 @@
 	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
 	// the specified property structs to it as if the properties were set in a blueprint file.
 	CreateModule(ModuleFactory, ...interface{}) Module
+
+	// CreateBazelTargetModule creates a BazelTargetModule by calling the
+	// factory method, just like in CreateModule, but also requires
+	// BazelTargetModuleProperties containing additional metadata for the
+	// bp2build codegenerator.
+	CreateBazelTargetModule(ModuleFactory, bazel.BazelTargetModuleProperties, interface{}) BazelTargetModule
 }
 
 type topDownMutatorContext struct {
@@ -502,6 +509,13 @@
 	ctx.BottomUp("deps", depsMutator).Parallel()
 }
 
+func (t *topDownMutatorContext) CreateBazelTargetModule(
+	factory ModuleFactory,
+	bazelProps bazel.BazelTargetModuleProperties,
+	attrs interface{}) BazelTargetModule {
+	return t.CreateModule(factory, &bazelProps, attrs).(BazelTargetModule)
+}
+
 func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
 	for _, p := range props {
 		err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
diff --git a/bazel/properties.go b/bazel/properties.go
index 5b98d15..fbbbfe6 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -29,6 +29,8 @@
 // BazelTargetModuleProperties contain properties and metadata used for
 // Blueprint to BUILD file conversion.
 type BazelTargetModuleProperties struct {
+	Name *string
+
 	// The Bazel rule class for this target.
 	Rule_class string
 
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 5e6481b..b5f5448 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -3,8 +3,6 @@
 import (
 	"android/soong/android"
 	"android/soong/bazel"
-
-	"github.com/google/blueprint/proptools"
 )
 
 type nestedProps struct {
@@ -105,7 +103,6 @@
 }
 
 type customBazelModuleAttributes struct {
-	Name             *string
 	String_prop      string
 	String_list_prop []string
 }
@@ -127,14 +124,18 @@
 
 func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
 	if m, ok := ctx.Module().(*customModule); ok {
-		name := "__bp2build__" + m.Name()
-		ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
-			Name:             proptools.StringPtr(name),
+		attrs := &customBazelModuleAttributes{
 			String_prop:      m.props.String_prop,
 			String_list_prop: m.props.String_list_prop,
-		}, &bazel.BazelTargetModuleProperties{
+		}
+
+		name := "__bp2build__" + m.Name()
+		props := bazel.BazelTargetModuleProperties{
+			Name:       &name,
 			Rule_class: "custom",
-		})
+		}
+
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, props, attrs)
 	}
 }
 
@@ -142,24 +143,31 @@
 // module to target.
 func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
 	if m, ok := ctx.Module().(*customModule); ok {
-		baseName := "__bp2build__" + m.Name()
-		ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
-			Name: proptools.StringPtr(baseName),
-		}, &bazel.BazelTargetModuleProperties{
+		baseName := m.Name()
+		attrs := &customBazelModuleAttributes{}
+
+		myLibraryName := "__bp2build__" + baseName
+		myLibraryProps := bazel.BazelTargetModuleProperties{
+			Name:              &myLibraryName,
 			Rule_class:        "my_library",
 			Bzl_load_location: "//build/bazel/rules:rules.bzl",
-		})
-		ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
-			Name: proptools.StringPtr(baseName + "_proto_library_deps"),
-		}, &bazel.BazelTargetModuleProperties{
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, myLibraryProps, attrs)
+
+		protoLibraryName := "__bp2build__" + baseName + "_proto_library_deps"
+		protoLibraryProps := bazel.BazelTargetModuleProperties{
+			Name:              &protoLibraryName,
 			Rule_class:        "proto_library",
 			Bzl_load_location: "//build/bazel/rules:proto.bzl",
-		})
-		ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
-			Name: proptools.StringPtr(baseName + "_my_proto_library_deps"),
-		}, &bazel.BazelTargetModuleProperties{
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, protoLibraryProps, attrs)
+
+		myProtoLibraryName := "__bp2build__" + baseName + "_my_proto_library_deps"
+		myProtoLibraryProps := bazel.BazelTargetModuleProperties{
+			Name:              &myProtoLibraryName,
 			Rule_class:        "my_proto_library",
 			Bzl_load_location: "//build/bazel/rules:proto.bzl",
-		})
+		}
+		ctx.CreateBazelTargetModule(customBazelModuleFactory, myProtoLibraryProps, attrs)
 	}
 }
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 62aa7f8..427c995 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -780,7 +780,6 @@
 }
 
 type bazelGenruleAttributes struct {
-	Name  *string
 	Srcs  bazel.LabelList
 	Outs  []string
 	Tools bazel.LabelList
@@ -804,7 +803,7 @@
 	if !ok {
 		return
 	}
-	name := "__bp2build__" + m.Name()
+
 	// Bazel only has the "tools" attribute.
 	tools := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
 	tool_files := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
@@ -847,16 +846,22 @@
 		}
 	}
 
-	// Create the BazelTargetModule.
-	ctx.CreateModule(BazelGenruleFactory, &bazelGenruleAttributes{
-		Name:  proptools.StringPtr(name),
+	attrs := &bazelGenruleAttributes{
 		Srcs:  srcs,
 		Outs:  outs,
 		Cmd:   cmd,
 		Tools: tools,
-	}, &bazel.BazelTargetModuleProperties{
+	}
+
+	// Can we automate this?
+	name := "__bp2build__" + m.Name()
+	props := bazel.BazelTargetModuleProperties{
+		Name:       &name,
 		Rule_class: "genrule",
-	})
+	}
+
+	// Create the BazelTargetModule.
+	ctx.CreateBazelTargetModule(BazelGenruleFactory, props, attrs)
 }
 
 func (m *bazelGenrule) Name() string {