summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ochsenreither <simon@ochsenreither.de>2012-07-31 01:02:07 +0200
committerJason Zaugg <jzaugg@gmail.com>2012-09-10 22:57:21 +0200
commite3b0c7abbf637dacce7bcd7b69d5655820e8e714 (patch)
tree392819cf24113b893c1622b5ecc80605bd34b3d6
parentadf2d3632b07eef4fc2303aef994e66584a73f49 (diff)
downloadscala-e3b0c7abbf637dacce7bcd7b69d5655820e8e714.tar.gz
scala-e3b0c7abbf637dacce7bcd7b69d5655820e8e714.tar.bz2
scala-e3b0c7abbf637dacce7bcd7b69d5655820e8e714.zip
SI-6162 Adds @deprecatedInheritance/@deprecatedOverriding
These annotations are meant to warn from inheriting a class or from overriding a member, due to the reasons given in `msg`. The naming and placement of the methods is in line with @deprecated and @deprecatedName.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
-rw-r--r--src/library/scala/deprecatedInheritance.scala20
-rw-r--r--src/library/scala/deprecatedOverriding.scala19
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala12
-rw-r--r--test/files/neg/t6162-inheritance.check4
-rw-r--r--test/files/neg/t6162-inheritance.flags1
-rw-r--r--test/files/neg/t6162-inheritance.scala4
-rw-r--r--test/files/neg/t6162-overriding.check4
-rw-r--r--test/files/neg/t6162-overriding.flags1
-rw-r--r--test/files/neg/t6162-overriding.scala8
12 files changed, 95 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 166bb2d18c..919250c562 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -430,6 +430,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
overrideError("cannot override a macro")
} else {
checkOverrideTypes()
+ checkOverrideDeprecated()
if (settings.warnNullaryOverride.value) {
if (other.paramss.isEmpty && !member.paramss.isEmpty) {
unit.warning(member.pos, "non-nullary method overrides nullary method")
@@ -508,6 +509,16 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
}
}
+
+ def checkOverrideDeprecated() {
+ if (other.hasDeprecatedOverridingAnnotation) {
+ val msg =
+ member.toString + member.locationString + " overrides " + other.toString + other.locationString +
+ ", but overriding this member is deprecated" +
+ other.deprecatedOverridingMessage.map(": " + _).getOrElse(".")
+ unit.deprecationWarning(member.pos, msg)
+ }
+ }
}
val opc = new overridingPairs.Cursor(clazz)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9cf5d42e00..df97e451d1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1577,6 +1577,15 @@ trait Typers extends Modes with Adaptations with Tags {
if (psym.isFinal)
pending += ParentFinalInheritanceError(parent, psym)
+ if (psym.hasDeprecatedInheritanceAnnotation) {
+ val sym = selfType.typeSymbol
+ val msg =
+ sym.toString + sym.locationString + " inherits from " + psym.toString + psym.locationString +
+ ", but inheriting from that class is deprecated" +
+ psym.deprecatedInheritanceMessage.map(": " + _).getOrElse(".")
+ unit.deprecationWarning(sym.pos, msg)
+ }
+
if (psym.isSealed && !phase.erasedTypes)
if (context.unit.source.file == psym.sourceFile)
psym addChild context.owner
diff --git a/src/library/scala/deprecatedInheritance.scala b/src/library/scala/deprecatedInheritance.scala
new file mode 100644
index 0000000000..c461f6737c
--- /dev/null
+++ b/src/library/scala/deprecatedInheritance.scala
@@ -0,0 +1,20 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2012, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+
+/** An annotation that designates that inheriting from a class is deprecated.
+ *
+ * This is usually done to warn about a non-final class being made final in a future version.
+ * Sub-classing such a class then generates a warning.
+ *
+ * @param message the message to print during compilation if the class was sub-classed
+ * @param since a string identifying the first version in which inheritance was deprecated
+ * @since 2.10
+ */
+class deprecatedInheritance(message: String = "", since: String = "") extends annotation.StaticAnnotation \ No newline at end of file
diff --git a/src/library/scala/deprecatedOverriding.scala b/src/library/scala/deprecatedOverriding.scala
new file mode 100644
index 0000000000..9048d5d32d
--- /dev/null
+++ b/src/library/scala/deprecatedOverriding.scala
@@ -0,0 +1,19 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2012, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala
+
+/** An annotation that designates that overriding a member is deprecated.
+ *
+ * Overriding such a member in a sub-class then generates a warning.
+ *
+ * @param message the message to print during compilation if the member was overridden
+ * @param since a string identifying the first version in which overriding was deprecated
+ * @since 2.10
+ */
+class deprecatedOverriding(message: String = "", since: String = "") extends annotation.StaticAnnotation \ No newline at end of file
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index c21ebfe997..556fcee64f 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -940,6 +940,8 @@ trait Definitions extends api.StandardDefinitions {
lazy val CloneableAttr = requiredClass[scala.annotation.cloneable]
lazy val DeprecatedAttr = requiredClass[scala.deprecated]
lazy val DeprecatedNameAttr = requiredClass[scala.deprecatedName]
+ lazy val DeprecatedInheritanceAttr = requiredClass[scala.deprecatedInheritance]
+ lazy val DeprecatedOverridingAttr = requiredClass[scala.deprecatedOverriding]
lazy val NativeAttr = requiredClass[scala.native]
lazy val RemoteAttr = requiredClass[scala.remote]
lazy val ScalaInlineClass = requiredClass[scala.inline]
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 3548657c04..e75079a6ff 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -697,6 +697,18 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def deprecationMessage = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 0)
def deprecationVersion = getAnnotation(DeprecatedAttr) flatMap (_ stringArg 1)
def deprecatedParamName = getAnnotation(DeprecatedNameAttr) flatMap (_ symbolArg 0)
+ def hasDeprecatedInheritanceAnnotation
+ = hasAnnotation(DeprecatedInheritanceAttr)
+ def deprecatedInheritanceMessage
+ = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 0)
+ def deprecatedInheritanceVersion
+ = getAnnotation(DeprecatedInheritanceAttr) flatMap (_ stringArg 1)
+ def hasDeprecatedOverridingAnnotation
+ = hasAnnotation(DeprecatedOverridingAttr)
+ def deprecatedOverridingMessage
+ = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 0)
+ def deprecatedOverridingVersion
+ = getAnnotation(DeprecatedOverridingAttr) flatMap (_ stringArg 1)
// !!! when annotation arguments are not literal strings, but any sort of
// assembly of strings, there is a fair chance they will turn up here not as
diff --git a/test/files/neg/t6162-inheritance.check b/test/files/neg/t6162-inheritance.check
new file mode 100644
index 0000000000..69112d7f86
--- /dev/null
+++ b/test/files/neg/t6162-inheritance.check
@@ -0,0 +1,4 @@
+t6162-inheritance.scala:4: error: class SubFoo inherits from class Foo, but inheriting from that class is deprecated: `Foo` will be made final in a future version.
+class SubFoo extends Foo
+ ^
+one error found \ No newline at end of file
diff --git a/test/files/neg/t6162-inheritance.flags b/test/files/neg/t6162-inheritance.flags
new file mode 100644
index 0000000000..65faf53579
--- /dev/null
+++ b/test/files/neg/t6162-inheritance.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -deprecation \ No newline at end of file
diff --git a/test/files/neg/t6162-inheritance.scala b/test/files/neg/t6162-inheritance.scala
new file mode 100644
index 0000000000..67bd4466c3
--- /dev/null
+++ b/test/files/neg/t6162-inheritance.scala
@@ -0,0 +1,4 @@
+@deprecatedInheritance("`Foo` will be made final in a future version.", "2.10.0")
+class Foo
+
+class SubFoo extends Foo \ No newline at end of file
diff --git a/test/files/neg/t6162-overriding.check b/test/files/neg/t6162-overriding.check
new file mode 100644
index 0000000000..14221ddc63
--- /dev/null
+++ b/test/files/neg/t6162-overriding.check
@@ -0,0 +1,4 @@
+t6162-overriding.scala:7: error: method bar in class SubBar overrides method bar in class Bar, but overriding this member is deprecated: `bar` will be made private in a future version.
+ override def bar = 43
+ ^
+one error found
diff --git a/test/files/neg/t6162-overriding.flags b/test/files/neg/t6162-overriding.flags
new file mode 100644
index 0000000000..65faf53579
--- /dev/null
+++ b/test/files/neg/t6162-overriding.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -deprecation \ No newline at end of file
diff --git a/test/files/neg/t6162-overriding.scala b/test/files/neg/t6162-overriding.scala
new file mode 100644
index 0000000000..4907dbb075
--- /dev/null
+++ b/test/files/neg/t6162-overriding.scala
@@ -0,0 +1,8 @@
+class Bar {
+ @deprecatedOverriding("`bar` will be made private in a future version.", "2.10.0")
+ def bar = 42
+}
+
+class SubBar extends Bar {
+ override def bar = 43
+} \ No newline at end of file