Repository: kythe/kythe
Pull request #5664 (2023-05-26 22:21:30)

chore(tooling): record -source values from java CUs for kzip info


Patch:
diff --git a/kythe/go/platform/kzip/info/info.go b/kythe/go/platform/kzip/info/info.go
index e42e30539..00adcd3ce 100644
--- a/kythe/go/platform/kzip/info/info.go
+++ b/kythe/go/platform/kzip/info/info.go
@@ -20,6 +20,7 @@ package info // import "kythe.io/kythe/go/platform/kzip/info"
 import (
 	"fmt"
 	"path/filepath"
+	"strconv"
 	"strings"
 
 	"kythe.io/kythe/go/platform/kzip"
@@ -84,6 +85,13 @@ func (a *Accumulator) Accumulate(u *kzip.Unit) {
 		return
 	}
 
+	cuInfo(u.Proto.GetVName().GetCorpus(), cuLang, a.KzipInfo).Count++
+
+	if cuLang == "java" {
+		v := javaSourceVersion(u.Proto.GetArgument())
+		cuInfo(u.Proto.GetVName().GetCorpus(), cuLang, a.KzipInfo).JavaVersionCount[int32(v)]++
+	}
+
 	var srcCorpora stringset.Set
 	var absPaths stringset.Set
 	srcsWithRI := stringset.New()
@@ -124,6 +132,26 @@ func (a *Accumulator) Accumulate(u *kzip.Unit) {
 	a.KzipInfo.AbsolutePaths = absPaths.Elements()
 }
 
+// javaSourceVersion checks if the CU args include setting source to a language level and if it does
+// it returns that version. If no source flag is set or it can't be read, it returns 0.
+func javaSourceVersion(args []string) int {
+	for i, arg := range args {
+		if arg == "-source" || arg == "--source" {
+			if i+1 < len(args) {
+				version := args[i+1]
+				version = strings.TrimPrefix(version, "1.")
+				intVersion, err := strconv.Atoi(version)
+				if err != nil {
+					log.Errorf("Unable to parse java version string: %v", err)
+					return 0
+				}
+				return intVersion
+			}
+		}
+	}
+	return 0
+}
+
 // Get returns the final KzipInfo after info from each unit in the kzip has been
 // accumulated.
 func (a *Accumulator) Get() *apb.KzipInfo {
@@ -144,15 +172,16 @@ func requiredInputCorpus(u *kzip.Unit, ri *apb.CompilationUnit_FileInput) string
 // KzipInfoTotalCount returns the total CompilationUnits counts for infos split apart by language.
 func KzipInfoTotalCount(infos []*apb.KzipInfo) *apb.KzipInfo_CorpusInfo {
 	totals := &apb.KzipInfo_CorpusInfo{
-		LanguageRequiredInputs: make(map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs),
-		LanguageSources:        make(map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs),
+		LanguageRequiredInputs: make(map[string]*apb.KzipInfo_CorpusInfo_Inputs),
+		LanguageSources:        make(map[string]*apb.KzipInfo_CorpusInfo_Inputs),
+		LanguageCuInfo:         make(map[string]*apb.KzipInfo_CorpusInfo_CUInfo),
 	}
 	for _, info := range infos {
 		for _, i := range info.GetCorpora() {
 			for lang, stats := range i.GetLanguageRequiredInputs() {
 				total := totals.LanguageRequiredInputs[lang]
 				if total == nil {
-					total = &apb.KzipInfo_CorpusInfo_RequiredInputs{}
+					total = &apb.KzipInfo_CorpusInfo_Inputs{}
 					totals.LanguageRequiredInputs[lang] = total
 				}
 				total.Count += stats.GetCount()
@@ -160,11 +189,22 @@ func KzipInfoTotalCount(infos []*apb.KzipInfo) *apb.KzipInfo_CorpusInfo {
 			for lang, stats := range i.GetLanguageSources() {
 				total := totals.LanguageSources[lang]
 				if total == nil {
-					total = &apb.KzipInfo_CorpusInfo_RequiredInputs{}
+					total = &apb.KzipInfo_CorpusInfo_Inputs{}
 					totals.LanguageSources[lang] = total
 				}
 				total.Count += stats.GetCount()
 			}
+			for lang, stats := range i.GetLanguageCuInfo() {
+				total := totals.LanguageCuInfo[lang]
+				if total == nil {
+					total = makeCUInfo()
+					totals.LanguageCuInfo[lang] = total
+				}
+				total.Count += stats.GetCount()
+				for version, count := range stats.GetJavaVersionCount() {
+					total.JavaVersionCount[version] += count
+				}
+			}
 		}
 	}
 	return totals
@@ -184,6 +224,13 @@ func MergeKzipInfo(infos []*apb.KzipInfo) *apb.KzipInfo {
 				c := sourceInfo(corpus, lang, kzipInfo)
 				c.Count += sources.GetCount()
 			}
+			for lang, cu := range cinfo.GetLanguageCuInfo() {
+				c := cuInfo(corpus, lang, kzipInfo)
+				c.Count += cu.GetCount()
+				for version, count := range cu.GetJavaVersionCount() {
+					c.JavaVersionCount[version] += count
+				}
+			}
 		}
 		kzipInfo.CriticalKzipErrors = append(kzipInfo.GetCriticalKzipErrors(), i.GetCriticalKzipErrors()...)
 		kzipInfo.Size += i.Size
@@ -192,32 +239,49 @@ func MergeKzipInfo(infos []*apb.KzipInfo) *apb.KzipInfo {
 	return kzipInfo
 }
 
-func requiredInputInfo(corpus, lang string, kzipInfo *apb.KzipInfo) *apb.KzipInfo_CorpusInfo_RequiredInputs {
+func requiredInputInfo(corpus, lang string, kzipInfo *apb.KzipInfo) *apb.KzipInfo_CorpusInfo_Inputs {
 	c := corpusInfo(corpus, kzipInfo)
 	lri := c.LanguageRequiredInputs[lang]
 	if lri == nil {
-		lri = &apb.KzipInfo_CorpusInfo_RequiredInputs{}
+		lri = &apb.KzipInfo_CorpusInfo_Inputs{}
 		c.LanguageRequiredInputs[lang] = lri
 	}
 	return lri
 }
 
-func sourceInfo(corpus, lang string, kzipInfo *apb.KzipInfo) *apb.KzipInfo_CorpusInfo_RequiredInputs {
+func sourceInfo(corpus, lang string, kzipInfo *apb.KzipInfo) *apb.KzipInfo_CorpusInfo_Inputs {
 	c := corpusInfo(corpus, kzipInfo)
 	ls := c.LanguageSources[lang]
 	if ls == nil {
-		ls = &apb.KzipInfo_CorpusInfo_RequiredInputs{}
+		ls = &apb.KzipInfo_CorpusInfo_Inputs{}
 		c.LanguageSources[lang] = ls
 	}
 	return ls
 }
 
+func cuInfo(corpus, lang string, kzipInfo *apb.KzipInfo) *apb.KzipInfo_CorpusInfo_CUInfo {
+	c := corpusInfo(corpus, kzipInfo)
+	cuInfo := c.LanguageCuInfo[lang]
+	if cuInfo == nil {
+		cuInfo = makeCUInfo()
+		c.LanguageCuInfo[lang] = cuInfo
+	}
+	return cuInfo
+}
+
+func makeCUInfo() *apb.KzipInfo_CorpusInfo_CUInfo {
+	return &apb.KzipInfo_CorpusInfo_CUInfo{
+		JavaVersionCount: make(map[int32]int32),
+	}
+}
+
 func corpusInfo(corpus string, kzipInfo *apb.KzipInfo) *apb.KzipInfo_CorpusInfo {
 	i := kzipInfo.GetCorpora()[corpus]
 	if i == nil {
 		i = &apb.KzipInfo_CorpusInfo{
-			LanguageRequiredInputs: make(map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs),
-			LanguageSources:        make(map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs),
+			LanguageRequiredInputs: make(map[string]*apb.KzipInfo_CorpusInfo_Inputs),
+			LanguageSources:        make(map[string]*apb.KzipInfo_CorpusInfo_Inputs),
+			LanguageCuInfo:         make(map[string]*apb.KzipInfo_CorpusInfo_CUInfo),
 		}
 		kzipInfo.Corpora[corpus] = i
 	}
diff --git a/kythe/proto/analysis.proto b/kythe/proto/analysis.proto
index bf7f14a37..fe46f05f4 100644
--- a/kythe/proto/analysis.proto
+++ b/kythe/proto/analysis.proto
@@ -191,17 +191,28 @@ message KzipInfo {
   message CorpusInfo {
     reserved 1, 2, 3;
 
-    message RequiredInputs {
+    message Inputs {
       // TODO(salguarnieri) Add count of unique inputs for this corpus?
       int32 count = 1;
     }
 
+    message CUInfo {
+      int32 count = 1;
+      // Map from java version to number of CUs that make use of that java
+      // version. Note that if no -source flag is specified for a CU, it will
+      // not impact this count.
+      map<int32, int32> java_version_count = 2;
+    }
+
     // Map from language to count of required inputs that have this corpus in
     // their VName.
-    map<string, RequiredInputs> language_required_inputs = 4;
+    map<string, Inputs> language_required_inputs = 4;
     // Map from language to count of sources that have this corpus in their
     // required_input VName.
-    map<string, RequiredInputs> language_sources = 5;
+    map<string, Inputs> language_sources = 5;
+    // Map from language to count of compilation units that have this corpus in
+    // their VName.
+    map<string, CUInfo> language_cu_info = 6;
   }
 
   // Map from corpus name to corpus info.
diff --git a/kythe/proto/analysis_go_proto/analysis.pb.go b/kythe/proto/analysis_go_proto/analysis.pb.go
index 24eca32e5..228a2ff9a 100644
--- a/kythe/proto/analysis_go_proto/analysis.pb.go
+++ b/kythe/proto/analysis_go_proto/analysis.pb.go
@@ -896,8 +896,9 @@ type KzipInfo_CorpusInfo struct {
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	LanguageRequiredInputs map[string]*KzipInfo_CorpusInfo_RequiredInputs `protobuf:"bytes,4,rep,name=language_required_inputs,json=languageRequiredInputs,proto3" json:"language_required_inputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
-	LanguageSources        map[string]*KzipInfo_CorpusInfo_RequiredInputs `protobuf:"bytes,5,rep,name=language_sources,json=languageSources,proto3" json:"language_sources,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	LanguageRequiredInputs map[string]*KzipInfo_CorpusInfo_Inputs `protobuf:"bytes,4,rep,name=language_required_inputs,json=languageRequiredInputs,proto3" json:"language_required_inputs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	LanguageSources        map[string]*KzipInfo_CorpusInfo_Inputs `protobuf:"bytes,5,rep,name=language_sources,json=languageSources,proto3" json:"language_sources,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	LanguageCuInfo         map[string]*KzipInfo_CorpusInfo_CUInfo `protobuf:"bytes,6,rep,name=language_cu_info,json=languageCuInfo,proto3" json:"language_cu_info,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
 }
 
 func (x *KzipInfo_CorpusInfo) Reset() {
@@ -932,21 +933,28 @@ func (*KzipInfo_CorpusInfo) Descriptor() ([]byte, []int) {
 	return file_kythe_proto_analysis_proto_rawDescGZIP(), []int{4, 0}
 }
 
-func (x *KzipInfo_CorpusInfo) GetLanguageRequiredInputs() map[string]*KzipInfo_CorpusInfo_RequiredInputs {
+func (x *KzipInfo_CorpusInfo) GetLanguageRequiredInputs() map[string]*KzipInfo_CorpusInfo_Inputs {
 	if x != nil {
 		return x.LanguageRequiredInputs
 	}
 	return nil
 }
 
-func (x *KzipInfo_CorpusInfo) GetLanguageSources() map[string]*KzipInfo_CorpusInfo_RequiredInputs {
+func (x *KzipInfo_CorpusInfo) GetLanguageSources() map[string]*KzipInfo_CorpusInfo_Inputs {
 	if x != nil {
 		return x.LanguageSources
 	}
 	return nil
 }
 
-type KzipInfo_CorpusInfo_RequiredInputs struct {
+func (x *KzipInfo_CorpusInfo) GetLanguageCuInfo() map[string]*KzipInfo_CorpusInfo_CUInfo {
+	if x != nil {
+		return x.LanguageCuInfo
+	}
+	return nil
+}
+
+type KzipInfo_CorpusInfo_Inputs struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
@@ -954,8 +962,8 @@ type KzipInfo_CorpusInfo_RequiredInputs struct {
 	Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"`
 }
 
-func (x *KzipInfo_CorpusInfo_RequiredInputs) Reset() {
-	*x = KzipInfo_CorpusInfo_RequiredInputs{}
+func (x *KzipInfo_CorpusInfo_Inputs) Reset() {
+	*x = KzipInfo_CorpusInfo_Inputs{}
 	if protoimpl.UnsafeEnabled {
 		mi := &file_kythe_proto_analysis_proto_msgTypes[15]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -963,13 +971,13 @@ func (x *KzipInfo_CorpusInfo_RequiredInputs) Reset() {
 	}
 }
 
-func (x *KzipInfo_CorpusInfo_RequiredInputs) String() string {
+func (x *KzipInfo_CorpusInfo_Inputs) String() string {
 	return protoimpl.X.MessageStringOf(x)
 }
 
-func (*KzipInfo_CorpusInfo_RequiredInputs) ProtoMessage() {}
+func (*KzipInfo_CorpusInfo_Inputs) ProtoMessage() {}
 
-func (x *KzipInfo_CorpusInfo_RequiredInputs) ProtoReflect() protoreflect.Message {
+func (x *KzipInfo_CorpusInfo_Inputs) ProtoReflect() protoreflect.Message {
 	mi := &file_kythe_proto_analysis_proto_msgTypes[15]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
@@ -981,18 +989,73 @@ func (x *KzipInfo_CorpusInfo_RequiredInputs) ProtoReflect() protoreflect.Message
 	return mi.MessageOf(x)
 }
 
-// Deprecated: Use KzipInfo_CorpusInfo_RequiredInputs.ProtoReflect.Descriptor instead.
-func (*KzipInfo_CorpusInfo_RequiredInputs) Descriptor() ([]byte, []int) {
+// Deprecated: Use KzipInfo_CorpusInfo_Inputs.ProtoReflect.Descriptor instead.
+func (*KzipInfo_CorpusInfo_Inputs) Descriptor() ([]byte, []int) {
 	return file_kythe_proto_analysis_proto_rawDescGZIP(), []int{4, 0, 0}
 }
 
-func (x *KzipInfo_CorpusInfo_RequiredInputs) GetCount() int32 {
+func (x *KzipInfo_CorpusInfo_Inputs) GetCount() int32 {
+	if x != nil {
+		return x.Count
+	}
+	return 0
+}
+
+type KzipInfo_CorpusInfo_CUInfo struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Count            int32           `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"`
+	JavaVersionCount map[int32]int32 `protobuf:"bytes,2,rep,name=java_version_count,json=javaVersionCount,proto3" json:"java_version_count,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+}
+
+func (x *KzipInfo_CorpusInfo_CUInfo) Reset() {
+	*x = KzipInfo_CorpusInfo_CUInfo{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_kythe_proto_analysis_proto_msgTypes[16]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *KzipInfo_CorpusInfo_CUInfo) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*KzipInfo_CorpusInfo_CUInfo) ProtoMessage() {}
+
+func (x *KzipInfo_CorpusInfo_CUInfo) ProtoReflect() protoreflect.Message {
+	mi := &file_kythe_proto_analysis_proto_msgTypes[16]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use KzipInfo_CorpusInfo_CUInfo.ProtoReflect.Descriptor instead.
+func (*KzipInfo_CorpusInfo_CUInfo) Descriptor() ([]byte, []int) {
+	return file_kythe_proto_analysis_proto_rawDescGZIP(), []int{4, 0, 1}
+}
+
+func (x *KzipInfo_CorpusInfo_CUInfo) GetCount() int32 {
 	if x != nil {
 		return x.Count
 	}
 	return 0
 }
 
+func (x *KzipInfo_CorpusInfo_CUInfo) GetJavaVersionCount() map[int32]int32 {
+	if x != nil {
+		return x.JavaVersionCount
+	}
+	return nil
+}
+
 type IndexedCompilation_Index struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -1004,7 +1067,7 @@ type IndexedCompilation_Index struct {
 func (x *IndexedCompilation_Index) Reset() {
 	*x = IndexedCompilation_Index{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_kythe_proto_analysis_proto_msgTypes[18]
+		mi := &file_kythe_proto_analysis_proto_msgTypes[21]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -1017,7 +1080,7 @@ func (x *IndexedCompilation_Index) String() string {
 func (*IndexedCompilation_Index) ProtoMessage() {}
 
 func (x *IndexedCompilation_Index) ProtoReflect() protoreflect.Message {
-	mi := &file_kythe_proto_analysis_proto_msgTypes[18]
+	mi := &file_kythe_proto_analysis_proto_msgTypes[21]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -1125,7 +1188,7 @@ var file_kythe_proto_analysis_proto_rawDesc = []byte{
 	0x03, 0x45, 0x6e, 0x76, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
 	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
 	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x4a, 0x04,
-	0x08, 0x02, 0x10, 0x03, 0x22, 0xb3, 0x06, 0x0a, 0x08, 0x4b, 0x7a, 0x69, 0x70, 0x49, 0x6e, 0x66,
+	0x08, 0x02, 0x10, 0x03, 0x22, 0xba, 0x09, 0x0a, 0x08, 0x4b, 0x7a, 0x69, 0x70, 0x49, 0x6e, 0x66,
 	0x6f, 0x12, 0x3c, 0x0a, 0x07, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x18, 0x01, 0x20, 0x03,
 	0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 	0x2e, 0x4b, 0x7a, 0x69, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72,
@@ -1136,7 +1199,7 @@ var file_kythe_proto_analysis_proto_rawDesc = []byte{
 	0x6f, 0x6c, 0x75, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x72,
 	0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6b, 0x7a, 0x69, 0x70, 0x5f, 0x65, 0x72, 0x72, 0x6f,
 	0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63,
-	0x61, 0x6c, 0x4b, 0x7a, 0x69, 0x70, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, 0x91, 0x04, 0x0a,
+	0x61, 0x6c, 0x4b, 0x7a, 0x69, 0x70, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, 0x98, 0x07, 0x0a,
 	0x0a, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x76, 0x0a, 0x18, 0x6c,
 	0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
 	0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e,
@@ -1151,74 +1214,98 @@ var file_kythe_proto_analysis_proto_rawDesc = []byte{
 	0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x2e,
 	0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45,
 	0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x6f,
-	0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0x26, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
-	0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74,
-	0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0x7a, 0x0a,
-	0x1b, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
-	0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
-	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x45,
-	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
-	0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x7a, 0x69, 0x70,
-	0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x2e,
-	0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x52, 0x05,
-	0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x73, 0x0a, 0x14, 0x4c, 0x61, 0x6e,
-	0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72,
-	0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
-	0x6b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x5e, 0x0a, 0x10, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67,
+	0x65, 0x5f, 0x63, 0x75, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x34, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x7a,
+	0x69, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x49, 0x6e, 0x66,
+	0x6f, 0x2e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x43, 0x75, 0x49, 0x6e, 0x66, 0x6f,
+	0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x43,
+	0x75, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x1e, 0x0a, 0x06, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12,
+	0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
+	0x63, 0x6f, 0x75, 0x6e, 0x74, 0x1a, 0xd0, 0x01, 0x0a, 0x06, 0x43, 0x55, 0x49, 0x6e, 0x66, 0x6f,
+	0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
+	0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x6b, 0x0a, 0x12, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x76,
+	0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
 	0x2e, 0x4b, 0x7a, 0x69, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73,
-	0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x70,
-	0x75, 0x74, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04,
-	0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04,
-	0x1a, 0x5c, 0x0a, 0x0c, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79,
+	0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x55, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4a, 0x61, 0x76, 0x61,
+	0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72,
+	0x79, 0x52, 0x10, 0x6a, 0x61, 0x76, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f,
+	0x75, 0x6e, 0x74, 0x1a, 0x43, 0x0a, 0x15, 0x4a, 0x61, 0x76, 0x61, 0x56, 0x65, 0x72, 0x73, 0x69,
+	0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
+	0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
+	0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76,
+	0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x72, 0x0a, 0x1b, 0x4c, 0x61, 0x6e, 0x67,
+	0x75, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x49, 0x6e, 0x70, 0x75,
+	0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x7a, 0x69, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x2e,
+	0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74,
+	0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6b, 0x0a, 0x14,
+	0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45,
+	0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x7a, 0x69, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x72,
+	0x70, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x52, 0x05,
+	0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x6a, 0x0a, 0x13, 0x4c, 0x61, 0x6e,
+	0x67, 0x75, 0x61, 0x67, 0x65, 0x43, 0x75, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x74, 0x72, 0x79,
 	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
-	0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x20, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
+	0x65, 0x79, 0x12, 0x3d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x27, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
 	0x4b, 0x7a, 0x69, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x49,
-	0x6e, 0x66, 0x6f, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04,
-	0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0x56, 0x0a, 0x0d, 0x42, 0x75,
-	0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x45, 0x0a, 0x10, 0x63,
-	0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
-	0x70, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
-	0x6d, 0x70, 0x22, 0x3b, 0x0a, 0x0c, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
-	0x0b, 0x32, 0x15, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22,
-	0x36, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70,
-	0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12,
-	0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x69, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x44,
-	0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a,
-	0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6b, 0x79,
-	0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e,
-	0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x69, 0x73, 0x73,
-	0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6d, 0x69, 0x73, 0x73, 0x69,
-	0x6e, 0x67, 0x22, 0x72, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f,
-	0x6e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55,
-	0x6e, 0x69, 0x74, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x66, 0x69, 0x6c,
-	0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52,
-	0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0xaa, 0x01, 0x0a, 0x12, 0x49, 0x6e, 0x64, 0x65, 0x78,
-	0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a,
-	0x04, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6b, 0x79,
-	0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
-	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x12,
-	0x3b, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25,
-	0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x6e, 0x64,
-	0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
-	0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x1a, 0x25, 0x0a, 0x05,
-	0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f,
-	0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69,
-	0x6f, 0x6e, 0x73, 0x42, 0x37, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
-	0x65, 0x2e, 0x64, 0x65, 0x76, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x11, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73,
-	0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xf8, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x33,
+	0x6e, 0x66, 0x6f, 0x2e, 0x43, 0x55, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10,
+	0x03, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x1a, 0x5c, 0x0a, 0x0c, 0x43, 0x6f, 0x72, 0x70, 0x6f,
+	0x72, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c,
+	0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4b, 0x7a, 0x69, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x2e,
+	0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
+	0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x03, 0x10,
+	0x04, 0x22, 0x56, 0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
+	0x74, 0x61, 0x12, 0x45, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d,
+	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
+	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+	0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x3b, 0x0a, 0x0c, 0x46, 0x69, 0x6c,
+	0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x66, 0x69, 0x6c,
+	0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+	0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x36, 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e,
+	0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x22, 0x69,
+	0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f,
+	0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e,
+	0x74, 0x65, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12,
+	0x18, 0x0a, 0x07, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
+	0x52, 0x07, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x22, 0x72, 0x0a, 0x11, 0x43, 0x6f, 0x6d,
+	0x70, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x30,
+	0x0a, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6b,
+	0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69,
+	0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74, 0x52, 0x04, 0x75, 0x6e, 0x69, 0x74,
+	0x12, 0x2b, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
+	0x15, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69,
+	0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0xaa, 0x01,
+	0x0a, 0x12, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x61,
+	0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x6e, 0x69, 0x74,
+	0x52, 0x04, 0x75, 0x6e, 0x69, 0x74, 0x12, 0x3b, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x69,
+	0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x05, 0x69, 0x6e,
+	0x64, 0x65, 0x78, 0x1a, 0x25, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x09,
+	0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
+	0x09, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x37, 0x0a, 0x1f, 0x63, 0x6f,
+	0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x64, 0x65, 0x76, 0x74, 0x6f, 0x6f, 0x6c,
+	0x73, 0x2e, 0x6b, 0x79, 0x74, 0x68, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5a, 0x11, 0x61,
+	0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x5f, 0x67, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0xf8, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -1234,62 +1321,68 @@ func file_kythe_proto_analysis_proto_rawDescGZIP() []byte {
 }
 
 var file_kythe_proto_analysis_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
-var file_kythe_proto_analysis_proto_msgTypes = make([]protoimpl.MessageInfo, 19)
+var file_kythe_proto_analysis_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
 var file_kythe_proto_analysis_proto_goTypes = []interface{}{
-	(AnalysisResult_Status)(0),                 // 0: kythe.proto.AnalysisResult.Status
-	(*AnalysisRequest)(nil),                    // 1: kythe.proto.AnalysisRequest
-	(*AnalysisOutput)(nil),                     // 2: kythe.proto.AnalysisOutput
-	(*AnalysisResult)(nil),                     // 3: kythe.proto.AnalysisResult
-	(*CompilationUnit)(nil),                    // 4: kythe.proto.CompilationUnit
-	(*KzipInfo)(nil),                           // 5: kythe.proto.KzipInfo
-	(*BuildMetadata)(nil),                      // 6: kythe.proto.BuildMetadata
-	(*FilesRequest)(nil),                       // 7: kythe.proto.FilesRequest
-	(*FileInfo)(nil),                           // 8: kythe.proto.FileInfo
-	(*FileData)(nil),                           // 9: kythe.proto.FileData
-	(*CompilationBundle)(nil),                  // 10: kythe.proto.CompilationBundle
-	(*IndexedCompilation)(nil),                 // 11: kythe.proto.IndexedCompilation
-	(*CompilationUnit_FileInput)(nil),          // 12: kythe.proto.CompilationUnit.FileInput
-	(*CompilationUnit_Env)(nil),                // 13: kythe.proto.CompilationUnit.Env
-	(*KzipInfo_CorpusInfo)(nil),                // 14: kythe.proto.KzipInfo.CorpusInfo
-	nil,                                        // 15: kythe.proto.KzipInfo.CorporaEntry
-	(*KzipInfo_CorpusInfo_RequiredInputs)(nil), // 16: kythe.proto.KzipInfo.CorpusInfo.RequiredInputs
-	nil,                              // 17: kythe.proto.KzipInfo.CorpusInfo.LanguageRequiredInputsEntry
-	nil,                              // 18: kythe.proto.KzipInfo.CorpusInfo.LanguageSourcesEntry
-	(*IndexedCompilation_Index)(nil), // 19: kythe.proto.IndexedCompilation.Index
-	(*anypb.Any)(nil),                // 20: google.protobuf.Any
-	(*storage_go_proto.VName)(nil),   // 21: kythe.proto.VName
-	(*timestamppb.Timestamp)(nil),    // 22: google.protobuf.Timestamp
+	(AnalysisResult_Status)(0),         // 0: kythe.proto.AnalysisResult.Status
+	(*AnalysisRequest)(nil),            // 1: kythe.proto.AnalysisRequest
+	(*AnalysisOutput)(nil),             // 2: kythe.proto.AnalysisOutput
+	(*AnalysisResult)(nil),             // 3: kythe.proto.AnalysisResult
+	(*CompilationUnit)(nil),            // 4: kythe.proto.CompilationUnit
+	(*KzipInfo)(nil),                   // 5: kythe.proto.KzipInfo
+	(*BuildMetadata)(nil),              // 6: kythe.proto.BuildMetadata
+	(*FilesRequest)(nil),               // 7: kythe.proto.FilesRequest
+	(*FileInfo)(nil),                   // 8: kythe.proto.FileInfo
+	(*FileData)(nil),                   // 9: kythe.proto.FileData
+	(*CompilationBundle)(nil),          // 10: kythe.proto.CompilationBundle
+	(*IndexedCompilation)(nil),         // 11: kythe.proto.IndexedCompilation
+	(*CompilationUnit_FileInput)(nil),  // 12: kythe.proto.CompilationUnit.FileInput
+	(*CompilationUnit_Env)(nil),        // 13: kythe.proto.CompilationUnit.Env
+	(*KzipInfo_CorpusInfo)(nil),        // 14: kythe.proto.KzipInfo.CorpusInfo
+	nil,                                // 15: kythe.proto.KzipInfo.CorporaEntry
+	(*KzipInfo_CorpusInfo_Inputs)(nil), // 16: kythe.proto.KzipInfo.CorpusInfo.Inputs
+	(*KzipInfo_CorpusInfo_CUInfo)(nil), // 17: kythe.proto.KzipInfo.CorpusInfo.CUInfo
+	nil,                                // 18: kythe.proto.KzipInfo.CorpusInfo.LanguageRequiredInputsEntry
+	nil,                                // 19: kythe.proto.KzipInfo.CorpusInfo.LanguageSourcesEntry
+	nil,                                // 20: kythe.proto.KzipInfo.CorpusInfo.LanguageCuInfoEntry
+	nil,                                // 21: kythe.proto.KzipInfo.CorpusInfo.CUInfo.JavaVersionCountEntry
+	(*IndexedCompilation_Index)(nil),   // 22: kythe.proto.IndexedCompilation.Index
+	(*anypb.Any)(nil),                  // 23: google.protobuf.Any
+	(*storage_go_proto.VName)(nil),     // 24: kythe.proto.VName
+	(*timestamppb.Timestamp)(nil),      // 25: google.protobuf.Timestamp
 }
 var file_kythe_proto_analysis_proto_depIdxs = []int32{
 	4,  // 0: kythe.proto.AnalysisRequest.compilation:type_name -> kythe.proto.CompilationUnit
 	3,  // 1: kythe.proto.AnalysisOutput.final_result:type_name -> kythe.proto.AnalysisResult
 	0,  // 2: kythe.proto.AnalysisResult.status:type_name -> kythe.proto.AnalysisResult.Status
-	20, // 3: kythe.proto.AnalysisResult.details:type_name -> google.protobuf.Any
-	21, // 4: kythe.proto.CompilationUnit.v_name:type_name -> kythe.proto.VName
+	23, // 3: kythe.proto.AnalysisResult.details:type_name -> google.protobuf.Any
+	24, // 4: kythe.proto.CompilationUnit.v_name:type_name -> kythe.proto.VName
 	12, // 5: kythe.proto.CompilationUnit.required_input:type_name -> kythe.proto.CompilationUnit.FileInput
 	13, // 6: kythe.proto.CompilationUnit.environment:type_name -> kythe.proto.CompilationUnit.Env
-	20, // 7: kythe.proto.CompilationUnit.details:type_name -> google.protobuf.Any
+	23, // 7: kythe.proto.CompilationUnit.details:type_name -> google.protobuf.Any
 	15, // 8: kythe.proto.KzipInfo.corpora:type_name -> kythe.proto.KzipInfo.CorporaEntry
-	22, // 9: kythe.proto.BuildMetadata.commit_timestamp:type_name -> google.protobuf.Timestamp
+	25, // 9: kythe.proto.BuildMetadata.commit_timestamp:type_name -> google.protobuf.Timestamp
 	8,  // 10: kythe.proto.FilesRequest.files:type_name -> kythe.proto.FileInfo
 	8,  // 11: kythe.proto.FileData.info:type_name -> kythe.proto.FileInfo
 	4,  // 12: kythe.proto.CompilationBundle.unit:type_name -> kythe.proto.CompilationUnit
 	9,  // 13: kythe.proto.CompilationBundle.files:type_name -> kythe.proto.FileData
 	4,  // 14: kythe.proto.IndexedCompilation.unit:type_name -> kythe.proto.CompilationUnit
-	19, // 15: kythe.proto.IndexedCompilation.index:type_name -> kythe.proto.IndexedCompilation.Index
-	21, // 16: kythe.proto.CompilationUnit.FileInput.v_name:type_name -> kythe.proto.VName
+	22, // 15: kythe.proto.IndexedCompilation.index:type_name -> kythe.proto.IndexedCompilation.Index
+	24, // 16: kythe.proto.CompilationUnit.FileInput.v_name:type_name -> kythe.proto.VName
 	8,  // 17: kythe.proto.CompilationUnit.FileInput.info:type_name -> kythe.proto.FileInfo
-	20, // 18: kythe.proto.CompilationUnit.FileInput.details:type_name -> google.protobuf.Any
-	17, // 19: kythe.proto.KzipInfo.CorpusInfo.language_required_inputs:type_name -> kythe.proto.KzipInfo.CorpusInfo.LanguageRequiredInputsEntry
-	18, // 20: kythe.proto.KzipInfo.CorpusInfo.language_sources:type_name -> kythe.proto.KzipInfo.CorpusInfo.LanguageSourcesEntry
-	14, // 21: kythe.proto.KzipInfo.CorporaEntry.value:type_name -> kythe.proto.KzipInfo.CorpusInfo
-	16, // 22: kythe.proto.KzipInfo.CorpusInfo.LanguageRequiredInputsEntry.value:type_name -> kythe.proto.KzipInfo.CorpusInfo.RequiredInputs
-	16, // 23: kythe.proto.KzipInfo.CorpusInfo.LanguageSourcesEntry.value:type_name -> kythe.proto.KzipInfo.CorpusInfo.RequiredInputs
-	24, // [24:24] is the sub-list for method output_type
-	24, // [24:24] is the sub-list for method input_type
-	24, // [24:24] is the sub-list for extension type_name
-	24, // [24:24] is the sub-list for extension extendee
-	0,  // [0:24] is the sub-list for field type_name
+	23, // 18: kythe.proto.CompilationUnit.FileInput.details:type_name -> google.protobuf.Any
+	18, // 19: kythe.proto.KzipInfo.CorpusInfo.language_required_inputs:type_name -> kythe.proto.KzipInfo.CorpusInfo.LanguageRequiredInputsEntry
+	19, // 20: kythe.proto.KzipInfo.CorpusInfo.language_sources:type_name -> kythe.proto.KzipInfo.CorpusInfo.LanguageSourcesEntry
+	20, // 21: kythe.proto.KzipInfo.CorpusInfo.language_cu_info:type_name -> kythe.proto.KzipInfo.CorpusInfo.LanguageCuInfoEntry
+	14, // 22: kythe.proto.KzipInfo.CorporaEntry.value:type_name -> kythe.proto.KzipInfo.CorpusInfo
+	21, // 23: kythe.proto.KzipInfo.CorpusInfo.CUInfo.java_version_count:type_name -> kythe.proto.KzipInfo.CorpusInfo.CUInfo.JavaVersionCountEntry
+	16, // 24: kythe.proto.KzipInfo.CorpusInfo.LanguageRequiredInputsEntry.value:type_name -> kythe.proto.KzipInfo.CorpusInfo.Inputs
+	16, // 25: kythe.proto.KzipInfo.CorpusInfo.LanguageSourcesEntry.value:type_name -> kythe.proto.KzipInfo.CorpusInfo.Inputs
+	17, // 26: kythe.proto.KzipInfo.CorpusInfo.LanguageCuInfoEntry.value:type_name -> kythe.proto.KzipInfo.CorpusInfo.CUInfo
+	27, // [27:27] is the sub-list for method output_type
+	27, // [27:27] is the sub-list for method input_type
+	27, // [27:27] is the sub-list for extension type_name
+	27, // [27:27] is the sub-list for extension extendee
+	0,  // [0:27] is the sub-list for field type_name
 }
 
 func init() { file_kythe_proto_analysis_proto_init() }
@@ -1467,7 +1560,19 @@ func file_kythe_proto_analysis_proto_init() {
 			}
 		}
 		file_kythe_proto_analysis_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*KzipInfo_CorpusInfo_RequiredInputs); i {
+			switch v := v.(*KzipInfo_CorpusInfo_Inputs); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_kythe_proto_analysis_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*KzipInfo_CorpusInfo_CUInfo); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1478,7 +1583,7 @@ func file_kythe_proto_analysis_proto_init() {
 				return nil
 			}
 		}
-		file_kythe_proto_analysis_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
+		file_kythe_proto_analysis_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*IndexedCompilation_Index); i {
 			case 0:
 				return &v.state
@@ -1497,7 +1602,7 @@ func file_kythe_proto_analysis_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_kythe_proto_analysis_proto_rawDesc,
 			NumEnums:      1,
-			NumMessages:   19,
+			NumMessages:   22,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/kythe/proto/analysis_rust_proto/analysis.rs b/kythe/proto/analysis_rust_proto/analysis.rs
index c34dc69a7..f69922e21 100644
--- a/kythe/proto/analysis_rust_proto/analysis.rs
+++ b/kythe/proto/analysis_rust_proto/analysis.rs
@@ -2150,8 +2150,9 @@ impl ::protobuf::reflect::ProtobufValue for KzipInfo {
 #[derive(PartialEq,Clone,Default)]
 pub struct KzipInfo_CorpusInfo {
     // message fields
-    pub language_required_inputs: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs>,
-    pub language_sources: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs>,
+    pub language_required_inputs: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs>,
+    pub language_sources: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs>,
+    pub language_cu_info: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_CUInfo>,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -2171,7 +2172,7 @@ impl KzipInfo_CorpusInfo {
     // repeated .kythe.proto.KzipInfo.CorpusInfo.LanguageRequiredInputsEntry language_required_inputs = 4;
 
 
-    pub fn get_language_required_inputs(&self) -> &::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs> {
+    pub fn get_language_required_inputs(&self) -> &::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs> {
         &self.language_required_inputs
     }
     pub fn clear_language_required_inputs(&mut self) {
@@ -2179,24 +2180,24 @@ impl KzipInfo_CorpusInfo {
     }
 
     // Param is passed by value, moved
-    pub fn set_language_required_inputs(&mut self, v: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs>) {
+    pub fn set_language_required_inputs(&mut self, v: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs>) {
         self.language_required_inputs = v;
     }
 
     // Mutable pointer to the field.
-    pub fn mut_language_required_inputs(&mut self) -> &mut ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs> {
+    pub fn mut_language_required_inputs(&mut self) -> &mut ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs> {
         &mut self.language_required_inputs
     }
 
     // Take field
-    pub fn take_language_required_inputs(&mut self) -> ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs> {
+    pub fn take_language_required_inputs(&mut self) -> ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs> {
         ::std::mem::replace(&mut self.language_required_inputs, ::std::collections::HashMap::new())
     }
 
     // repeated .kythe.proto.KzipInfo.CorpusInfo.LanguageSourcesEntry language_sources = 5;
 
 
-    pub fn get_language_sources(&self) -> &::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs> {
+    pub fn get_language_sources(&self) -> &::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs> {
         &self.language_sources
     }
     pub fn clear_language_sources(&mut self) {
@@ -2204,19 +2205,44 @@ impl KzipInfo_CorpusInfo {
     }
 
     // Param is passed by value, moved
-    pub fn set_language_sources(&mut self, v: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs>) {
+    pub fn set_language_sources(&mut self, v: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs>) {
         self.language_sources = v;
     }
 
     // Mutable pointer to the field.
-    pub fn mut_language_sources(&mut self) -> &mut ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs> {
+    pub fn mut_language_sources(&mut self) -> &mut ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs> {
         &mut self.language_sources
     }
 
     // Take field
-    pub fn take_language_sources(&mut self) -> ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_RequiredInputs> {
+    pub fn take_language_sources(&mut self) -> ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_Inputs> {
         ::std::mem::replace(&mut self.language_sources, ::std::collections::HashMap::new())
     }
+
+    // repeated .kythe.proto.KzipInfo.CorpusInfo.LanguageCuInfoEntry language_cu_info = 6;
+
+
+    pub fn get_language_cu_info(&self) -> &::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_CUInfo> {
+        &self.language_cu_info
+    }
+    pub fn clear_language_cu_info(&mut self) {
+        self.language_cu_info.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_language_cu_info(&mut self, v: ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_CUInfo>) {
+        self.language_cu_info = v;
+    }
+
+    // Mutable pointer to the field.
+    pub fn mut_language_cu_info(&mut self) -> &mut ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_CUInfo> {
+        &mut self.language_cu_info
+    }
+
+    // Take field
+    pub fn take_language_cu_info(&mut self) -> ::std::collections::HashMap<::std::string::String, KzipInfo_CorpusInfo_CUInfo> {
+        ::std::mem::replace(&mut self.language_cu_info, ::std::collections::HashMap::new())
+    }
 }
 
 impl ::protobuf::Message for KzipInfo_CorpusInfo {
@@ -2229,10 +2255,13 @@ impl ::protobuf::Message for KzipInfo_CorpusInfo {
             let (field_number, wire_type) = is.read_tag_unpack()?;
             match field_number {
                 4 => {
-                    ::protobuf::rt::read_map_into::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_RequiredInputs>>(wire_type, is, &mut self.language_required_inputs)?;
+                    ::protobuf::rt::read_map_into::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_Inputs>>(wire_type, is, &mut self.language_required_inputs)?;
                 },
                 5 => {
-                    ::protobuf::rt::read_map_into::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_RequiredInputs>>(wire_type, is, &mut self.language_sources)?;
+                    ::protobuf::rt::read_map_into::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_Inputs>>(wire_type, is, &mut self.language_sources)?;
+                },
+                6 => {
+                    ::protobuf::rt::read_map_into::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_CUInfo>>(wire_type, is, &mut self.language_cu_info)?;
                 },
                 _ => {
                     ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@@ -2246,16 +2275,18 @@ impl ::protobuf::Message for KzipInfo_CorpusInfo {
     #[allow(unused_variables)]
     fn compute_size(&self) -> u32 {
         let mut my_size = 0;
-        my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_RequiredInputs>>(4, &self.language_required_inputs);
-        my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_RequiredInputs>>(5, &self.language_sources);
+        my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_Inputs>>(4, &self.language_required_inputs);
+        my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_Inputs>>(5, &self.language_sources);
+        my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_CUInfo>>(6, &self.language_cu_info);
         my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
         self.cached_size.set(my_size);
         my_size
     }
 
     fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_RequiredInputs>>(4, &self.language_required_inputs, os)?;
-        ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_RequiredInputs>>(5, &self.language_sources, os)?;
+        ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_Inputs>>(4, &self.language_required_inputs, os)?;
+        ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_Inputs>>(5, &self.language_sources, os)?;
+        ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_CUInfo>>(6, &self.language_cu_info, os)?;
         os.write_unknown_fields(self.get_unknown_fields())?;
         ::std::result::Result::Ok(())
     }
@@ -2294,16 +2325,21 @@ impl ::protobuf::Message for KzipInfo_CorpusInfo {
         static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
         descriptor.get(|| {
             let mut fields = ::std::vec::Vec::new();
-            fields.push(::protobuf::reflect::accessor::make_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_RequiredInputs>>(
+            fields.push(::protobuf::reflect::accessor::make_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_Inputs>>(
                 "language_required_inputs",
                 |m: &KzipInfo_CorpusInfo| { &m.language_required_inputs },
                 |m: &mut KzipInfo_CorpusInfo| { &mut m.language_required_inputs },
             ));
-            fields.push(::protobuf::reflect::accessor::make_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_RequiredInputs>>(
+            fields.push(::protobuf::reflect::accessor::make_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_Inputs>>(
                 "language_sources",
                 |m: &KzipInfo_CorpusInfo| { &m.language_sources },
                 |m: &mut KzipInfo_CorpusInfo| { &mut m.language_sources },
             ));
+            fields.push(::protobuf::reflect::accessor::make_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeMessage<KzipInfo_CorpusInfo_CUInfo>>(
+                "language_cu_info",
+                |m: &KzipInfo_CorpusInfo| { &m.language_cu_info },
+                |m: &mut KzipInfo_CorpusInfo| { &mut m.language_cu_info },
+            ));
             ::protobuf::reflect::MessageDescriptor::new_pb_name::<KzipInfo_CorpusInfo>(
                 "KzipInfo.CorpusInfo",
                 fields,
@@ -2322,6 +2358,7 @@ impl ::protobuf::Clear for KzipInfo_CorpusInfo {
     fn clear(&mut self) {
         self.language_required_inputs.clear();
         self.language_sources.clear();
+        self.language_cu_info.clear();
         self.unknown_fields.clear();
     }
 }
@@ -2339,7 +2376,7 @@ impl ::protobuf::reflect::ProtobufValue for KzipInfo_CorpusInfo {
 }
 
 #[derive(PartialEq,Clone,Default)]
-pub struct KzipInfo_CorpusInfo_RequiredInputs {
+pub struct KzipInfo_CorpusInfo_Inputs {
     // message fields
     pub count: i32,
     // special fields
@@ -2347,14 +2384,14 @@ pub struct KzipInfo_CorpusInfo_RequiredInputs {
     pub cached_size: ::protobuf::CachedSize,
 }
 
-impl<'a> ::std::default::Default for &'a KzipInfo_CorpusInfo_RequiredInputs {
-    fn default() -> &'a KzipInfo_CorpusInfo_RequiredInputs {
-        <KzipInfo_CorpusInfo_RequiredInputs as ::protobuf::Message>::default_instance()
+impl<'a> ::std::default::Default for &'a KzipInfo_CorpusInfo_Inputs {
+    fn default() -> &'a KzipInfo_CorpusInfo_Inputs {
+        <KzipInfo_CorpusInfo_Inputs as ::protobuf::Message>::default_instance()
     }
 }
 
-impl KzipInfo_CorpusInfo_RequiredInputs {
-    pub fn new() -> KzipInfo_CorpusInfo_RequiredInputs {
+impl KzipInfo_CorpusInfo_Inputs {
+    pub fn new() -> KzipInfo_CorpusInfo_Inputs {
         ::std::default::Default::default()
     }
 
@@ -2374,7 +2411,7 @@ impl KzipInfo_CorpusInfo_RequiredInputs {
     }
 }
 
-impl ::protobuf::Message for KzipInfo_CorpusInfo_RequiredInputs {
+impl ::protobuf::Message for KzipInfo_CorpusInfo_Inputs {
     fn is_initialized(&self) -> bool {
         true
     }
@@ -2444,8 +2481,8 @@ impl ::protobuf::Message for KzipInfo_CorpusInfo_RequiredInputs {
         Self::descriptor_static()
     }
 
-    fn new() -> KzipInfo_CorpusInfo_RequiredInputs {
-        KzipInfo_CorpusInfo_RequiredInputs::new()
+    fn new() -> KzipInfo_CorpusInfo_Inputs {
+        KzipInfo_CorpusInfo_Inputs::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -2454,37 +2491,226 @@ impl ::protobuf::Message for KzipInfo_CorpusInfo_RequiredInputs {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
                 "count",
-                |m: &KzipInfo_CorpusInfo_RequiredInputs| { &m.count },
-                |m: &mut KzipInfo_CorpusInfo_RequiredInputs| { &mut m.count },
+                |m: &KzipInfo_CorpusInfo_Inputs| { &m.count },
+                |m: &mut KzipInfo_CorpusInfo_Inputs| { &mut m.count },
+            ));
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<KzipInfo_CorpusInfo_Inputs>(
+                "KzipInfo.CorpusInfo.Inputs",
+                fields,
+                file_descriptor_proto()
+            )
+        })
+    }
+
+    fn default_instance() -> &'static KzipInfo_CorpusInfo_Inputs {
+        static instance: ::protobuf::rt::LazyV2<KzipInfo_CorpusInfo_Inputs> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(KzipInfo_CorpusInfo_Inputs::new)
+    }
+}
+
+impl ::protobuf::Clear for KzipInfo_CorpusInfo_Inputs {
+    fn clear(&mut self) {
+        self.count = 0;
+        self.unknown_fields.clear();
+    }
+}
+
+impl ::std::fmt::Debug for KzipInfo_CorpusInfo_Inputs {
+    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+        ::protobuf::text_format::fmt(self, f)
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for KzipInfo_CorpusInfo_Inputs {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Message(self)
+    }
+}
+
+#[derive(PartialEq,Clone,Default)]
+pub struct KzipInfo_CorpusInfo_CUInfo {
+    // message fields
+    pub count: i32,
+    pub java_version_count: ::std::collections::HashMap<i32, i32>,
+    // special fields
+    pub unknown_fields: ::protobuf::UnknownFields,
+    pub cached_size: ::protobuf::CachedSize,
+}
+
+impl<'a> ::std::default::Default for &'a KzipInfo_CorpusInfo_CUInfo {
+    fn default() -> &'a KzipInfo_CorpusInfo_CUInfo {
+        <KzipInfo_CorpusInfo_CUInfo as ::protobuf::Message>::default_instance()
+    }
+}
+
+impl KzipInfo_CorpusInfo_CUInfo {
+    pub fn new() -> KzipInfo_CorpusInfo_CUInfo {
+        ::std::default::Default::default()
+    }
+
+    // int32 count = 1;
+
+
+    pub fn get_count(&self) -> i32 {
+        self.count
+    }
+    pub fn clear_count(&mut self) {
+        self.count = 0;
+    }
+
+    // Param is passed by value, moved
+    pub fn set_count(&mut self, v: i32) {
+        self.count = v;
+    }
+
+    // repeated .kythe.proto.KzipInfo.CorpusInfo.CUInfo.JavaVersionCountEntry java_version_count = 2;
+
+
+    pub fn get_java_version_count(&self) -> &::std::collections::HashMap<i32, i32> {
+        &self.java_version_count
+    }
+    pub fn clear_java_version_count(&mut self) {
+        self.java_version_count.clear();
+    }
+
+    // Param is passed by value, moved
+    pub fn set_java_version_count(&mut self, v: ::std::collections::HashMap<i32, i32>) {
+        self.java_version_count = v;
+    }
+
+    // Mutable pointer to the field.
+    pub fn mut_java_version_count(&mut self) -> &mut ::std::collections::HashMap<i32, i32> {
+        &mut self.java_version_count
+    }
+
+    // Take field
+    pub fn take_java_version_count(&mut self) -> ::std::collections::HashMap<i32, i32> {
+        ::std::mem::replace(&mut self.java_version_count, ::std::collections::HashMap::new())
+    }
+}
+
+impl ::protobuf::Message for KzipInfo_CorpusInfo_CUInfo {
+    fn is_initialized(&self) -> bool {
+        true
+    }
+
+    fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        while !is.eof()? {
+            let (field_number, wire_type) = is.read_tag_unpack()?;
+            match field_number {
+                1 => {
+                    if wire_type != ::protobuf::wire_format::WireTypeVarint {
+                        return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
+                    }
+                    let tmp = is.read_int32()?;
+                    self.count = tmp;
+                },
+                2 => {
+                    ::protobuf::rt::read_map_into::<::protobuf::types::ProtobufTypeInt32, ::protobuf::types::ProtobufTypeInt32>(wire_type, is, &mut self.java_version_count)?;
+                },
+                _ => {
+                    ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
+                },
+            };
+        }
+        ::std::result::Result::Ok(())
+    }
+
+    // Compute sizes of nested messages
+    #[allow(unused_variables)]
+    fn compute_size(&self) -> u32 {
+        let mut my_size = 0;
+        if self.count != 0 {
+            my_size += ::protobuf::rt::value_size(1, self.count, ::protobuf::wire_format::WireTypeVarint);
+        }
+        my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeInt32, ::protobuf::types::ProtobufTypeInt32>(2, &self.java_version_count);
+        my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
+        self.cached_size.set(my_size);
+        my_size
+    }
+
+    fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
+        if self.count != 0 {
+            os.write_int32(1, self.count)?;
+        }
+        ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeInt32, ::protobuf::types::ProtobufTypeInt32>(2, &self.java_version_count, os)?;
+        os.write_unknown_fields(self.get_unknown_fields())?;
+        ::std::result::Result::Ok(())
+    }
+
+    fn get_cached_size(&self) -> u32 {
+        self.cached_size.get()
+    }
+
+    fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
+        &self.unknown_fields
+    }
+
+    fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
+        &mut self.unknown_fields
+    }
+
+    fn as_any(&self) -> &dyn (::std::any::Any) {
+        self as &dyn (::std::any::Any)
+    }
+    fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
+        self as &mut dyn (::std::any::Any)
+    }
+    fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
+        self
+    }
+
+    fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
+        Self::descriptor_static()
+    }
+
+    fn new() -> KzipInfo_CorpusInfo_CUInfo {
+        KzipInfo_CorpusInfo_CUInfo::new()
+    }
+
+    fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            let mut fields = ::std::vec::Vec::new();
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
+                "count",
+                |m: &KzipInfo_CorpusInfo_CUInfo| { &m.count },
+                |m: &mut KzipInfo_CorpusInfo_CUInfo| { &mut m.count },
+            ));
+            fields.push(::protobuf::reflect::accessor::make_map_accessor::<_, ::protobuf::types::ProtobufTypeInt32, ::protobuf::types::ProtobufTypeInt32>(
+                "java_version_count",
+                |m: &KzipInfo_CorpusInfo_CUInfo| { &m.java_version_count },
+                |m: &mut KzipInfo_CorpusInfo_CUInfo| { &mut m.java_version_count },
             ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<KzipInfo_CorpusInfo_RequiredInputs>(
-                "KzipInfo.CorpusInfo.RequiredInputs",
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<KzipInfo_CorpusInfo_CUInfo>(
+                "KzipInfo.CorpusInfo.CUInfo",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static KzipInfo_CorpusInfo_RequiredInputs {
-        static instance: ::protobuf::rt::LazyV2<KzipInfo_CorpusInfo_RequiredInputs> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(KzipInfo_CorpusInfo_RequiredInputs::new)
+    fn default_instance() -> &'static KzipInfo_CorpusInfo_CUInfo {
+        static instance: ::protobuf::rt::LazyV2<KzipInfo_CorpusInfo_CUInfo> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(KzipInfo_CorpusInfo_CUInfo::new)
     }
 }
 
-impl ::protobuf::Clear for KzipInfo_CorpusInfo_RequiredInputs {
+impl ::protobuf::Clear for KzipInfo_CorpusInfo_CUInfo {
     fn clear(&mut self) {
         self.count = 0;
+        self.java_version_count.clear();
         self.unknown_fields.clear();
     }
 }
 
-impl ::std::fmt::Debug for KzipInfo_CorpusInfo_RequiredInputs {
+impl ::std::fmt::Debug for KzipInfo_CorpusInfo_CUInfo {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for KzipInfo_CorpusInfo_RequiredInputs {
+impl ::protobuf::reflect::ProtobufValue for KzipInfo_CorpusInfo_CUInfo {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
@@ -3924,40 +4150,49 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     proto.FileInfoR\x04info\x12.\n\x07details\x18\x04\x20\x03(\x0b2\x14.goog\
     le.protobuf.AnyR\x07detailsJ\x04\x08\x03\x10\x04\x1a/\n\x03Env\x12\x12\n\
     \x04name\x18\x01\x20\x01(\tR\x04name\x12\x14\n\x05value\x18\x02\x20\x01(\
-    \tR\x05valueJ\x04\x08\x02\x10\x03\"\xb3\x06\n\x08KzipInfo\x12<\n\x07corp\
-    ora\x18\x01\x20\x03(\x0b2\".kythe.proto.KzipInfo.CorporaEntryR\x07corpor\
-    a\x12\x12\n\x04size\x18\x04\x20\x01(\x03R\x04size\x12%\n\x0eabsolute_pat\
-    hs\x18\x06\x20\x03(\tR\rabsolutePaths\x120\n\x14critical_kzip_errors\x18\
-    \x05\x20\x03(\tR\x12criticalKzipErrors\x1a\x91\x04\n\nCorpusInfo\x12v\n\
+    \tR\x05valueJ\x04\x08\x02\x10\x03\"\xba\t\n\x08KzipInfo\x12<\n\x07corpor\
+    a\x18\x01\x20\x03(\x0b2\".kythe.proto.KzipInfo.CorporaEntryR\x07corpora\
+    \x12\x12\n\x04size\x18\x04\x20\x01(\x03R\x04size\x12%\n\x0eabsolute_path\
+    s\x18\x06\x20\x03(\tR\rabsolutePaths\x120\n\x14critical_kzip_errors\x18\
+    \x05\x20\x03(\tR\x12criticalKzipErrors\x1a\x98\x07\n\nCorpusInfo\x12v\n\
     \x18language_required_inputs\x18\x04\x20\x03(\x0b2<.kythe.proto.KzipInfo\
     .CorpusInfo.LanguageRequiredInputsEntryR\x16languageRequiredInputs\x12`\
     \n\x10language_sources\x18\x05\x20\x03(\x0b25.kythe.proto.KzipInfo.Corpu\
-    sInfo.LanguageSourcesEntryR\x0flanguageSources\x1a&\n\x0eRequiredInputs\
-    \x12\x14\n\x05count\x18\x01\x20\x01(\x05R\x05count\x1az\n\x1bLanguageReq\
-    uiredInputsEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12E\n\x05v\
-    alue\x18\x02\x20\x01(\x0b2/.kythe.proto.KzipInfo.CorpusInfo.RequiredInpu\
-    tsR\x05value:\x028\x01\x1as\n\x14LanguageSourcesEntry\x12\x10\n\x03key\
-    \x18\x01\x20\x01(\tR\x03key\x12E\n\x05value\x18\x02\x20\x01(\x0b2/.kythe\
-    .proto.KzipInfo.CorpusInfo.RequiredInputsR\x05value:\x028\x01J\x04\x08\
-    \x01\x10\x02J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04\x1a\\\n\x0cCorpor\
-    aEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x126\n\x05value\x18\
-    \x02\x20\x01(\x0b2\x20.kythe.proto.KzipInfo.CorpusInfoR\x05value:\x028\
-    \x01J\x04\x08\x02\x10\x03J\x04\x08\x03\x10\x04\"V\n\rBuildMetadata\x12E\
-    \n\x10commit_timestamp\x18\x01\x20\x01(\x0b2\x1a.google.protobuf.Timesta\
-    mpR\x0fcommitTimestamp\";\n\x0cFilesRequest\x12+\n\x05files\x18\x01\x20\
-    \x03(\x0b2\x15.kythe.proto.FileInfoR\x05files\"6\n\x08FileInfo\x12\x12\n\
-    \x04path\x18\x01\x20\x01(\tR\x04path\x12\x16\n\x06digest\x18\x02\x20\x01\
-    (\tR\x06digest\"i\n\x08FileData\x12\x18\n\x07content\x18\x01\x20\x01(\
-    \x0cR\x07content\x12)\n\x04info\x18\x02\x20\x01(\x0b2\x15.kythe.proto.Fi\
-    leInfoR\x04info\x12\x18\n\x07missing\x18\x03\x20\x01(\x08R\x07missing\"r\
-    \n\x11CompilationBundle\x120\n\x04unit\x18\x01\x20\x01(\x0b2\x1c.kythe.p\
-    roto.CompilationUnitR\x04unit\x12+\n\x05files\x18\x02\x20\x03(\x0b2\x15.\
-    kythe.proto.FileDataR\x05files\"\xaa\x01\n\x12IndexedCompilation\x120\n\
-    \x04unit\x18\x01\x20\x01(\x0b2\x1c.kythe.proto.CompilationUnitR\x04unit\
-    \x12;\n\x05index\x18\x02\x20\x01(\x0b2%.kythe.proto.IndexedCompilation.I\
-    ndexR\x05index\x1a%\n\x05Index\x12\x1c\n\trevisions\x18\x01\x20\x03(\tR\
-    \trevisionsB7\n\x1fcom.google.devtools.kythe.protoZ\x11analysis_go_proto\
-    \xf8\x01\x01b\x06proto3\
+    sInfo.LanguageSourcesEntryR\x0flanguageSources\x12^\n\x10language_cu_inf\
+    o\x18\x06\x20\x03(\x0b24.kythe.proto.KzipInfo.CorpusInfo.LanguageCuInfoE\
+    ntryR\x0elanguageCuInfo\x1a\x1e\n\x06Inputs\x12\x14\n\x05count\x18\x01\
+    \x20\x01(\x05R\x05count\x1a\xd0\x01\n\x06CUInfo\x12\x14\n\x05count\x18\
+    \x01\x20\x01(\x05R\x05count\x12k\n\x12java_version_count\x18\x02\x20\x03\
+    (\x0b2=.kythe.proto.KzipInfo.CorpusInfo.CUInfo.JavaVersionCountEntryR\
+    \x10javaVersionCount\x1aC\n\x15JavaVersionCountEntry\x12\x10\n\x03key\
+    \x18\x01\x20\x01(\x05R\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\x05R\
+    \x05value:\x028\x01\x1ar\n\x1bLanguageRequiredInputsEntry\x12\x10\n\x03k\
+    ey\x18\x01\x20\x01(\tR\x03key\x12=\n\x05value\x18\x02\x20\x01(\x0b2'.kyt\
+    he.proto.KzipInfo.CorpusInfo.InputsR\x05value:\x028\x01\x1ak\n\x14Langua\
+    geSourcesEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12=\n\x05val\
+    ue\x18\x02\x20\x01(\x0b2'.kythe.proto.KzipInfo.CorpusInfo.InputsR\x05val\
+    ue:\x028\x01\x1aj\n\x13LanguageCuInfoEntry\x12\x10\n\x03key\x18\x01\x20\
+    \x01(\tR\x03key\x12=\n\x05value\x18\x02\x20\x01(\x0b2'.kythe.proto.KzipI\
+    nfo.CorpusInfo.CUInfoR\x05value:\x028\x01J\x04\x08\x01\x10\x02J\x04\x08\
+    \x02\x10\x03J\x04\x08\x03\x10\x04\x1a\\\n\x0cCorporaEntry\x12\x10\n\x03k\
+    ey\x18\x01\x20\x01(\tR\x03key\x126\n\x05value\x18\x02\x20\x01(\x0b2\x20.\
+    kythe.proto.KzipInfo.CorpusInfoR\x05value:\x028\x01J\x04\x08\x02\x10\x03\
+    J\x04\x08\x03\x10\x04\"V\n\rBuildMetadata\x12E\n\x10commit_timestamp\x18\
+    \x01\x20\x01(\x0b2\x1a.google.protobuf.TimestampR\x0fcommitTimestamp\";\
+    \n\x0cFilesRequest\x12+\n\x05files\x18\x01\x20\x03(\x0b2\x15.kythe.proto\
+    .FileInfoR\x05files\"6\n\x08FileInfo\x12\x12\n\x04path\x18\x01\x20\x01(\
+    \tR\x04path\x12\x16\n\x06digest\x18\x02\x20\x01(\tR\x06digest\"i\n\x08Fi\
+    leData\x12\x18\n\x07content\x18\x01\x20\x01(\x0cR\x07content\x12)\n\x04i\
+    nfo\x18\x02\x20\x01(\x0b2\x15.kythe.proto.FileInfoR\x04info\x12\x18\n\
+    \x07missing\x18\x03\x20\x01(\x08R\x07missing\"r\n\x11CompilationBundle\
+    \x120\n\x04unit\x18\x01\x20\x01(\x0b2\x1c.kythe.proto.CompilationUnitR\
+    \x04unit\x12+\n\x05files\x18\x02\x20\x03(\x0b2\x15.kythe.proto.FileDataR\
+    \x05files\"\xaa\x01\n\x12IndexedCompilation\x120\n\x04unit\x18\x01\x20\
+    \x01(\x0b2\x1c.kythe.proto.CompilationUnitR\x04unit\x12;\n\x05index\x18\
+    \x02\x20\x01(\x0b2%.kythe.proto.IndexedCompilation.IndexR\x05index\x1a%\
+    \n\x05Index\x12\x1c\n\trevisions\x18\x01\x20\x03(\tR\trevisionsB7\n\x1fc\
+    om.google.devtools.kythe.protoZ\x11analysis_go_proto\xf8\x01\x01b\x06pro\
+    to3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;


Test patch:
diff --git a/kythe/go/platform/kzip/info/info_test.go b/kythe/go/platform/kzip/info/info_test.go
index bc77bab60..e7dc1c365 100644
--- a/kythe/go/platform/kzip/info/info_test.go
+++ b/kythe/go/platform/kzip/info/info_test.go
@@ -32,16 +32,27 @@ func TestMergeKzipInfo(t *testing.T) {
 		{
 			Corpora: map[string]*apb.KzipInfo_CorpusInfo{
 				"corpus1": {
-					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 						"python": {
 							Count: 2,
 						},
 					},
-					LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+					LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 						"python": {
 							Count: 1,
 						},
 					},
+					LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
+						"python": {
+							Count: 1,
+						},
+						"java": {
+							Count: 20,
+							JavaVersionCount: map[int32]int32{
+								7: 10,
+							},
+						},
+					},
 				},
 			},
 			CriticalKzipErrors: []string{"foo.py doesn't have a required_input"},
@@ -50,14 +61,26 @@ func TestMergeKzipInfo(t *testing.T) {
 		{
 			Corpora: map[string]*apb.KzipInfo_CorpusInfo{
 				"corpus1": {
-					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 						"python": {
 							Count: 1,
 						},
 					},
+					LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
+						"python": {
+							Count: 1,
+						},
+						"java": {
+							Count: 2,
+							JavaVersionCount: map[int32]int32{
+								6: 1,
+								7: 7,
+							},
+						},
+					},
 				},
 				"corpus2": {
-					LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+					LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 						"python": {
 							Count: 5,
 						},
@@ -65,9 +88,17 @@ func TestMergeKzipInfo(t *testing.T) {
 							Count: 3,
 						},
 					},
+					LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
+						"java": {
+							Count: 3,
+							JavaVersionCount: map[int32]int32{
+								4: 1,
+							},
+						},
+					},
 				},
 				"unnamed_required_input_corpus": {
-					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 						"python": {
 							Count: 9,
 						},
@@ -88,19 +119,31 @@ func TestMergeKzipInfo(t *testing.T) {
 	want := &apb.KzipInfo{
 		Corpora: map[string]*apb.KzipInfo_CorpusInfo{
 			"corpus1": {
-				LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+				LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 					"python": {
 						Count: 3,
 					},
 				},
-				LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+				LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 					"python": {
 						Count: 1,
 					},
 				},
+				LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
+					"python": {
+						Count: 2,
+					},
+					"java": {
+						Count: 22,
+						JavaVersionCount: map[int32]int32{
+							6: 1,
+							7: 17,
+						},
+					},
+				},
 			},
 			"corpus2": {
-				LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+				LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 					"python": {
 						Count: 5,
 					},
@@ -108,9 +151,17 @@ func TestMergeKzipInfo(t *testing.T) {
 						Count: 3,
 					},
 				},
+				LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
+					"java": {
+						Count: 3,
+						JavaVersionCount: map[int32]int32{
+							4: 1,
+						},
+					},
+				},
 			},
 			"unnamed_required_input_corpus": {
-				LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+				LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 					"python": {
 						Count: 9,
 					},
@@ -127,7 +178,7 @@ func TestMergeKzipInfo(t *testing.T) {
 		Size:               40,
 	}
 	wantTotal := &apb.KzipInfo_CorpusInfo{
-		LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+		LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 			"python": {
 				Count: 12,
 			},
@@ -138,7 +189,7 @@ func TestMergeKzipInfo(t *testing.T) {
 				Count: 2,
 			},
 		},
-		LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+		LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 			"python": {
 				Count: 6,
 			},
@@ -146,6 +197,19 @@ func TestMergeKzipInfo(t *testing.T) {
 				Count: 3,
 			},
 		},
+		LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
+			"python": {
+				Count: 2,
+			},
+			"java": {
+				Count: 25,
+				JavaVersionCount: map[int32]int32{
+					4: 1,
+					6: 1,
+					7: 17,
+				},
+			},
+		},
 	}
 
 	got := MergeKzipInfo(infos)
@@ -175,10 +239,12 @@ func makeKzip(t *testing.T, u *apb.CompilationUnit) *bytes.Reader {
 }
 
 var infoTests = []struct {
-	in  *apb.CompilationUnit
-	out *apb.KzipInfo
+	name string
+	in   *apb.CompilationUnit
+	out  *apb.KzipInfo
 }{
 	{
+		"required counts",
 		&apb.CompilationUnit{
 			VName: &spb.VName{Language: "python"},
 			RequiredInput: []*apb.CompilationUnit_FileInput{
@@ -191,7 +257,14 @@ var infoTests = []struct {
 		&apb.KzipInfo{
 			Corpora: map[string]*apb.KzipInfo_CorpusInfo{
 				"mycorpus": {
-					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
+						"python": {
+							Count: 1,
+						},
+					},
+				},
+				"": {
+					LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
 						"python": {
 							Count: 1,
 						},
@@ -202,6 +275,7 @@ var infoTests = []struct {
 	},
 
 	{
+		"No corpus for required input",
 		&apb.CompilationUnit{
 			VName: &spb.VName{Language: "python"},
 			RequiredInput: []*apb.CompilationUnit_FileInput{
@@ -212,6 +286,15 @@ var infoTests = []struct {
 			},
 		},
 		&apb.KzipInfo{
+			Corpora: map[string]*apb.KzipInfo_CorpusInfo{
+				"": {
+					LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
+						"python": {
+							Count: 1,
+						},
+					},
+				},
+			},
 			CriticalKzipErrors: []string{"unable to determine corpus for required_input \"file1.py\" in CU language:\"python\""},
 		},
 	},
@@ -220,8 +303,9 @@ var infoTests = []struct {
 	// entry. This test case checks that the required_input path is normalized
 	// before doing the check.
 	{
+		"normalize paths",
 		&apb.CompilationUnit{
-			VName: &spb.VName{Language: "c++"},
+			VName: &spb.VName{Language: "c++", Corpus: "kythe"},
 			RequiredInput: []*apb.CompilationUnit_FileInput{
 				{
 					VName: &spb.VName{
@@ -240,12 +324,17 @@ var infoTests = []struct {
 		&apb.KzipInfo{
 			Corpora: map[string]*apb.KzipInfo_CorpusInfo{
 				"kythe": {
-					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+					LanguageRequiredInputs: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
+						"c++": {
+							Count: 1,
+						},
+					},
+					LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_Inputs{
 						"c++": {
 							Count: 1,
 						},
 					},
-					LanguageSources: map[string]*apb.KzipInfo_CorpusInfo_RequiredInputs{
+					LanguageCuInfo: map[string]*apb.KzipInfo_CorpusInfo_CUInfo{
 						"c++": {
 							Count: 1,
 						},
@@ -266,7 +355,7 @@ func TestInfo(t *testing.T) {
 		}
 
 		if diff := compare.ProtoDiff(testcase.out, got); diff != "" {
-			t.Errorf("KzipInfo() output differs from expected (-: found, +: expected)\n%s", diff)
+			t.Errorf("KzipInfo() output differs from expected for %s (-: found, +: expected)\n%s", testcase.name, diff)
 		}
 	}
 }