cmd/protoc-gen-go: make deprecated messages more descriptive

Also respect the file-wide deprecation option by treating every
identifier within the file as deprecated.

Change-Id: Ic3a5e84c2d90bbcbefc0a1b3272cc50554b94218
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/462315
Reviewed-by: Lasse Folger <lassefolger@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/cmd/protoc-gen-go/internal_gengo/main.go b/cmd/protoc-gen-go/internal_gengo/main.go
index d34efa9..f8b76bf 100644
--- a/cmd/protoc-gen-go/internal_gengo/main.go
+++ b/cmd/protoc-gen-go/internal_gengo/main.go
@@ -228,6 +228,7 @@
 	// Enum type declaration.
 	g.Annotate(e.GoIdent.GoName, e.Location)
 	leadingComments := appendDeprecationSuffix(e.Comments.Leading,
+		e.Desc.ParentFile(),
 		e.Desc.Options().(*descriptorpb.EnumOptions).GetDeprecated())
 	g.P(leadingComments,
 		"type ", e.GoIdent, " int32")
@@ -237,6 +238,7 @@
 	for _, value := range e.Values {
 		g.Annotate(value.GoIdent.GoName, value.Location)
 		leadingComments := appendDeprecationSuffix(value.Comments.Leading,
+			value.Desc.ParentFile(),
 			value.Desc.Options().(*descriptorpb.EnumValueOptions).GetDeprecated())
 		g.P(leadingComments,
 			value.GoIdent, " ", e.GoIdent, " = ", value.Desc.Number(),
@@ -322,6 +324,7 @@
 	// Message type declaration.
 	g.Annotate(m.GoIdent.GoName, m.Location)
 	leadingComments := appendDeprecationSuffix(m.Comments.Leading,
+		m.Desc.ParentFile(),
 		m.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
 	g.P(leadingComments,
 		"type ", m.GoIdent, " struct {")
@@ -421,6 +424,7 @@
 	}
 	g.Annotate(m.GoIdent.GoName+"."+name, field.Location)
 	leadingComments := appendDeprecationSuffix(field.Comments.Leading,
+		field.Desc.ParentFile(),
 		field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 	g.P(leadingComments,
 		name, " ", goType, tags,
@@ -561,6 +565,7 @@
 		defaultValue := fieldDefaultValue(g, f, m, field)
 		g.Annotate(m.GoIdent.GoName+".Get"+field.GoName, field.Location)
 		leadingComments := appendDeprecationSuffix("",
+			field.Desc.ParentFile(),
 			field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 		switch {
 		case field.Desc.IsWeak():
@@ -611,6 +616,7 @@
 
 		g.Annotate(m.GoIdent.GoName+".Set"+field.GoName, field.Location)
 		leadingComments := appendDeprecationSuffix("",
+			field.Desc.ParentFile(),
 			field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 		g.P(leadingComments, "func (x *", m.GoIdent, ") Set", field.GoName, "(v ", protoPackage.Ident("Message"), ") {")
 		g.P("var w *", protoimplPackage.Ident("WeakFields"))
@@ -773,6 +779,7 @@
 			leadingComments += protogen.Comments(fmt.Sprintf(" %v %v %v = %v;\n",
 				xd.Cardinality(), typeName, fieldName, xd.Number()))
 			leadingComments = appendDeprecationSuffix(leadingComments,
+				x.Desc.ParentFile(),
 				x.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 			g.P(leadingComments,
 				"E_", x.GoIdent, " = &", extensionTypesVarName(f), "[", allExtensionsByPtr[x], "]",
@@ -807,6 +814,7 @@
 				tags = append(tags, gotrackTags...)
 			}
 			leadingComments := appendDeprecationSuffix(field.Comments.Leading,
+				field.Desc.ParentFile(),
 				field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
 			g.P(leadingComments,
 				field.GoName, " ", goType, tags,
@@ -860,14 +868,18 @@
 }
 
 // appendDeprecationSuffix optionally appends a deprecation notice as a suffix.
-func appendDeprecationSuffix(prefix protogen.Comments, deprecated bool) protogen.Comments {
-	if !deprecated {
+func appendDeprecationSuffix(prefix protogen.Comments, parentFile protoreflect.FileDescriptor, deprecated bool) protogen.Comments {
+	fileDeprecated := parentFile.Options().(*descriptorpb.FileOptions).GetDeprecated()
+	if !deprecated && !fileDeprecated {
 		return prefix
 	}
 	if prefix != "" {
 		prefix += "\n"
 	}
-	return prefix + " Deprecated: Do not use.\n"
+	if fileDeprecated {
+		return prefix + " Deprecated: The entire proto file " + protogen.Comments(parentFile.Path()) + " is marked as deprecated.\n"
+	}
+	return prefix + " Deprecated: Marked as deprecated in " + protogen.Comments(parentFile.Path()) + ".\n"
 }
 
 // trailingComment is like protogen.Comments, but lacks a trailing newline.
diff --git a/cmd/protoc-gen-go/testdata/comments/deprecated.pb.go b/cmd/protoc-gen-go/testdata/comments/deprecated.pb.go
index a23f64c..906a421 100644
--- a/cmd/protoc-gen-go/testdata/comments/deprecated.pb.go
+++ b/cmd/protoc-gen-go/testdata/comments/deprecated.pb.go
@@ -14,11 +14,11 @@
 	sync "sync"
 )
 
-// Deprecated: Do not use.
+// Deprecated: The entire proto file cmd/protoc-gen-go/testdata/comments/deprecated.proto is marked as deprecated.
 type DeprecatedEnum int32
 
 const (
-	// Deprecated: Do not use.
+	// Deprecated: The entire proto file cmd/protoc-gen-go/testdata/comments/deprecated.proto is marked as deprecated.
 	DeprecatedEnum_DEPRECATED DeprecatedEnum = 0
 )
 
@@ -59,13 +59,13 @@
 	return file_cmd_protoc_gen_go_testdata_comments_deprecated_proto_rawDescGZIP(), []int{0}
 }
 
-// Deprecated: Do not use.
+// Deprecated: The entire proto file cmd/protoc-gen-go/testdata/comments/deprecated.proto is marked as deprecated.
 type DeprecatedMessage struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	// Deprecated: Do not use.
+	// Deprecated: The entire proto file cmd/protoc-gen-go/testdata/comments/deprecated.proto is marked as deprecated.
 	DeprecatedField string `protobuf:"bytes,1,opt,name=deprecated_field,json=deprecatedField,proto3" json:"deprecated_field,omitempty"`
 }
 
@@ -101,7 +101,7 @@
 	return file_cmd_protoc_gen_go_testdata_comments_deprecated_proto_rawDescGZIP(), []int{0}
 }
 
-// Deprecated: Do not use.
+// Deprecated: The entire proto file cmd/protoc-gen-go/testdata/comments/deprecated.proto is marked as deprecated.
 func (x *DeprecatedMessage) GetDeprecatedField() string {
 	if x != nil {
 		return x.DeprecatedField
diff --git a/internal/testprotos/test/test.pb.go b/internal/testprotos/test/test.pb.go
index 4263ff9..a9b14ee 100644
--- a/internal/testprotos/test/test.pb.go
+++ b/internal/testprotos/test/test.pb.go
@@ -190,11 +190,11 @@
 	return file_internal_testprotos_test_test_proto_rawDescGZIP(), []int{0, 0}
 }
 
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in internal/testprotos/test/test.proto.
 type TestDeprecatedMessage_DeprecatedEnum int32
 
 const (
-	// Deprecated: Do not use.
+	// Deprecated: Marked as deprecated in internal/testprotos/test/test.proto.
 	TestDeprecatedMessage_DEPRECATED TestDeprecatedMessage_DeprecatedEnum = 0
 )
 
@@ -1116,13 +1116,13 @@
 
 func (*TestAllTypes_OneofOptionalUint32) isTestAllTypes_OneofOptional() {}
 
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in internal/testprotos/test/test.proto.
 type TestDeprecatedMessage struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	// Deprecated: Do not use.
+	// Deprecated: Marked as deprecated in internal/testprotos/test/test.proto.
 	DeprecatedInt32 *int32 `protobuf:"varint,1,opt,name=deprecated_int32,json=deprecatedInt32" json:"deprecated_int32,omitempty"`
 	// Types that are assignable to DeprecatedOneof:
 	//	*TestDeprecatedMessage_DeprecatedOneofField
@@ -1161,7 +1161,7 @@
 	return file_internal_testprotos_test_test_proto_rawDescGZIP(), []int{1}
 }
 
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in internal/testprotos/test/test.proto.
 func (x *TestDeprecatedMessage) GetDeprecatedInt32() int32 {
 	if x != nil && x.DeprecatedInt32 != nil {
 		return *x.DeprecatedInt32
@@ -1176,7 +1176,7 @@
 	return nil
 }
 
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in internal/testprotos/test/test.proto.
 func (x *TestDeprecatedMessage) GetDeprecatedOneofField() int32 {
 	if x, ok := x.GetDeprecatedOneof().(*TestDeprecatedMessage_DeprecatedOneofField); ok {
 		return x.DeprecatedOneofField
@@ -1189,7 +1189,7 @@
 }
 
 type TestDeprecatedMessage_DeprecatedOneofField struct {
-	// Deprecated: Do not use.
+	// Deprecated: Marked as deprecated in internal/testprotos/test/test.proto.
 	DeprecatedOneofField int32 `protobuf:"varint,2,opt,name=deprecated_oneof_field,json=deprecatedOneofField,oneof"`
 }
 
diff --git a/types/descriptorpb/descriptor.pb.go b/types/descriptorpb/descriptor.pb.go
index c62f27a..db577ee 100644
--- a/types/descriptorpb/descriptor.pb.go
+++ b/types/descriptorpb/descriptor.pb.go
@@ -1396,7 +1396,7 @@
 	JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"`
 	// This option does nothing.
 	//
-	// Deprecated: Do not use.
+	// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 	JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"`
 	// If set true, then the Java2 code generator will generate code that
 	// throws an exception whenever an attempt is made to assign a non-UTF-8
@@ -1530,7 +1530,7 @@
 	return Default_FileOptions_JavaMultipleFiles
 }
 
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in google/protobuf/descriptor.proto.
 func (x *FileOptions) GetJavaGenerateEqualsAndHash() bool {
 	if x != nil && x.JavaGenerateEqualsAndHash != nil {
 		return *x.JavaGenerateEqualsAndHash