Skip to content

Commit

Permalink
Merge pull request #10517 from kapunga/12845-use-java-deprecation
Browse files Browse the repository at this point in the history
Always respect java.lang.Deprecated annotation
  • Loading branch information
lrytz committed Dec 20, 2023
2 parents 85fa13d + 6280a5b commit 97c2515
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 8 deletions.
8 changes: 6 additions & 2 deletions src/compiler/scala/tools/nsc/typechecker/Typers.scala
Expand Up @@ -4180,7 +4180,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper

if (hasError) ErroneousAnnotation
else if (unmappable) UnmappableAnnotation
else AnnotationInfo(annType, Nil, nvPairs.map(p => (p._1, p._2.get))).setOriginal(Apply(typedFun, namedArgs).setPos(ann.pos))
else {
if (annTypeSym == JavaDeprecatedAttr && !context.unit.isJava && settings.lintDeprecation)
context.warning(ann.pos, """Prefer the Scala annotation over Java's `@Deprecated` to provide a message and version: @deprecated("message", since = "MyLib 1.0")""", WarningCategory.LintDeprecation)
AnnotationInfo(annType, Nil, nvPairs.map(p => (p._1, p._2.get))).setOriginal(Apply(typedFun, namedArgs).setPos(ann.pos))
}
}
}
@inline def statically = {
Expand Down Expand Up @@ -4230,7 +4234,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
info.args.exists(treeInfo.isDefaultGetter)
}
if (annTypeSym == DeprecatedAttr && settings.lintDeprecation && argss.head.lengthIs < 2 && usesDefault)
context.warning(ann.pos, """Specify both message and version: @deprecated("message", since = "1.0")""", WarningCategory.LintDeprecation)
context.warning(ann.pos, """Specify both message and version: @deprecated("message", since = "MyLib 1.0")""", WarningCategory.LintDeprecation)
info
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/library/scala/deprecated.scala
Expand Up @@ -40,6 +40,9 @@ import scala.annotation.meta._
* // warning: there were three deprecation warnings in total; re-run with -deprecation for details
* }}}
*
* The Scala compiler also warns about using definitions annotated with [[java.lang.Deprecated]]. However it is
* recommended to use the Scala `@deprecated` annotation in Scala code because it allows providing a deprecation message.
*
* '''`@deprecated` in the Scala language and its standard library'''<br/>
*
* A deprecated element of the Scala language or a definition in the Scala standard library will
Expand Down
2 changes: 1 addition & 1 deletion src/reflect/scala/reflect/internal/Symbols.scala
Expand Up @@ -900,7 +900,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
@tailrec
final def isStrictFP: Boolean = this != NoSymbol && !isDeferred && (hasAnnotation(ScalaStrictFPAttr) || originalOwner.isStrictFP)
def isSerializable = info.baseClasses.exists(_ == SerializableClass)
def isDeprecated = hasAnnotation(DeprecatedAttr) || (isJava && hasAnnotation(JavaDeprecatedAttr))
def isDeprecated = hasAnnotation(DeprecatedAttr) || hasAnnotation(JavaDeprecatedAttr)
def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0)
def deprecationVersion = getAnnotation(DeprecatedAttr).flatMap(_.stringArg(1)) match {
case v @ Some(_) => v
Expand Down
4 changes: 2 additions & 2 deletions test/files/neg/deprecated.check
@@ -1,7 +1,7 @@
deprecated.scala:5: warning: Specify both message and version: @deprecated("message", since = "1.0")
deprecated.scala:5: warning: Specify both message and version: @deprecated("message", since = "MyLib 1.0")
@deprecated def f = ???
^
deprecated.scala:9: warning: Specify both message and version: @deprecated("message", since = "1.0")
deprecated.scala:9: warning: Specify both message and version: @deprecated("message", since = "MyLib 1.0")
@deprecated("Don't use it."/*, forRemoval=true*/) def stale = ???
^
deprecated.scala:21: warning: method f in trait T is deprecated
Expand Down
4 changes: 2 additions & 2 deletions test/files/neg/t12648.check
@@ -1,10 +1,10 @@
LogConfig_2.scala:7: warning: value MESSAGE_FORMAT_VERSION_CONFIG in class TopicConfig_1 is deprecated
val MessageFormatVersionPropX = TopicConfig_1.MESSAGE_FORMAT_VERSION_CONFIG
^
LogConfig_2.scala:10: warning: Specify both message and version: @deprecated("message", since = "1.0")
LogConfig_2.scala:10: warning: Specify both message and version: @deprecated("message", since = "MyLib 1.0")
@deprecated("3.0")
^
LogConfig_2.scala:12: warning: Specify both message and version: @deprecated("message", since = "1.0")
LogConfig_2.scala:12: warning: Specify both message and version: @deprecated("message", since = "MyLib 1.0")
@deprecated("3.0") @nowarn("cat=deprecation")
^
LogConfig_2.scala:12: warning: @nowarn annotation does not suppress any warnings
Expand Down
9 changes: 9 additions & 0 deletions test/files/neg/t12845.check
@@ -0,0 +1,9 @@
t12845.scala:4: warning: Prefer the Scala annotation over Java's `@Deprecated` to provide a message and version: @deprecated("message", since = "MyLib 1.0")
@Deprecated def f = 0
^
t12845.scala:6: warning: method f in object O is deprecated
class C { def g = O.f }
^
error: No warnings can be incurred under -Werror.
2 warnings
1 error
6 changes: 6 additions & 0 deletions test/files/neg/t12845.scala
@@ -0,0 +1,6 @@
//> using options -Werror -deprecation -Xlint

object O {
@Deprecated def f = 0
}
class C { def g = O.f }
4 changes: 4 additions & 0 deletions test/files/run/t9529.check
@@ -1,4 +1,5 @@
#partest java8
warning: 1 deprecation; re-run with -deprecation for details
A: List()
B: List(@java.lang.Deprecated())
C: List(@anns.Ann_0(name=C, value=see))
Expand All @@ -16,6 +17,7 @@ u: List(@anns.Ann_0$Container(value=[@anns.Ann_0(name=u, value=you), @anns.Ann_0
List(@anns.Ann_0$Container(value=[@anns.Ann_0(name=<init>, value=constructor), @anns.Ann_0(name=<init>, value=initializer)]))

#partest java11
warning: 1 deprecation; re-run with -deprecation for details
A: List()
B: List(@java.lang.Deprecated(forRemoval=false, since=""))
C: List(@anns.Ann_0(name="C", value="see"))
Expand All @@ -33,6 +35,7 @@ u: List(@anns.Ann_0$Container(value={@anns.Ann_0(name="u", value="you"), @anns.A
List(@anns.Ann_0$Container(value={@anns.Ann_0(name="<init>", value="constructor"), @anns.Ann_0(name="<init>", value="initializer")}))

#partest java17
warning: 1 deprecation; re-run with -deprecation for details
A: List()
B: List(@java.lang.Deprecated(forRemoval=false, since=""))
C: List(@anns.Ann_0(name="C", value="see"))
Expand All @@ -50,6 +53,7 @@ u: List(@anns.Ann_0$Container({@anns.Ann_0(name="u", value="you"), @anns.Ann_0(n
List(@anns.Ann_0$Container({@anns.Ann_0(name="<init>", value="constructor"), @anns.Ann_0(name="<init>", value="initializer")}))

#partest java20+
warning: 1 deprecation; re-run with -deprecation for details
A: List()
B: List(@java.lang.Deprecated(forRemoval=false, since=""))
C: List(@anns.Ann_0(name="C", value="see"))
Expand Down
1 change: 1 addition & 0 deletions test/files/run/t9644.check
@@ -0,0 +1 @@
warning: 3 deprecations; re-run with -deprecation for details
1 change: 1 addition & 0 deletions test/files/run/t9644b.check
@@ -0,0 +1 @@
warning: 3 deprecations; re-run with -deprecation for details
2 changes: 1 addition & 1 deletion test/junit/scala/tools/nsc/reporters/WConfTest.scala
Expand Up @@ -90,7 +90,7 @@ class WConfTest extends BytecodeTesting {
|}
|""".stripMargin

val l2 = (2, "Specify both message and version: @deprecated(\"message\", since = \"1.0\")")
val l2 = (2, "Specify both message and version: @deprecated(\"message\", since = \"MyLib 1.0\")")
val l5a = (5, "method f in class A is deprecated")
val l5b = (5, "method g in class A is deprecated")
val l7 = (7, "reflective access of structural type member method f should be enabled")
Expand Down

0 comments on commit 97c2515

Please sign in to comment.