summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/api/Constants.scala
diff options
context:
space:
mode:
authorVlad Ureche <vlad.ureche@gmail.com>2012-10-10 09:59:12 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-10-11 20:06:39 +0200
commite8525254314627bd145d2093f0a1a0f3ca6a8067 (patch)
treec71e1040649b39d56eef350504b6277d2c68fa9c /src/reflect/scala/reflect/api/Constants.scala
parentb9e3d94604e20791317d9c7b1aa939e0bff6c945 (diff)
downloadscala-e8525254314627bd145d2093f0a1a0f3ca6a8067.tar.gz
scala-e8525254314627bd145d2093f0a1a0f3ca6a8067.tar.bz2
scala-e8525254314627bd145d2093f0a1a0f3ca6a8067.zip
scala.reflect.api.Constants documentation
Diffstat (limited to 'src/reflect/scala/reflect/api/Constants.scala')
-rw-r--r--src/reflect/scala/reflect/api/Constants.scala193
1 files changed, 111 insertions, 82 deletions
diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala
index 1f303877de..8c532bd4dd 100644
--- a/src/reflect/scala/reflect/api/Constants.scala
+++ b/src/reflect/scala/reflect/api/Constants.scala
@@ -6,114 +6,143 @@
package scala.reflect
package api
-/** A slice of [[scala.reflect.api.Universe the Scala reflection cake]] that defines compile-time constants and operations on them.
- * See [[scala.reflect.api.Universe]] for a description of how the reflection API is encoded with the cake pattern.
- *
- * According to the section 6.24 "Constant Expressions" of the Scala language specification,
- * certain expressions (dubbed ''constant expressions'') can be evaluated by the Scala compiler at compile-time.
- *
- * [[scala.reflect.api.Constants#Constant]] instances represent certain kinds of these expressions
- * (with values stored in the `value` field and its strongly-typed views named `booleanValue`, `intValue` etc.), namely:
- * 1. Literals of primitive value classes (bytes, shorts, ints, longs, floats, doubles, chars, booleans and voids).
- * 1. String literals.
- * 1. References to classes (typically constructed with [[scala.Predef#classOf]]).
- * 1. References to enumeration values.
- *
- * Such constants are used to represent literals in abstract syntax trees (the [[scala.reflect.api.Trees#Literal]] node)
- * and literal arguments for Java class file annotations (the [[scala.reflect.api.Annotations#LiteralArgument]] class).
- *
- * === Example ===
- *
- * The `value` field deserves some explanation. Primitive and string values are represented as themselves, whereas
- * references to classes and enums are a bit roundabout.
- *
- * Class references are represented as instances of [[scala.reflect.api.Types#Type]]
- * (because when the Scala compiler processes a class reference, the underlying runtime class might not yet have been compiled).
- * To convert such a reference to a runtime class, one should use the `runtimeClass` method of a mirror such as [[scala.reflect.api.Mirrors#RuntimeMirror]]
- * (the simplest way to get such a mirror is using [[scala.reflect.runtime.package#currentMirror]]).
- *
- * Enumeration value references are represented as instances of [[scala.reflect.api.Symbols#Symbol]], which on JVM point to methods
- * that return underlying enum values. To inspect an underlying enumeration or to get runtime value of a reference to an enum,
- * one should use a [[scala.reflect.api.Mirrors#RuntimeMirror]] (the simplest way to get such a mirror is again [[scala.reflect.runtime.package#currentMirror]]).
-
- * {{{
- * enum JavaSimpleEnumeration { FOO, BAR }
- *
- * import java.lang.annotation.*;
- * @Retention(RetentionPolicy.RUNTIME)
- * @Target({ElementType.TYPE})
- * public @interface JavaSimpleAnnotation {
- * Class<?> classRef();
- * JavaSimpleEnumeration enumRef();
- * }
- *
- * @JavaSimpleAnnotation(
- * classRef = JavaAnnottee.class,
- * enumRef = JavaSimpleEnumeration.BAR
- * )
- * public class JavaAnnottee {}
- * }}}
- * {{{
- * import scala.reflect.runtime.universe._
- * import scala.reflect.runtime.{currentMirror => cm}
- *
- * object Test extends App {
- * val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs
- * def jarg(name: String) = jann(newTermName(name)).asInstanceOf[LiteralArgument].value
- *
- * val classRef = jarg("classRef").typeValue
- * println(showRaw(classRef)) // TypeRef(ThisType(<empty>), JavaAnnottee, List())
- * println(cm.runtimeClass(classRef)) // class JavaAnnottee
- *
- * val enumRef = jarg("enumRef").symbolValue
- * println(enumRef) // value BAR
- *
- * val siblings = enumRef.owner.typeSignature.declarations
- * val enumValues = siblings.filter(sym => sym.isVal && sym.isPublic)
- * println(enumValues) // Scope{
- * // final val FOO: JavaSimpleEnumeration;
- * // final val BAR: JavaSimpleEnumeration
- * // }
- *
- * // doesn't work because of https://issues.scala-lang.org/browse/SI-6459
- * // val enumValue = mirror.reflectField(enumRef.asTerm).get
- * val enumClass = cm.runtimeClass(enumRef.owner.asClass)
- * val enumValue = enumClass.getDeclaredField(enumRef.name.toString).get(null)
- * println(enumValue) // BAR
- * }
- * }}}
+/**
+ * This trait is the [[scala.reflect.api.Universe reflection API]] component that mirrors constant irreducible expressions
+ * such as `true`, `0` and `classOf[List]`. Constant values appear in the program abstract syntax tree and in annotation parameters
+ * wrapped in [[Constant `Constant`]] case classes.
*/
trait Constants {
self: Universe =>
- /** The type of compile-time constants.
+ /**
+ * This "virtual" case class represents the reflection interface for literal expressions which can not be further
+ * broken down or evaluated, such as "true", "0", "classOf[List]". Such values become parts of the Scala abstract
+ * syntax tree representing the program. The constants
+ * correspond to section 6.24 "Constant Expressions" of the
+ * [[http://www.scala-lang.org/docu/files/ScalaReference.pdf Scala language specification]].
+ *
+ * Such constants are used to represent literals in abstract syntax trees (the [[scala.reflect.api.Trees#Literal]] node)
+ * and literal arguments for Java class file annotations (the [[scala.reflect.api.Annotations#LiteralArgument]] class).
+ *
+ * Constants can be matched against and can be constructed directly, as if they were case classes:
+ * {{{
+ * assert(Constant(true).value == true)
+ * Constant(true) match {
+ * case Constant(s: String) => println("A string: " + s)
+ * case Constant(b: Boolean) => println("A boolean value: " + b)
+ * case Constant(x) => println("Something else: " + x)
+ * }
+ * }}}
+ *
+ * `Constant` instances can wrap certain kinds of these expressions:
+ * 1. Literals of primitive value classes ([[scala.Byte `Byte`]], [[scala.Short `Short`]], [[scala.Int `Int`]], [[scala.Long `Long`]], [[scala.Float `Float`]], [[scala.Double `Double`]], [[scala.Char `Char`]], [[scala.Boolean `Boolean`]] and [[scala.Unit `Unit`]]) - represented directly as the corresponding type
+ * 1. String literals - represented as instances of the `String`.
+ * 1. References to classes, typically constructed with [[scala.Predef#classOf]] - represented as [[scala.reflect.api.Types#Type types]].
+ * 1. References to enumeration values - represented as [[scala.reflect.api.Symbols#Symbol symbols]].
+ *
+ * Class references are represented as instances of [[scala.reflect.api.Types#Type]]
+ * (because when the Scala compiler processes a class reference, the underlying runtime class might not yet have
+ * been compiled). To convert such a reference to a runtime class, one should use the [[scala.reflect.api.Mirrors#RuntimeMirror#runtimeClass `runtimeClass`]] method of a
+ * mirror such as [[scala.reflect.api.Mirrors#RuntimeMirror `RuntimeMirror`]] (the simplest way to get such a mirror is using
+ * [[scala.reflect.runtime#currentMirror `scala.reflect.runtime.currentMirror`]]).
+ *
+ * Enumeration value references are represented as instances of [[scala.reflect.api.Symbols#Symbol]], which on JVM point to methods
+ * that return underlying enum values. To inspect an underlying enumeration or to get runtime value of a reference to an enum,
+ * one should use a [[scala.reflect.api.Mirrors#RuntimeMirror]] (the simplest way to get such a mirror is again [[scala.reflect.runtime.package#currentMirror]]).
+ *
+ * Usage example:
+ * {{{
+ * enum JavaSimpleEnumeration { FOO, BAR }
+ *
+ * import java.lang.annotation.*;
+ * @Retention(RetentionPolicy.RUNTIME)
+ * @Target({ElementType.TYPE})
+ * public @interface JavaSimpleAnnotation {
+ * Class<?> classRef();
+ * JavaSimpleEnumeration enumRef();
+ * }
+ *
+ * @JavaSimpleAnnotation(
+ * classRef = JavaAnnottee.class,
+ * enumRef = JavaSimpleEnumeration.BAR
+ * )
+ * public class JavaAnnottee {}
+ * }}}
+ * {{{
+ * import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.{currentMirror => cm}
+ *
+ * object Test extends App {
+ * val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs
+ * def jarg(name: String) = jann(newTermName(name)) match {
+ * // Constant is always wrapped into a Literal or LiteralArgument tree node
+ * case LiteralArgument(ct: Constant) => value
+ * case _ => sys.error("Not a constant")
+ * }
+ *
+ * val classRef = jarg("classRef").value.asInstanceOf[Type]
+ * // ideally one should match instead of casting
+ * println(showRaw(classRef)) // TypeRef(ThisType(<empty>), JavaAnnottee, List())
+ * println(cm.runtimeClass(classRef)) // class JavaAnnottee
+ *
+ * val enumRef = jarg("enumRef").value.asInstanceOf[Symbol]
+ * // ideally one should match instead of casting
+ * println(enumRef) // value BAR
+ *
+ * val siblings = enumRef.owner.typeSignature.declarations
+ * val enumValues = siblings.filter(sym => sym.isVal && sym.isPublic)
+ * println(enumValues) // Scope{
+ * // final val FOO: JavaSimpleEnumeration;
+ * // final val BAR: JavaSimpleEnumeration
+ * // }
+ *
+ * // doesn't work because of https://issues.scala-lang.org/browse/SI-6459
+ * // val enumValue = mirror.reflectField(enumRef.asTerm).get
+ * val enumClass = cm.runtimeClass(enumRef.owner.asClass)
+ * val enumValue = enumClass.getDeclaredField(enumRef.name.toString).get(null)
+ * println(enumValue) // BAR
+ * }
+ * }}}
+ * @template
+ * @group Constants
*/
type Constant >: Null <: AnyRef with ConstantApi
/** A tag that preserves the identity of the `Constant` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ConstantTag: ClassTag[Constant]
- /** The constructor/deconstructor for `Constant` instances. */
+ /** The constructor/deconstructor for `Constant` instances.
+ * @group Extractors
+ */
val Constant: ConstantExtractor
/** An extractor class to create and pattern match with syntax `Constant(value)`
* where `value` is the Scala value of the constant.
+ * @group Extractors
*/
abstract class ConstantExtractor {
+ /** A factory method that produces [[Constant `Constant`]] instances.
+ *
+ * Notice that not any value can be passed to a constant: it must be either a primitive, a `String`, a
+ * [[scala.reflect.api.Types#Type type]] or a [[scala.reflect.api.Symbols#Symbol symbol]].
+ * See [[Constant the `Constant` class]] for more information.
+ */
def apply(value: Any): Constant
+ /** An extractor that enables writing pattern matches against the [[Constant `Constant`]] class. */
def unapply(arg: Constant): Option[Any]
}
- /** The API of `Constant` instances.
- * The main source of information about constants is the [[scala.reflect.api.Constants]] page.
+ /** The API of [[Constant]] instances.
+ * @group API
*/
abstract class ConstantApi {
- /** Payload of the constant. */
+ /** Payload of the constant, that can be accessed directly or pattern matched against. */
val value: Any
- /** Scala type that describes the constant. */
+ /** Scala type that describes the constant. It is generated automatically based on the type of the value. */
def tpe: Type
}
}