Merge "Bp2build: handle the case where java_library has only proto srcs" into main
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
index 5d6b088..dfef697 100644
--- a/bp2build/java_proto_conversion_test.go
+++ b/bp2build/java_proto_conversion_test.go
@@ -137,3 +137,50 @@
 		},
 	})
 }
+
+func TestJavaLibsAndOnlyProtoSrcs(t *testing.T) {
+	runJavaProtoTestCase(t, Bp2buildTestCase{
+		Description: "java_library that has only proto srcs",
+		Blueprint: `java_library_static {
+    name: "java-protos",
+    srcs: ["a.proto"],
+    libs: ["java-lib"],
+    java_version: "7",
+    sdk_version: "current",
+}
+
+java_library_static {
+    name: "java-lib",
+    bazel_module: { bp2build_available: false },
+}
+`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{
+				"srcs": `["a.proto"]`,
+			}),
+			MakeBazelTarget(
+				"java_lite_proto_library",
+				"java-protos_java_proto_lite",
+				AttrNameToString{
+					"deps":         `[":java-protos_proto"]`,
+					"java_version": `"7"`,
+					"sdk_version":  `"current"`,
+				}),
+			MakeBazelTarget("java_library", "java-protos", AttrNameToString{
+				"exports": `[
+        ":java-protos_java_proto_lite",
+        ":java-lib-neverlink",
+    ]`,
+				"java_version": `"7"`,
+				"sdk_version":  `"current"`,
+			}),
+			MakeNeverlinkDuplicateTargetWithAttrs(
+				"java_library",
+				"java-protos",
+				AttrNameToString{
+					"java_version": `"7"`,
+					"sdk_version":  `"current"`,
+				}),
+		},
+	})
+}
diff --git a/java/java.go b/java/java.go
index 99bb1b3..a81abe6 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2885,8 +2885,9 @@
 // depending on the module type.
 type bp2BuildJavaInfo struct {
 	// separates dependencies into dynamic dependencies and static dependencies.
-	DepLabels *javaDependencyLabels
-	hasKotlin bool
+	DepLabels       *javaDependencyLabels
+	hasKotlin       bool
+	onlyProtoInSrcs bool
 }
 
 func javaXsdTargetName(xsd android.XsdConfigBp2buildTargets) string {
@@ -2949,6 +2950,9 @@
 
 	staticDeps.Append(srcPartitions[xsdSrcPartition])
 
+	_, protoInSrcs := srcPartitions[protoSrcPartition]
+	onlyProtoInSrcs := protoInSrcs && len(srcPartitions) == 1
+
 	if !srcPartitions[logtagSrcPartition].IsEmpty() {
 		logtagsLibName := m.Name() + "_logtags"
 		ctx.CreateBazelTargetModule(
@@ -3086,8 +3090,9 @@
 	}
 
 	bp2BuildInfo := &bp2BuildJavaInfo{
-		DepLabels: depLabels,
-		hasKotlin: hasKotlin,
+		DepLabels:       depLabels,
+		hasKotlin:       hasKotlin,
+		onlyProtoInSrcs: onlyProtoInSrcs,
 	}
 
 	return commonAttrs, bp2BuildInfo, true
@@ -3127,16 +3132,29 @@
 	depLabels := bp2BuildInfo.DepLabels
 
 	deps := depLabels.Deps
+	exports := depLabels.StaticDeps
 	if !commonAttrs.Srcs.IsEmpty() {
-		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
+		deps.Append(exports) // we should only append these if there are sources to use them
 	} else if !deps.IsEmpty() {
-		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
+		if bp2BuildInfo.onlyProtoInSrcs {
+			// java_library does not accept deps when there are no srcs because
+			// there is no compilation happening, but it accepts exports.
+			// bp2build converts this module to 2 java_libraries + java_xx_proto_library + proto_library
+			// the non-empty deps here are not necessary for compiling the protos, in which case
+			// they're unnecessary as deps on the java_library as well since they aren't
+			// being propagated to any dependencies.
+			// so we can put the deps to exports and drop deps here.
+			exports.Append(deps)
+			deps = bazel.LabelListAttribute{}
+		} else {
+			ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
+		}
 	}
 	var props bazel.BazelTargetModuleProperties
 	attrs := &javaLibraryAttributes{
 		javaCommonAttributes: commonAttrs,
 		Deps:                 deps,
-		Exports:              depLabels.StaticDeps,
+		Exports:              exports,
 	}
 	name := m.Name()