bp2build: split as, c, and cpp srcs for cc_library

This CL adds support for cc_library to correctly split c, as and cpp
srcs in shared/static nested props, as well as splitting
the *filegroup* deps in those props, where each filegroup is expanded
into its own c, cpp and as srcs filegroups. This ensures that the
correct sources go into cc_library_static's underlying cc_libraries for
c, cpp and as sources respectively.

See the bp2build conversion test for a better visualization.

Bug: 183064430

Test: TH
Change-Id: I29add5140672d042adff65527d8b65f4a5f0a05b
diff --git a/cc/bp2build.go b/cc/bp2build.go
index fed9936..a156d54 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -14,6 +14,7 @@
 package cc
 
 import (
+	"fmt"
 	"path/filepath"
 	"strings"
 
@@ -164,13 +165,86 @@
 // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
 // properties which apply to either the shared or static version of a cc_library module.
 type staticOrSharedAttributes struct {
-	copts            bazel.StringListAttribute
-	srcs             bazel.LabelListAttribute
+	srcs    bazel.LabelListAttribute
+	srcs_c  bazel.LabelListAttribute
+	srcs_as bazel.LabelListAttribute
+
+	copts bazel.StringListAttribute
+
 	staticDeps       bazel.LabelListAttribute
 	dynamicDeps      bazel.LabelListAttribute
 	wholeArchiveDeps bazel.LabelListAttribute
 }
 
+func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) (cppSrcs, cSrcs, asSrcs bazel.LabelListAttribute) {
+	// Branch srcs into three language-specific groups.
+	// C++ is the "catch-all" group, and comprises generated sources because we don't
+	// know the language of these sources until the genrule is executed.
+	// TODO(b/190006308): Handle language detection of sources in a Bazel rule.
+	isCSrcOrFilegroup := func(s string) bool {
+		return strings.HasSuffix(s, ".c") || strings.HasSuffix(s, "_c_srcs")
+	}
+
+	isAsmSrcOrFilegroup := func(s string) bool {
+		return strings.HasSuffix(s, ".S") || strings.HasSuffix(s, ".s") || strings.HasSuffix(s, "_as_srcs")
+	}
+
+	// Check that a module is a filegroup type named <label>.
+	isFilegroupNamed := func(m android.Module, fullLabel string) bool {
+		if ctx.OtherModuleType(m) != "filegroup" {
+			return false
+		}
+		labelParts := strings.Split(fullLabel, ":")
+		if len(labelParts) > 2 {
+			// There should not be more than one colon in a label.
+			panic(fmt.Errorf("%s is not a valid Bazel label for a filegroup", fullLabel))
+		} else {
+			return m.Name() == labelParts[len(labelParts)-1]
+		}
+	}
+
+	// Convert the filegroup dependencies into the extension-specific filegroups
+	// filtered in the filegroup.bzl macro.
+	cppFilegroup := func(label string) string {
+		ctx.VisitDirectDeps(func(m android.Module) {
+			if isFilegroupNamed(m, label) {
+				label = label + "_cpp_srcs"
+				return
+			}
+		})
+		return label
+	}
+	cFilegroup := func(label string) string {
+		ctx.VisitDirectDeps(func(m android.Module) {
+			if isFilegroupNamed(m, label) {
+				label = label + "_c_srcs"
+				return
+			}
+		})
+		return label
+	}
+	asFilegroup := func(label string) string {
+		ctx.VisitDirectDeps(func(m android.Module) {
+			if isFilegroupNamed(m, label) {
+				label = label + "_as_srcs"
+				return
+			}
+		})
+		return label
+	}
+
+	cSrcs = bazel.MapLabelListAttribute(srcs, cFilegroup)
+	cSrcs = bazel.FilterLabelListAttribute(cSrcs, isCSrcOrFilegroup)
+
+	asSrcs = bazel.MapLabelListAttribute(srcs, asFilegroup)
+	asSrcs = bazel.FilterLabelListAttribute(asSrcs, isAsmSrcOrFilegroup)
+
+	cppSrcs = bazel.MapLabelListAttribute(srcs, cppFilegroup)
+	cppSrcs = bazel.SubtractBazelLabelListAttribute(cppSrcs, cSrcs)
+	cppSrcs = bazel.SubtractBazelLabelListAttribute(cppSrcs, asSrcs)
+	return
+}
+
 // bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
 func bp2BuildParseSharedProps(ctx android.TopDownMutatorContext, module *Module) staticOrSharedAttributes {
 	lib, ok := module.compiler.(*libraryDecorator)
@@ -265,6 +339,11 @@
 		}
 	}
 
+	cppSrcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, attrs.srcs)
+	attrs.srcs = cppSrcs
+	attrs.srcs_c = cSrcs
+	attrs.srcs_as = asSrcs
+
 	return attrs
 }
 
@@ -528,20 +607,8 @@
 		}
 	}
 
