From 57c9cb448950e391885415d9ac8509c4b582d6aa Mon Sep 17 00:00:00 2001
From: Sam Guymer <sam@guymer.me>
Date: Sun, 8 Oct 2023 15:19:12 +1000
Subject: [PATCH] Avoid deprecation warnings in generated code

Add `nowarn` annotations so generated code does not produce deprecation
warnings during compilation.
---
 build.sbt                                     |  4 +---
 .../compiler/DescriptorImplicits.scala        | 13 ++++++++++-
 .../scalapb/compiler/ProtobufGenerator.scala  | 22 +++++++++++++++----
 .../protobuf/descriptor/FileOptions.scala     |  5 +++--
 .../protobuf/descriptor/FileOptions.scala     |  7 ++++--
 5 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/build.sbt b/build.sbt
index 9deb82454..f94d7b952 100644
--- a/build.sbt
+++ b/build.sbt
@@ -58,7 +58,6 @@ lazy val runtime = (projectMatrix in file("scalapb-runtime"))
     Compile / unmanagedResourceDirectories += (LocalRootProject / baseDirectory).value / "protobuf",
     scalacOptions ++= (if (!isScala3.value)
                          Seq(
-                           "-P:silencer:globalFilters=avaGenerateEqualsAndHash in class .* is deprecated",
                            "-P:silencer:lineContentFilters=import scala.collection.compat._"
                          )
                        else Nil),
