summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorSimon Ochsenreither <simon@ochsenreither.de>2012-09-17 13:45:43 +0200
committerSimon Ochsenreither <simon@ochsenreither.de>2012-09-21 18:20:35 +0200
commit990b3c7682d9b0655518e20274673aade75dbed0 (patch)
tree5850654506a86fdf3ec63446d7b2008cbe6c4c09 /src/reflect
parentb0a4d536482c6582bafb383a30f553862aceb00f (diff)
downloadscala-990b3c7682d9b0655518e20274673aade75dbed0.tar.gz
scala-990b3c7682d9b0655518e20274673aade75dbed0.tar.bz2
scala-990b3c7682d9b0655518e20274673aade75dbed0.zip
SI-6380 #1 Add @throws[Exception]
This change allows an additional notation of the @throws annotation: Old-style: @throws(classOf[Exception]) New-style: @throws[Exception] The optional String argument moves @throws in line with @deprecated, @migration, etc. and prevents confusion caused by the default inheritance of ScalaDoc comments and the non-inheritance of annotations. Before: /** This method does ... * @throws IllegalArgumentException if `a` is less than 0. */ @throws(classOf[IllegalArgumentException]) def foo(a: Int) = ... Now: /** This method does ... */ @throws[IllegalArgumentException]("if `a` is less than 0") def foo(a: Int) = ... ScalaDoc @throws tags remain supported for cases where documentation of thrown exceptions is needed, but are not supposed to be added to the exception attribute of the class file. In this commit the necessary compiler support is added. The code to extract exceptions from annotations is now shared instead of being duplicated all over the place. The change is completely source and binary compatible, except that the code is now enforcing that the type thrown is a subtype of Throwable as mandated by the JVM spec instead of allowing something like @throws(classOf[String]). Not in this commit: - ScalaDoc support to add the String argument to ScalaDoc's exception list - Adaption of the library
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala21
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala2
2 files changed, 21 insertions, 2 deletions
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index 3bd7f4f4fa..46e4329b2e 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -30,7 +30,7 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
/** Symbols of any @throws annotations on this symbol.
*/
def throwsAnnotations(): List[Symbol] = annotations collect {
- case AnnotationInfo(tp, Literal(Constant(tpe: Type)) :: Nil, _) if tp.typeSymbol == ThrowsClass => tpe.typeSymbol
+ case ThrownException(exc) => exc
}
/** Tests for, get, or remove an annotation */
@@ -325,4 +325,23 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
implicit val AnnotationTag = ClassTag[AnnotationInfo](classOf[AnnotationInfo])
object UnmappableAnnotation extends CompleteAnnotationInfo(NoType, Nil, Nil)
+
+ /** Extracts symbol of thrown exception from AnnotationInfo.
+ *
+ * Supports both “old-style” `@throws(classOf[Exception])`
+ * as well as “new-stye” `@throws[Exception]("cause")` annotations.
+ */
+ object ThrownException {
+ def unapply(ann: AnnotationInfo): Option[Symbol] =
+ ann match {
+ case AnnotationInfo(tpe, _, _) if tpe.typeSymbol != ThrowsClass =>
+ None
+ // old-style: @throws(classOf[Exception]) (which is throws[T](classOf[Exception]))
+ case AnnotationInfo(_, List(Literal(Constant(tpe: Type))), _) =>
+ Some(tpe.typeSymbol)
+ // new-style: @throws[Exception], @throws[Exception]("cause")
+ case AnnotationInfo(TypeRef(_, _, args), _, _) =>
+ Some(args.head.typeSymbol)
+ }
+ }
}
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 48a658192b..9eb20eb6ae 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -948,7 +948,7 @@ trait Definitions extends api.StandardDefinitions {
lazy val ScalaNoInlineClass = requiredClass[scala.noinline]
lazy val SerialVersionUIDAttr = requiredClass[scala.SerialVersionUID]
lazy val SpecializedClass = requiredClass[scala.specialized]
- lazy val ThrowsClass = requiredClass[scala.throws]
+ lazy val ThrowsClass = requiredClass[scala.throws[_]]
lazy val TransientAttr = requiredClass[scala.transient]
lazy val UncheckedClass = requiredClass[scala.unchecked]
lazy val UnspecializedClass = requiredClass[scala.annotation.unspecialized]