-	// Branch srcs into three language-specific groups.
-	// C++ is the "catch-all" group, and comprises generated sources because we don't
-	// know the language of these sources until the genrule is executed.
-	// TODO(b/): Handle language detection of sources in a Bazel rule.
-	isCSrc := func(s string) bool {
-		return strings.HasSuffix(s, ".c")
-	}
-	isAsmSrc := func(s string) bool {
-		return strings.HasSuffix(s, ".S") || strings.HasSuffix(s, ".s")
-	}
-	cSrcs := bazel.FilterLabelListAttribute(srcs, isCSrc)
-	asSrcs := bazel.FilterLabelListAttribute(srcs, isAsmSrc)
-	srcs = bazel.SubtractBazelLabelListAttribute(srcs, cSrcs)
-	srcs = bazel.SubtractBazelLabelListAttribute(srcs, asSrcs)
+	srcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, srcs)
+
 	return compilerAttributes{
 		copts:      copts,
 		srcs:       srcs,
diff --git a/cc/library.go b/cc/library.go
index 5e70c51..cdac01c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -221,25 +221,29 @@
 // For bp2build conversion.
 type bazelCcLibraryAttributes struct {
 	// Attributes pertaining to both static and shared variants.
-	Srcs                bazel.LabelListAttribute
+	Srcs    bazel.LabelListAttribute
+	Srcs_c  bazel.LabelListAttribute
+	Srcs_as bazel.LabelListAttribute
+
+	Copts      bazel.StringListAttribute
+	Cppflags   bazel.StringListAttribute
+	Conlyflags bazel.StringListAttribute
+	Asflags    bazel.StringListAttribute
+
 	Hdrs                bazel.LabelListAttribute
 	Deps                bazel.LabelListAttribute
 	Implementation_deps bazel.LabelListAttribute
 	Dynamic_deps        bazel.LabelListAttribute
 	Whole_archive_deps  bazel.LabelListAttribute
-	Copts               bazel.StringListAttribute
 	Includes            bazel.StringListAttribute
 	Linkopts            bazel.StringListAttribute
 
-	Cppflags   bazel.StringListAttribute
-	Srcs_c     bazel.LabelListAttribute
-	Conlyflags bazel.StringListAttribute
-	Srcs_as    bazel.LabelListAttribute
-	Asflags    bazel.StringListAttribute
-
 	// Attributes pertaining to shared variant.
-	Shared_copts                  bazel.StringListAttribute
-	Shared_srcs                   bazel.LabelListAttribute
+	Shared_srcs    bazel.LabelListAttribute
+	Shared_srcs_c  bazel.LabelListAttribute
+	Shared_srcs_as bazel.LabelListAttribute
+	Shared_copts   bazel.StringListAttribute
+
 	Exported_deps_for_shared      bazel.LabelListAttribute
 	Static_deps_for_shared        bazel.LabelListAttribute
 	Dynamic_deps_for_shared       bazel.LabelListAttribute
@@ -248,8 +252,11 @@
 	Version_script                bazel.LabelAttribute
 
 	// Attributes pertaining to static variant.
-	Static_copts                  bazel.StringListAttribute
-	Static_srcs                   bazel.LabelListAttribute
+	Static_srcs    bazel.LabelListAttribute
+	Static_srcs_c  bazel.LabelListAttribute
+	Static_srcs_as bazel.LabelListAttribute
+	Static_copts   bazel.StringListAttribute
+
 	Exported_deps_for_static      bazel.LabelListAttribute
 	Static_deps_for_static        bazel.LabelListAttribute
 	Dynamic_deps_for_static       bazel.LabelListAttribute
@@ -302,29 +309,35 @@
 	srcs.Append(compilerAttrs.srcs)
 
 	attrs := &bazelCcLibraryAttributes{
-		Srcs:                srcs,
+		Srcs:    srcs,
+		Srcs_c:  compilerAttrs.cSrcs,
+		Srcs_as: compilerAttrs.asSrcs,
+
+		Copts:      compilerAttrs.copts,
+		Cppflags:   compilerAttrs.cppFlags,
+		Conlyflags: compilerAttrs.conlyFlags,
+		Asflags:    compilerAttrs.asFlags,
+
 		Implementation_deps: linkerAttrs.deps,
 		Deps:                linkerAttrs.exportedDeps,
 		Dynamic_deps:        linkerAttrs.dynamicDeps,
 		Whole_archive_deps:  linkerAttrs.wholeArchiveDeps,
-		Copts:               compilerAttrs.copts,
 		Includes:            exportedIncludes,
 		Linkopts:            linkerAttrs.linkopts,
-		Cppflags:            compilerAttrs.cppFlags,
-		Srcs_c:              compilerAttrs.cSrcs,
-		Conlyflags:          compilerAttrs.conlyFlags,
-		Srcs_as:             compilerAttrs.asSrcs,
-		Asflags:             compilerAttrs.asFlags,
 
-		Shared_copts:                  sharedAttrs.copts,
 		Shared_srcs:                   sharedAttrs.srcs,
+		Shared_srcs_c:                 sharedAttrs.srcs_c,
+		Shared_srcs_as:                sharedAttrs.srcs_as,
+		Shared_copts:                  sharedAttrs.copts,
 		Static_deps_for_shared:        sharedAttrs.staticDeps,
 		Whole_archive_deps_for_shared: sharedAttrs.wholeArchiveDeps,
 		Dynamic_deps_for_shared:       sharedAttrs.dynamicDeps,
 		Version_script:                linkerAttrs.versionScript,
 
-		Static_copts:                  staticAttrs.copts,
 		Static_srcs:                   staticAttrs.srcs,
+		Static_srcs_c:                 staticAttrs.srcs_c,
+		Static_srcs_as:                staticAttrs.srcs_as,
+		Static_copts:                  staticAttrs.copts,
 		Static_deps_for_static:        staticAttrs.staticDeps,
 		Whole_archive_deps_for_static: staticAttrs.wholeArchiveDeps,
 		Dynamic_deps_for_static:       staticAttrs.dynamicDeps,