@@ -430,8 +429,7 @@ lazy val e2e = (projectMatrix in file("e2e"))
   .settings(
     scalacOptions ++= (if (!isScala3.value)
                          Seq(
-                           "-P:silencer:globalFilters=value deprecatedInt32 in class TestDeprecatedFields is deprecated",
-                           "-P:silencer:pathFilters=custom_options_use;CustomAnnotationProto.scala;TestDeprecatedFields.scala",
+                           "-P:silencer:pathFilters=custom_options_use;CustomAnnotationProto.scala",
                            "-P:silencer:lineContentFilters=import com.thesamet.pb.MisplacedMapper.weatherMapper"
                          )
                        else Nil),
diff --git a/compiler-plugin/src/main/scala/scalapb/compiler/DescriptorImplicits.scala b/compiler-plugin/src/main/scala/scalapb/compiler/DescriptorImplicits.scala
index cc8eca64b..9dcd68a2b 100644
--- a/compiler-plugin/src/main/scala/scalapb/compiler/DescriptorImplicits.scala
+++ b/compiler-plugin/src/main/scala/scalapb/compiler/DescriptorImplicits.scala
@@ -551,8 +551,19 @@ class DescriptorImplicits private[compiler] (
         Nil
     }
 
+    def containsADeprecatedField = message.fields.exists(_.getOptions.getDeprecated)
+
+    private[this] def ignoreDeprecatedFieldsAnnotation: Option[String] = {
+      if (containsADeprecatedField)
+        Some(ProtobufGenerator.ignoreDeprecatedAnnotation)
+      else
+        None
+    }
+
     def annotationList: Seq[String] = {
-      deprecatedAnnotation ++ messageOptions.getAnnotationsList().asScala
+      deprecatedAnnotation ++ ignoreDeprecatedFieldsAnnotation.toList ++ messageOptions
+        .getAnnotationsList()
+        .asScala
     }
 
     def companionAnnotationList: Seq[String] = {
diff --git a/compiler-plugin/src/main/scala/scalapb/compiler/ProtobufGenerator.scala b/compiler-plugin/src/main/scala/scalapb/compiler/ProtobufGenerator.scala
index 123f04852..5b56ae9db 100644
--- a/compiler-plugin/src/main/scala/scalapb/compiler/ProtobufGenerator.scala
+++ b/compiler-plugin/src/main/scala/scalapb/compiler/ProtobufGenerator.scala
@@ -753,6 +753,7 @@ class ProtobufGenerator(
   def generateToJavaProto(message: Descriptor)(printer: FunctionalPrinter): FunctionalPrinter = {
     val myFullScalaName = message.scalaType.fullName
     printer
+      .when(message.containsADeprecatedField)(_.add(ProtobufGenerator.ignoreDeprecatedAnnotation))
       .add(s"def toJavaProto(scalaPbSource: $myFullScalaName): ${message.javaTypeName} = {")
       .indent
       .add(s"val javaPbOut = ${message.javaTypeName}.newBuilder")
@@ -767,6 +768,7 @@ class ProtobufGenerator(
   def generateFromJavaProto(message: Descriptor)(printer: FunctionalPrinter): FunctionalPrinter = {
     val myFullScalaName = message.scalaType.fullName
     printer
+      .when(message.containsADeprecatedField)(_.add(ProtobufGenerator.ignoreDeprecatedAnnotation))
       .add(
         s"def fromJavaProto(javaPbSource: ${message.javaTypeName}): $myFullScalaName = $myFullScalaName("
       )
@@ -948,27 +950,36 @@ class ProtobufGenerator(
       .indent
       .print(message.fields) { case (printer, field) =>
         val fieldName = field.scalaName.asSymbol
+
+        val deprecatedAnnotation: String = {
+          if (field.getOptions.getDeprecated) {
+            ProtobufGenerator.deprecatedAnnotation + " "
+          } else {
+            ""
+          }
+        }
+
         if (!field.isInOneof) {
           if (field.supportsPresence) {
             val optionLensName = "optional" + field.upperScalaName
             printer
               .add(
-                s"""def $fieldName: ${lensType(
+                s"""${deprecatedAnnotation}def $fieldName: ${lensType(
                     field.singleScalaTypeName
                   )} = field(_.${field.getMethod})((c_, f_) => c_.copy($fieldName = Option(f_)))
-                   |def ${optionLensName}: ${lensType(
+                   |${deprecatedAnnotation}def ${optionLensName}: ${lensType(
                     field.scalaTypeName
                   )} = field(_.$fieldName)((c_, f_) => c_.copy($fieldName = f_))""".stripMargin
               )
           } else
             printer.add(
-              s"def $fieldName: ${lensType(field.scalaTypeName)} = field(_.$fieldName)((c_, f_) => c_.copy($fieldName = f_))"
+              s"${deprecatedAnnotation}def $fieldName: ${lensType(field.scalaTypeName)} = field(_.$fieldName)((c_, f_) => c_.copy($fieldName = f_))"
             )
         } else {
           val oneofName = field.getContainingOneof.scalaName.nameSymbol
           printer
             .add(
-              s"def $fieldName: ${lensType(field.scalaTypeName)} = field(_.${field.getMethod})((c_, f_) => c_.copy($oneofName = ${field.oneOfTypeName
+              s"${deprecatedAnnotation}def $fieldName: ${lensType(field.scalaTypeName)} = field(_.${field.getMethod})((c_, f_) => c_.copy($oneofName = ${field.oneOfTypeName
                   .fullNameWithMaybeRoot(message)}(f_)))"
             )
         }
@@ -1759,6 +1770,9 @@ object ProtobufGenerator {
   val deprecatedAnnotation: String =
     """@scala.deprecated(message="Marked as deprecated in proto file", "")"""
 
+  val ignoreDeprecatedAnnotation: String =
+    """@scala.annotation.nowarn("cat=deprecation")"""
+
   private[scalapb] def escapeScalaString(raw: String): String =
     raw
       .map {
diff --git a/scalapb-runtime/src/main/js-native/com/google/protobuf/descriptor/FileOptions.scala b/scalapb-runtime/src/main/js-native/com/google/protobuf/descriptor/FileOptions.scala
index bc3885059..dfc0aca62 100644
--- a/scalapb-runtime/src/main/js-native/com/google/protobuf/descriptor/FileOptions.scala
+++ b/scalapb-runtime/src/main/js-native/com/google/protobuf/descriptor/FileOptions.scala
@@ -87,6 +87,7 @@ package com.google.protobuf.descriptor
   *   See the documentation for the "Options" section above.
   */
 @SerialVersionUID(0L)
+@scala.annotation.nowarn("cat=deprecation")
 final case class FileOptions(
     javaPackage: _root_.scala.Option[_root_.scala.Predef.String] = _root_.scala.None,
     javaOuterClassname: _root_.scala.Option[_root_.scala.Predef.String] = _root_.scala.None,
@@ -655,8 +656,8 @@ object FileOptions extends scalapb.GeneratedMessageCompanion[com.google.protobuf
     def optionalJavaOuterClassname: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Predef.String]] = field(_.javaOuterClassname)((c_, f_) => c_.copy(javaOuterClassname = f_))
     def javaMultipleFiles: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getJavaMultipleFiles)((c_, f_) => c_.copy(javaMultipleFiles = Option(f_)))
     def optionalJavaMultipleFiles: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.javaMultipleFiles)((c_, f_) => c_.copy(javaMultipleFiles = f_))
-    def javaGenerateEqualsAndHash: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getJavaGenerateEqualsAndHash)((c_, f_) => c_.copy(javaGenerateEqualsAndHash = Option(f_)))
-    def optionalJavaGenerateEqualsAndHash: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.javaGenerateEqualsAndHash)((c_, f_) => c_.copy(javaGenerateEqualsAndHash = f_))
+    @scala.deprecated(message="Marked as deprecated in proto file", "") def javaGenerateEqualsAndHash: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getJavaGenerateEqualsAndHash)((c_, f_) => c_.copy(javaGenerateEqualsAndHash = Option(f_)))
+    @scala.deprecated(message="Marked as deprecated in proto file", "") def optionalJavaGenerateEqualsAndHash: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.javaGenerateEqualsAndHash)((c_, f_) => c_.copy(javaGenerateEqualsAndHash = f_))
     def javaStringCheckUtf8: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getJavaStringCheckUtf8)((c_, f_) => c_.copy(javaStringCheckUtf8 = Option(f_)))
     def optionalJavaStringCheckUtf8: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.javaStringCheckUtf8)((c_, f_) => c_.copy(javaStringCheckUtf8 = f_))
     def optimizeFor: _root_.scalapb.lenses.Lens[UpperPB, com.google.protobuf.descriptor.FileOptions.OptimizeMode] = field(_.getOptimizeFor)((c_, f_) => c_.copy(optimizeFor = Option(f_)))
diff --git a/scalapb-runtime/src/main/scalajvm/com/google/protobuf/descriptor/FileOptions.scala b/scalapb-runtime/src/main/scalajvm/com/google/protobuf/descriptor/FileOptions.scala
index 7c4350afd..3fb5132de 100644
--- a/scalapb-runtime/src/main/scalajvm/com/google/protobuf/descriptor/FileOptions.scala
+++ b/scalapb-runtime/src/main/scalajvm/com/google/protobuf/descriptor/FileOptions.scala
@@ -88,6 +88,7 @@ import _root_.scalapb.internal.compat.JavaConverters._
   *   See the documentation for the "Options" section above.
   */
 @SerialVersionUID(0L)
+@scala.annotation.nowarn("cat=deprecation")
 final case class FileOptions(
     javaPackage: _root_.scala.Option[_root_.scala.Predef.String] = _root_.scala.None,
     javaOuterClassname: _root_.scala.Option[_root_.scala.Predef.String] = _root_.scala.None,
@@ -425,6 +426,7 @@ final case class FileOptions(
 
 object FileOptions extends scalapb.GeneratedMessageCompanion[com.google.protobuf.descriptor.FileOptions] with scalapb.JavaProtoSupport[com.google.protobuf.descriptor.FileOptions, com.google.protobuf.DescriptorProtos.FileOptions] {
   implicit def messageCompanion: scalapb.GeneratedMessageCompanion[com.google.protobuf.descriptor.FileOptions] with scalapb.JavaProtoSupport[com.google.protobuf.descriptor.FileOptions, com.google.protobuf.DescriptorProtos.FileOptions] = this
+  @scala.annotation.nowarn("cat=deprecation")
   def toJavaProto(scalaPbSource: com.google.protobuf.descriptor.FileOptions): com.google.protobuf.DescriptorProtos.FileOptions = {
     val javaPbOut = com.google.protobuf.DescriptorProtos.FileOptions.newBuilder
     scalaPbSource.javaPackage.foreach(javaPbOut.setJavaPackage)
@@ -450,6 +452,7 @@ object FileOptions extends scalapb.GeneratedMessageCompanion[com.google.protobuf
     javaPbOut.addAllUninterpretedOption(_root_.scalapb.internal.compat.toIterable(scalaPbSource.uninterpretedOption.iterator.map(com.google.protobuf.descriptor.UninterpretedOption.toJavaProto(_))).asJava)
     javaPbOut.build
   }
+  @scala.annotation.nowarn("cat=deprecation")
   def fromJavaProto(javaPbSource: com.google.protobuf.DescriptorProtos.FileOptions): com.google.protobuf.descriptor.FileOptions = com.google.protobuf.descriptor.FileOptions(
     javaPackage = if (javaPbSource.hasJavaPackage) Some(javaPbSource.getJavaPackage) else _root_.scala.None,
     javaOuterClassname = if (javaPbSource.hasJavaOuterClassname) Some(javaPbSource.getJavaOuterClassname) else _root_.scala.None,
@@ -709,8 +712,8 @@ object FileOptions extends scalapb.GeneratedMessageCompanion[com.google.protobuf
     def optionalJavaOuterClassname: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Predef.String]] = field(_.javaOuterClassname)((c_, f_) => c_.copy(javaOuterClassname = f_))
     def javaMultipleFiles: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getJavaMultipleFiles)((c_, f_) => c_.copy(javaMultipleFiles = Option(f_)))
     def optionalJavaMultipleFiles: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.javaMultipleFiles)((c_, f_) => c_.copy(javaMultipleFiles = f_))
-    def javaGenerateEqualsAndHash: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getJavaGenerateEqualsAndHash)((c_, f_) => c_.copy(javaGenerateEqualsAndHash = Option(f_)))
-    def optionalJavaGenerateEqualsAndHash: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.javaGenerateEqualsAndHash)((c_, f_) => c_.copy(javaGenerateEqualsAndHash = f_))
+    @scala.deprecated(message="Marked as deprecated in proto file", "") def javaGenerateEqualsAndHash: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getJavaGenerateEqualsAndHash)((c_, f_) => c_.copy(javaGenerateEqualsAndHash = Option(f_)))
+    @scala.deprecated(message="Marked as deprecated in proto file", "") def optionalJavaGenerateEqualsAndHash: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.javaGenerateEqualsAndHash)((c_, f_) => c_.copy(javaGenerateEqualsAndHash = f_))
     def javaStringCheckUtf8: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getJavaStringCheckUtf8)((c_, f_) => c_.copy(javaStringCheckUtf8 = Option(f_)))
     def optionalJavaStringCheckUtf8: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.javaStringCheckUtf8)((c_, f_) => c_.copy(javaStringCheckUtf8 = f_))
     def optimizeFor: _root_.scalapb.lenses.Lens[UpperPB, com.google.protobuf.descriptor.FileOptions.OptimizeMode] = field(_.getOptimizeFor)((c_, f_) => c_.copy(optimizeFor = Option(f_)))